/* symbols.c */
/* author: Edward A. Green */
/* purpose: symbol table routines */

#include "proj3.h"

/**********************************************************/
/* SYMBOL TABLE ROUTINES */
/*************************/

BLOCK *make_block(BLOCK *blocks, char *s)
{
	BLOCK *blk;
	char   *strsave(char *subject);

	/* Generate the new block */
	if (NULL==(blk=(BLOCK *)malloc(sizeof(BLOCK))))
	  {
	  printf("no more room on allocation of block\n");
	  exit(1);
	  }

	if (NULL==(blk->table=(SYMTBL *)malloc(sizeof(SYMTBL))))
	    {
	    printf("no more room on allocation of sym_list(1)\n");
	    exit(1);
	    }
	blk->table->symbol=strsave(&s[3]);
	blk->table->symbol[strlen(blk->table->symbol)-1]='.';
	blk->table->offset=0;
	blk->table->mem=NULL;
	blk->table->stype=' ';
	blk->table->ctype=' ';
	blk->table->from=0;
	blk->table->to=0;
	blk->table->nparms=0;
	blk->table->next=NULL;
	blk->table->parms=NULL;

	blk->lead=NULL;

	/* Now add the block to the collection */
	if (blocks==NULL)
	  {
	  blk->next=blk;
	  blk->last=blk;
	  blocks=blk;
	  }
	else
	  {
	  blk->next=blocks;
	  blk->last=blocks->last;
	  blk->last->next=blk;
	  blocks->last=blk;
	  }

	return(blk);
}


void make_sym(BLOCK *blk, char *s, FILE *f)
{
	SYMTBL  *st;
	char    *sym;
	int     iparms ,nparms, i;
	char   *strsave(char *subject);

	/* Check for existance of symbol; add if not defined already */
	sym=strtok(s," ");
	sym=strtok(NULL," ");
	sym=strtok(NULL," ");
	st=blk->table;
	do
	  {
	  if (!strcmp(sym,st->symbol)) return;
	  if (st->next!=NULL) st=st->next;
	  }
	while (st->next != NULL);
	if (!strcmp(sym,st->symbol)) return;
	if (NULL==(st->next=(SYMTBL *)malloc(sizeof(SYMTBL))))
	  {
	  printf("no more room on allocation of sym_tbl\n");
	  exit(1);
	  }
	st=st->next;

	/* insert symbol name */
	st->symbol=strsave(sym);

	/* fill in default values */
	st->offset=0;
	st->mem=NULL;
	st->stype=' ';
	st->ctype='s';
	st->from=0;
	st->to=0;
	st->nparms=0;
	st->parms=NULL;
	st->next=NULL;

	/* ready next input field */
	sym=strtok(NULL," ");

	/* fill in fields which depend on symbol type */
	switch (s[1])
	  {
	  /* variables */
	  case 'V':

	    /* fill in symbol type for variables */
	    st->stype=sym[0];
	    sym=strtok(NULL," ");

            /* check for an array */
	    if (sym[0]=='[')
	      {
	      st->ctype='a';
	      st->from=atoi(&sym[1]);
	      for (i=strlen(sym); sym[i]!='.'; i--);
	      i++;
	      st->to=atoi(&sym[i]);
	      sym=strtok(NULL," ");
	      }

	    st->offset=atoi(sym);

	    return;

	  /* functions */
	  case 'F':

	    st->stype=sym[0];
	    sym=strtok(NULL," ");

	  /* programs and procedures */
	  case 'P':
	  case 'R':

	    st->ctype='p';
	    st->nparms=atoi(sym);
	    nparms=st->nparms;

	    for (iparms=0; iparms<nparms; iparms++)
	      {

	      if (NULL==(st->parms=(SYMTBL *)malloc(sizeof(SYMTBL))))
		{
		printf("no more room on allocation of parms\n");
		exit(1);
		}
	      st=st->parms;

	      st->symbol=NULL;
	      st->ctype='s';
	      st->from=0;
	      st->to=0;
	      st->nparms=0;
	      st->parms=NULL;
	      st->next=NULL;

	      fgets(s,195,f);
	      sym=strtok(s," ");
	      sym=strtok(NULL," ");
	      st->stype=sym[0];

	      sym=strtok(NULL," ");

	      /* check for an array */
	      if (sym[0]=='[')
		{
		st->ctype='a';
		st->from=atoi(&sym[1]);
		for (i=strlen(sym); sym[i]!='.'; i--);
		i++;
		st->to=atoi(&sym[i]);
		sym=strtok(NULL," ");
		}

	      st->offset=atoi(sym);
	      }
	    return;
	  }
}

SYMTBL *sym_look_up(BLOCK *blk, char *var)
{
	SYMTBL *symtbl;

	for (symtbl=blk->table; symtbl!=NULL; symtbl=symtbl->next)
	  if (!strcmp(symtbl->symbol,var)) return(symtbl);
	return(NULL);
}


void init_mod_use(BLOCK *blk)
{
	SYMTBL *st;

	for (st=blk->table; st!=NULL; st=st->next)
	  {
	  st->next_use=-1;
	  st->mod_use=' ';
	  }
	return;
}
