/* This file is part of the Project Athena Zephyr Notification System.
 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
 * $Source: /mit/zephyr/src/zwgc/RCS/eval.c,v $
 * $Author: marc $
 *
 *	Copyright (c) 1988 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */
#include <zephyr/mit-copyright.h>
#ifndef lint
static char rcsid[] = "$Header: eval.c,v 2.10 89/04/26 13:28:13 marc Exp $";
#endif lint

#include "ropes.h"
#include "comp_types.h"
#ifdef X11
#include <X11/Xlib.h>
#else
typedef int Window;
#endif

rope *pop_match();
char *rop_prt();

void xtx_map_draw(), xtx_ring_bell();
char *malloc();
Window eval_show();

void rop_debug();

arg_foo(rp)
     rope *rp;
{
  rop_debug(rp,0);
}
/*
 * We will be getting things like
 *
 *      ROPE[
 *     		COMMAND[DOES]
 *	     	ROPE[
 *     			HEAD[7]		-- $opcode
 *     			END.
 * 	    	]
 *     		ROPE[
 *     			COMMAND[MATCH]
 *     			ROPE[
 *     				RAW[38]:<PING>
 *     				END.
 *     			]
 *     			ROPE[
 *     				COMMAND[EXIT]
 *     				END.
 *     			]
 *     			END.
 *     		]
 *     		END.
 *     	]
 * 
 */
#define MRSTK 128
rope *ropestack[MRSTK];
int ropesptr;			/* initialize to 0 */

push_match(rp)
     rope *rp;
{
  /*
   * save the rope handed here onto top of a stack...
   */
  ropestack[ropesptr++] = rp;
  if(ropesptr >= MRSTK)
    {
      printf("zwgc:eval Stack Overfull, squishing...\n");
      ropesptr --;
    }
}

rope *pop_match()
{
  /*
   * save the rope handed here onto top of a stack...
   */
  if(ropesptr > 0)
    {
      return(ropestack[--ropesptr]);
    }
  printf("zwgc:eval rope Stack Empty, reusing...\n");
  return(ropestack[ropesptr]);
}
/* from ropes.c ... */
#define FAILURE TRUE
#define SUCCESS FALSE

int if_match(rp)
     rope *rp;
{
  /*
   * Check if the rope handed in matches the one on the top
   * of the stack. return TRUE or FALSE.
   */
  if(ropcmp(rp, ropestack[ropesptr-1]) == SUCCESS)
    return(TRUE);
  else
    return(FALSE);
}

#include "eval_stat.h"

Window ne_set_show;
char *ne_set_summ;

void new_eval_map()
{
  xtx_map_draw(ne_set_show, ne_set_summ);
  free(ne_set_summ);
  ne_set_summ = NULL;
  ne_set_show = 0;
}

int new_eval(rp, stat)
     rope *rp;
     int stat;
{
  int done=0;
  
  while(!done)
    {
      if(rp->typ==END)
	{
	  return(stat);
	}
      if(rp->typ==ROPE)
	{
	  stat = new_eval(rp->ind.next,stat);
	  if(NE_IS_DONE(stat))
	    {
	      return(stat);
	    }
	  rp++;
	  continue;
	}
      if(rp->typ==NEXT)
	{
	  rp = rp->ind.next;
	  continue;
	}
      switch(rp->ind.ex)
	{
	case CMD_DOES:
	  rp++;
	  push_match(rp->ind.next); rp++;
	  for(;rp->typ!=END;rp++)
	    {
	      if(rp->typ == NEXT)
		{
		  rp = rp->ind.next;
		  continue;	/* keep processing the rope */
		}
	      stat = new_eval(rp->ind.next,stat);
	      if(NE_IS_DONE(stat))
		{
		  (void) pop_match();
		  return(stat);
		}
	    }
	  (void) pop_match();	/* done if_matching... */
	  return(stat);
	  break;
	case CMD_MATCH:
	  rp++;
	  if(if_match(rp->ind.next) == TRUE)
	    {
	      rp++;
	      for(;rp->typ!=END;rp++)
		{
		  if(rp->typ == NEXT)
		    {
		      rp = rp->ind.next;
		      continue;	/* keep processing the rope */
		    }
		  stat = new_eval(rp->ind.next, stat);
		  if(NE_IS_DONE(stat))
		    return(stat);
		}
	      return(stat);
	    }
	  else
	    {
	      return(stat);
	    }
	  break;
	case CMD_SHOW:
	  rp++;
	  if(NE_CAN_SHOW(stat))
	    {
	      ne_set_show = eval_show(rp->ind.next); /* ROPE unit */
	      stat |= NE_SHOW;
	      if(NE_CAN_MAP(stat)) new_eval_map();
	    }
	  return(stat);
	  break;

	case CMD_SUMMARY:
	  if(!NE_IS_SUMM(stat))
	    {
	      ne_set_summ = rop_prt((++rp)->ind.next);
	      stat |= NE_SUMM;
	      if(NE_CAN_MAP(stat)) new_eval_map();
	    }
	  return(stat);

	case CMD_ENDDOES:
	case CMD_ENDMATCH:
	case CMD_ENDSHOW:
	  return(stat);		/* weird... */
	  break;
	  
	case CMD_FIELDS:
	  rp++;
	  {
	    int i;
	    rope *rl = rp->ind.rope, *ropinit();
	    
	    for(i=0; rl->typ != END; i++, rl++)
	      {
		if(rl->typ == NEXT)
		  {
		    rl = rl->ind.next;
		    i--; rl--;
		    continue;
		  }
		/* strand_var[rl->ind.ex] = strand_field[i]; */
		varropes[rl->ind.ex] = ropinit(ROPE_SIZE);
		{
		  rope elem, *bld;
		  bld = varropes[rl->ind.ex];

		  elem.typ = FIELD;
		  elem.ind.ex = i;

		  ropappend(bld, elem, ROPE_SIZE);

		  elem.typ = ROPE;
		  elem.ind.rope = varropes[rl->ind.ex];
		  ropappend(fieldrp, elem, ROPE_SIZE);
		}
	      }			/* deal with excess later */
	  }
	  return(stat);
	  break;		
	case CMD_SET:
	  rp++;
	  /* strand_var[rp->ind.rope[0].ind.ex] = rop_prt(&rp->ind.rope[1]); */
	  if(rp->ind.rope[0].typ != VAR)
	    {
	      printf("zwgc:eval arg of SET not VAR\n");
	      abort();
	    }
	  varropes[rp->ind.rope[0].ind.ex] = &rp->ind.rope[1];
	  return(stat);
	  break;
	case CMD_EXEC:
	  if(!NE_IS_EXIT(stat))
	  {
	    char *x = rop_prt(++rp);
	    char *prs = malloc(strlen(x)+sizeof("()&"));
	    sprintf(prs, "(%s)&", x);
	    system(prs);
	    free(x);
	    free(prs);
	  }
	  return(stat);
	  break;
	case CMD_EXIT:
	  stat |= NE_EXIT;
	  return(stat);
	  break;
	  
	case CMD_BUTTON:
	  return(stat);
	  break;

	case CMD_BEEP:
	  xtx_ring_bell();	/* optional arg parsed here later... */
	  return(stat);
	  break;
	default:
	  stat = NE_ERR;
	  return(stat);
	  break;
	}
    }
  return(stat);
}
