/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: elib.c,v $
 * Revision 2.11  1993/01/18  18:04:54  lotos
 * distribution issues
 *
 * Revision 2.10  1992/10/14  19:20:19  lotos
 * check contents of annotations: empty, nonempty, one word
 *
 * Revision 2.9  1992/10/14  18:37:02  lotos
 * check consistency of combinations of annotations
 *
 * Revision 2.8  1992/09/11  15:03:08  lotos
 * default is no longer a special case
 *
 * Revision 2.7  1992/09/02  14:47:27  lotos
 * keep annotations as independent (and sorted!) nodes in AST
 *
 * Revision 2.6  92/01/14  15:22:47  lotos
 * distribution issues
 *
 * Revision 2.5  92/01/10  15:01:09  lotos
 * mark as "implicit true" those asts that are simplified syntactically
 *
 * Revision 2.4  91/08/28  15:53:35  lotos
 * colour 'default' may be duplicated, getting into a STRlist
 *
 * Revision 2.3  91/02/28  17:17:51  lotos
 * rule 'premiss ::= _value_expression' removed
 * consequences: colours c_bool, c_rectrue, c_true removed
 * unique identifier per class generated
 *
 *
 * Revision 2.2  90/10/31  07:53:29  lotos
 * prefer local version of grc.h
 *
 * Revision 2.1  90/10/30  14:12:37  lotos
 * compressed AST
 * use of hardwired colours
 * compressed value expressions
 * annotations to colours
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: elib.c,v 2.11 1993/01/18 18:04:54 lotos Exp $";
#endif

# include "swbus.h"
# include "grc.h"

# define pop(L) L->elt; L= L->next

PRIVATE IT* glist= NULL;

PUBLIC	int
validexc (key, vclrs)
     int key;
     INTlist vclrs;
{
  int elt;

  while (vclrs != NULL) {
    elt= pop (vclrs);
    if (elt == key)
      return TRUE;
  }
  return FALSE;
}

PUBLIC void
putexc (to, ndexc)
     TNODE* to;
     TNODE* ndexc;
{
  INTlist kl;
  STRlist vl;
  int kc;
  char* vc;
  TATTR* att;

  kl= (INTlist)(find_attr(c_keylist, ndexc)->value);
  vl= (STRlist)(find_attr(c_vallist, ndexc)->value);
  while (kl != nil (INTlist)) {
    kc= INThead(kl);  kl= INTtail(kl);
    vc= STRhead(vl);  vl= STRtail(vl);
    att= add_attr(kc, to);
    if (att == NULL) {
      report (ndexc, c_line);
      (void) fprintf (stderr,
		      "annotation %s repeated\n",
		      type2clr(kc)->keyword);
      continue;
    }
    att->value= (CLR_TYPE)vc;
  }
}

PUBLIC	TNODE*
tv1	(vorig, tree)
	TNODE*	vorig;
	TNODE*	tree;
{
	int*	grlv;
	int*	grlt;
	int	i;

  if (glist == NULL)
      glist= ITcreate (4, 2, 1);
  glist->size= 0;
  grlt= grnl->data[(int)(tree->value0)];
  for (i= 0; grlt[i] != 0; i++)
       (void)ITadd(grlt[i], glist);
  grlv= grnl->data[(int)(vorig->value0)];
  for (i= 1; grlv[i] != 0; i++)
       (void)ITadd(grlv[i], glist);
  tree->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  return tree;
}


PUBLIC	TNODE*
tv2	(vorig, value, term, lexv, line, infix)
	TNODE*	vorig;
	TNODE*	value;
	TNODE*	term;
	int	lexv;
	int*	line;
	int	infix;
{
	TNODE*	nd;
	int*	grl;
	int	i;

  nd= new_node(tvalue_expression);
  if (glist == NULL)
      glist= ITcreate (4, 2, 1);
  glist->size= 0;
  (void)ITadd(_value_expression_1, glist);
  grl= grnl->data[(int)(vorig->value0)];
  for (i= 1; grl[i] != 0; i++)
       (void)ITadd(grl[i], glist);
  nd->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  nd->value1= (CLR_TYPE)1;
  nd->sons= value;
  value->father= nd;
  value->brothers= term;
  term->father= nd;
  set_attr(c_lexv, nd, (CLR_TYPE)lexv);
  set_attr(c_line, nd, (CLR_TYPE)line);
  set_attr(c_infix, nd, (CLR_TYPE)infix);
  return nd;
}

PUBLIC  TNODE*
tt1     (term, lexv, line, ofsort)
	TNODE*	term;
	int	lexv;
	int*	line;
	int	ofsort;
{
	TNODE*	nd;
	int*	grl;
	int	i;

  nd= new_node(tvalue_expression);
  if (glist == NULL)
    glist= ITcreate (4, 2, 1);
  glist->size= 0;
  (void)ITadd(_value_expression_1, glist);
  grl= grnl->data[(int)(term->value0)];
  for (i= 1; grl[i] != 0; i++)
       (void)ITadd(grl[i], glist);
  nd->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  nd->value1= (CLR_TYPE)0;
  set_attr(c_lexv, nd, (CLR_TYPE)lexv);
  set_attr(c_line, nd, (CLR_TYPE)line);
  if (ofsort != -1)
    set_attr(c_ofsort, nd, (CLR_TYPE)ofsort);
  return nd;
}

PUBLIC  TNODE*
tt2     (term, list, lexv, line, ofsort)
	TNODE*	term;
	TNODE*	list;
	int	lexv;
	int*	line;
	int	ofsort;
{
	TNODE*	nd;
	int*	grl;
	int	i;

  nd= new_node(tvalue_expression);
  if (glist == NULL)
    glist= ITcreate (4, 2, 1);
  glist->size= 0;
  (void)ITadd(_value_expression_1, glist);
  grl= grnl->data[(int)(term->value0)];
  for (i= 1; grl[i] != 0; i++)
       (void)ITadd(grl[i], glist);
  nd->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  nd->value1= (CLR_TYPE)1;
  nd->sons= list;
  while (list != NULL) { list->father= nd; list= list->brothers; }
  set_attr(c_lexv, nd, (CLR_TYPE)lexv);
  set_attr(c_line, nd, (CLR_TYPE)line);
  if (ofsort != -1)
    set_attr(c_ofsort, nd, (CLR_TYPE)ofsort);
  return nd;
}

PUBLIC  TNODE*
tt3     (value, paren, ofsort)
	TNODE*	value;
	int	paren;
	int	ofsort;
{
	TATTR*	att;

  att= find_attr(c_paren, value);
  if (att != NULL)
    att->value= (CLR_TYPE) (paren-1);
  else
    set_attr(c_paren, value, (CLR_TYPE) (paren-1));
  att= find_attr(c_ofsort, value);
  if (ofsort != -1 && att != NULL && ofsort != (int)att->value) {
    report (value, c_line);
    (void) fprintf (stderr,
		    "different sorts assigned to the term expression\n");
  }
  if (att == NULL && ofsort != -1)
    set_attr(c_ofsort, value, (CLR_TYPE)ofsort);
  return value;
}

PUBLIC	TNODE*
tvl1	(list)
	TNODE*	list;
{
	TNODE*	tree;

  if (list != NULL){
    tree= (TNODE*)fdclr(c_tree, list, -1);
    tree->brothers= tvl1(list->brothers);
    return tree;
  }
  else
    return NULL;
}


PUBLIC	TNODE*
simple_eq (implicit, tree)
	TNODE*	implicit;
	TNODE*	tree;
{
	TNODE*	nd;
	int*	grl;
	int	i;

  nd= new_node (tsimple_equation);
  if (glist == NULL) glist= ITcreate (4, 2, 1);
  glist->size= 0;
  (void)ITadd(_simple_equation_1, glist);
  grl= grnl->data[(int)(implicit->value0)];
  if (grl[1] == premiss_2)
      (void)ITadd(premiss_1, glist);
  for (i= 2; grl[i] != 0; i++)
       (void)ITadd(grl[i], glist);
  nd->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  nd->value1= (CLR_TYPE)3;
  nd->sons= tree;
  tree->father= nd;
  set_attr(c_funny, nd, (CLR_TYPE)0);

  tree= new_node (tvalue_expression);
  glist->size= 0;
  (void)ITadd(_value_expression_1, glist);
  tree->value0= (CLR_TYPE)IAT_IT_add(glist, grnl);
  tree->value1= (CLR_TYPE)0;
  nd->sons->brothers= tree;
  tree->father= nd;
  tree->sons= NULL;
  tree->brothers= NULL;
  set_attr(c_lexv,
	   tree,
	   (CLR_TYPE)(STHadd("true", SymbolTable, hidtbl, FALSE)));
  set_attr (c_line, tree, find_attr (c_line, nd->sons)->value);
  set_attr (c_impt, tree, (CLR_TYPE)0);
  return nd;
}

PUBLIC void
excheck1 (nd)
  TNODE* nd;
{
  int state= 0;
  TNODE* n;

  for (n= nd; n != NULL; n= n->brothers) {
    switch (state) {
    case 0:
      if (find_attr (c_wait, n))
	break;
      if (find_attr (c_delay, n))
	break;
      if (find_attr (c_if, n))
	break;
      if (find_attr (c_priority, n)) {
	state= 1;
	break;
      }
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {wait|delay|if} [priority]\n");
      return;
    case 1:
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {wait|delay|if} [priority]\n");
      return;
    }
  }
  return;
}

PUBLIC void
excheck2 (nd)
  TNODE* nd;
{
  int state= 0;
  TNODE* n;

  for (n= nd; n != NULL; n= n->brothers) {
    switch (state) {
    case 0:
      if (find_attr (c_c, n))
	break;
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {C}\n");
      return;
    }
  }
  return;
}

PUBLIC void
excheck3 (nd)
  TNODE* nd;
{
  int state= 0;
  TNODE* n;

  for (n= nd; n != NULL; n= n->brothers) {
    switch (state) {
    case 0:
      if (find_attr (c_default, n)) {
	state= 1;
	break;
      }
      if (find_attr (c_use, n)) {
	state= 2;
	break;
      }
      if (find_attr (c_eval, n)) {
	state= 2;
	break;
      }
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {default} | [use] | [eval]\n");
      return;
    case 1:
      if (find_attr (c_default, n))
	break;
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {default} | [use] | [eval]\n");
      return;
    case 2:
      report (nd, c_line);
      (void) fprintf (stderr, "invalid annotation combination\n");
      (void) fprintf (stderr, "usage: {default} | [use] | [eval]\n");
      return;
    }
  }
  return;
}

PUBLIC void
check_empty (nd)
  TNODE* nd;
{
  char* val;

  for (val= (char*) fdclr (c_cval, nd, -1); *val != 0; val++)
    if (! isspace (*val)) {
      report (nd, c_line);
      (void) fprintf (stderr,
		      "annotation %s should be empty\n",
		      fdclr (c_ckey, nd, -1));
      return;
    }
}

PUBLIC void
check_nonempty (nd)
  TNODE* nd;
{
  char* val;

  for (val= (char*) fdclr (c_cval, nd, -1); *val != 0; val++)
    if (! isspace (*val))
      return;
  report (nd, c_line);
  (void) fprintf (stderr,
		  "annotation %s should not be empty\n",
		  fdclr (c_ckey, nd, -1));
}

PUBLIC void
check_one_word (nd)
  TNODE* nd;
{
  char* val;
  int state= 0;

  val= (char*) fdclr (c_cval, nd, -1);
  while (TRUE) {
    switch (state) {
    case 0:
      if (*val == 0) {
	report (nd, c_line);
	(void) fprintf (stderr,
			"annotation %s needs a name\n",
			fdclr (c_ckey, nd, -1));
	return;
      }
      if (!isspace (*val))
	state= 1;
      break;

    case 1:
      if (*val == 0)
	return;
      if (isspace (*val))
	state= 2;
      break;

    case 2:
      if (*val == 0)
	return;
      if (!isspace (*val)) {
	report (nd, c_line);
	(void) fprintf (stderr,
			"annotation %s needs a single name\n",
			fdclr (c_ckey, nd, -1));
	return;
      }
      break;

    }
    val++;
  }
}

