/*********************************************************
 *  symbol table manager
 *  a binary tree is used
 *********************************************************/
/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
$Log: symtab.c,v $
 * Revision 2.11  1993/01/18  18:10:59  lotos
 * distribution issues
 *
 * Revision 2.10  1993/01/12  20:19:56  lotos
 * portability issues
 *
 * Revision 2.9  1992/02/21  17:14:02  lotos
 * adapted to new lfe
 * better presentation of reports
 *
 * Revision 2.8  92/01/22  20:00:22  lotos
 * fixed bug w.r.t. the use of names in renaming and actualization
 * 
 * Revision 2.7  92/01/14  15:23:53  lotos
 * distribution issues
 * 
 * Revision 2.6  92/01/13  19:31:11  lotos
 * identification of names
 * adaption to phuscation
 * 
 * Revision 2.5  92/01/13  17:00:28  lotos
 * consider formal (sorts|operations)
 * 
 * Revision 2.4  91/02/28  19:31:02  lotos
 * adapted to lack of rule 'premiss ::= _value_expression'
 * adapted to information contained in AT
 * 
 * Revision 2.3  90/10/30  14:18:32  lotos
 * adapted to compressed CAST
 * 
 * Revision 2.2  90/06/04  10:38:06  lotos
 * unused items may be printed apart
 * 
 * Revision 2.1  90/06/01  15:08:00  lotos
 * handles identifier classification
 * and legends to qualify occurrences
 * 
 * Revision 1.3  90/03/16  17:50:58  lotos
 * check for redeclarations of identifiers is dropped
 * to cope with formal_* actualizations of TRUE
 * 
 * Revision 1.2  90/01/29  13:14:03  lotos
 * fixing license details
 * 
 * Revision 1.1  90/01/22  12:50:22  lotos
 * Initial revision
 * 
 ***********************************/

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

# include "swbus.h"

PRIVATE SNODE* tsroot= NULL;

PRIVATE char* coding[]= {
    "",
    "specification", 
    "type",
    "sort",
    "operation",
    "process",
    "gate",
    "value",
    "formal sort",
    "formal opn",
    "name"
  };


PRIVATE SNODE* 
new_tsnode (lexv, idclass, iddec)
     int lexv, idclass, iddec;
{
  SNODE* s;
  
  s= (SNODE*) emalloc (sizeof (SNODE));
  s->lexv= lexv;
  s->idclass= idclass;
  s->iddec= iddec;
  s->line= 0;
  s->refs= NULL;
  s->left= NULL;
  s->right= NULL;
  s->legend= NULL;
  s->aux_legend= NULL;
  return s;
}

PUBLIC char* emalloc (i)
  int i;
{
  char *p;

  p = malloc ((unsigned) i);
  if (p == NULL) {
    (void)fprintf (stderr, "Out of memory\n");
    exit (1);
  }
  return p;
}

PUBLIC INTlist
INT2cons (s1, s2, t)
  int s1, s2;
  INTlist t;
{
  return INTcons (s1, INTcons (s2, t));
}

PUBLIC int
mygetlexv (h)
  TNODE *h;
{
  if (find_attr (c_iddec, h) != NULL)
    return (int)ATable->data[(int)find_attr(c_iddec, h)->value].value1;
  if (find_attr (c_idref, h) != NULL)
    return (int)ATable->data[(int)find_attr(c_idref, h)->value].value1;
  if (find_attr (c_lexv, h) != NULL)
    return (int)find_attr (c_lexv, h)->value;
  (void) fprintf (stderr, "%s: iddec, idref, and lexv do not exit\n",
		  progname);
  drn_tree (h, 2);
  exit (1);
  return 0; /* to shut lint off */
}

PRIVATE void
addline (r, line)
     SNODE* r;
     int line;
{
  LNODE* l;
  LNODE* n;

  l= r->refs;
  if (l != NULL && line == l->line)
    return;
  if (l == NULL || line < l->line) {
    n= (LNODE*) emalloc (sizeof (LNODE));
    n->line= line;
    n->next= l;
    r->refs= n;
    return;
  }
  while (l->next != NULL && line > l->next->line)
    l= l->next;
  if (l->next != NULL && line == l->next->line)
    return;
  n= (LNODE*) emalloc (sizeof (LNODE));
  n->line= line;
  n->next= l->next;
  l->next= n;
}

/*
 Given a symbol entry,
 add a new line occurrence
 lines are introduced in normal order
*/
/* The idclass and iddec should be
   explicitally passed because this colours are evaluated by the
   ls2, so they do not exist in the AST built by the lfe or ls1.
   Actually, the ls1 evaluates these colours but only for types */

PUBLIC SNODE*
putid (lexv, idclass, iddec, idd, line, legend)
     int lexv, idclass, iddec, idd, line;
     INTlist legend;
{
  SNODE* p;
  SNODE* q;
  SNODE* n;
  int test= 1;

  if (tsroot == NULL)
      tsroot= new_tsnode (-1, 0, -1);

  p= tsroot;
  q= tsroot->right;
  
  while (q != NULL) {
    p= q;
    test= strcmp (SymbolTable->data[lexv], SymbolTable->data[q->lexv]);
          /* The only reason to compare between lexv as string is order */
          /* In this case, the items are printed in alphabetic order */
    if (test == 0) {
      test= idclass - q->idclass;
      if (test == 0)
	test= iddec - q->iddec;
    }
    if (test == 0){
      if (idd == c_iddec) {
         q->line = line;
         q->legend = legend;
      }
      else addline (q, line);
      return q;
    }
    if (test < 0)
      q= p->left;
    else
      q= p->right;
  }
				/* comes to this point if
				   lexv does not yet exist */
  n= new_tsnode (lexv, idclass, iddec);
  if (test > 0)
    p->right = n;
  else
    p->left = n;

  if (idd == c_iddec) {
     n->line = line;
     n->legend = legend;
  }
  else addline (n, line);
  return n;
}

/* pretty printer of the color legend */

PRIVATE void
print_legend (t)
     SNODE* t;
{
  INTlist np;

  for (np = t->legend; np != NULL; np = INTtail (np)) {
    if (INThead(np) >= 0)
      (void) printf (" %s", SymbolTable->data[INThead (np)]);
    else switch (INThead(np)) {
           case LEFT_ARROW : (void) printf(" ->"); break;
           case RIGTH_BRACKET : (void) printf (" ]"); break;
	   case LEFT_BRACKET : (void) printf (" ["); break;
	   case RIGTH_PAREN : (void) printf (" )"); break;
	   case LEFT_PAREN : (void) printf (" ("); break;
	   case COLON : (void) printf (" :"); break;
	   case COMMA : (void) printf (","); break;
	   case COLON_NOEXIT : (void) printf (" : noexit"); break;
	   case COLON_EXIT : (void) printf (" : exit"); break;
	   case EXIT_PAREN : (void) printf (" : exit ("); break;
	   default : (void) fprintf (stderr,
				     "Internal error: code not allowed\n");
	             exit (1);
    }
  }
}

/* Prints one or more lines per symbol */

PRIVATE void
print_item (t, only_nlines)
     SNODE* t;
     int    only_nlines;
{
  int i;
  LNODE* l;

  if ((t->iddec < 0) || (t->line == 0)) {
    (void) printf ("%s (%s):",
     SymbolTable->data[t->lexv],
     coding[t->idclass]);
     if (!only_nlines)
       print_legend (t);
     (void) printf("\n");
  }
  else {
    (void) printf ("%s (%s): %d; ",
     SymbolTable->data[t->lexv],
     coding[t->idclass],
     t->line);
     if (!only_nlines)
       print_legend (t);
     (void) printf("\n");
  }
  i= 10;
  for (l= t->refs; l != NULL; l= l->next) {
    if (i-- == 0) {
      (void) printf ("\n");
      i= 9;
    }
    (void) printf ("%6d",l->line);
  }
  (void) printf ("\n");
}
 
/*
   traverses the symbol table
   while printing each item
*/

PRIVATE void
traverse (t, item_not_used, only_nlines, e_gate, e_proc,
	  e_type, e_sort, e_spec, e_val, e_opn, e_fsrt,
	  e_fopn, e_name)
  SNODE* t;
  int item_not_used, only_nlines, e_gate, e_proc,
      e_type, e_sort, e_spec, e_val, e_opn, e_fsrt,
      e_fopn, e_name;
{
  while (t != NULL) {
    traverse (t->left, item_not_used, only_nlines,
	      e_gate, e_proc, e_type,
	      e_sort, e_spec, e_val,
	      e_opn, e_fsrt, e_fopn, e_name);
    if (
	(e_spec && (t->idclass == TSPEC))  ||
	(e_type && (t->idclass == TTYPE))  ||
	(e_sort && (t->idclass == TSORT))  ||
	(e_opn  && (t->idclass == TOPN))   ||
	(e_proc && (t->idclass == TPROC))  ||
	(e_gate && (t->idclass == TGATE))  ||
	(e_val  && (t->idclass == TVAL))   ||
	(e_fsrt && (t->idclass == TFSORT)) ||
	(e_fopn && (t->idclass == TFOPN))  ||
	(e_name && (t->idclass == TNAME))
	)		/* print is allowed */

      if (!item_not_used || (t->refs == NULL))		/* all the items or */
							/* items not used */
	print_item (t, only_nlines);
    t= t->right;
  }
}

PUBLIC void
print_ts (item_not_used, only_nlines, e_gate, e_proc,
	  e_type, e_sort, e_spec, e_val, e_opn, e_fsrt,
	  e_fopn, e_name)
  int item_not_used, only_nlines, e_gate, e_proc,
      e_type, e_sort, e_spec, e_val, e_opn, e_fsrt,
      e_fopn, e_name;
{
  traverse (tsroot->right, item_not_used, only_nlines, e_gate,
	    e_proc, e_type, e_sort, e_spec, e_val, e_opn, e_fsrt,
	    e_fopn, e_name);
}

