/********************************************************************
   Program :  Recursive Descent Compiler for PL/0
   Module  :  PL0SYMT - Symbol table management
   File    :  pl0symt.c
   Compiler:  Borland C 3.1 - 4.5, GNU C 2.7.1
   Author  :  H. Weber
********************************************************************/

#include <stdio.h>
#include "pl0const.h"
#include "pl0symt.h"
#include "pl0err.h"

#define  txmax    200         /* maximum value for symbol table index */

struct symttype
   {
      char  name[cmax];
      int   kind;
      int   level;
      int   addr;
      int   size;
   }  symtable [txmax];


void enter(int k, char *id, int lev, int siz,
	   int *tx, int *txfirst, int *dindex)
{
   int i;

   i = position(id, *tx);
   if (i >= *txfirst) error(45);    /* multiple declaration */
   (*tx)++;
   if (*tx == txmax-1) error(49);   /* symbol table full */

   strcpy(symtable[*tx].name, id);
   symtable[*tx].kind = k;
   if (k == constobj)
      symtable[*tx].size = siz;
   else if (k == varobj) {
      symtable[*tx].level = lev;
      symtable[*tx].addr  = (*dindex)++;
   }
   else if (k == procobj)
      symtable[*tx].level = lev;
}

int position(char *id, int tx)
{
   int j;

   strcpy(symtable[0].name, id);
   j = tx;
   while (strcmp(symtable[j].name, id) != 0) j--;
   return j;
}

int objkind(int i)
{
   return symtable[i].kind;
}

int objlevel(int i)
{
   return symtable[i].level;
}

int objaddr(int i)
{
   return symtable[i].addr;
}

int constsize(int i)
{
   return symtable[i].size;
}

void entersymt(int n, int codeindex, int dindex)
{
   symtable[n].addr = codeindex;
   symtable[n].size = dindex;
}

void printsymt(FILE *stfile, int index, int tx)
{
   int j;
   fprintf(stfile,
    "\n*****************************************************\n");
   if (index == 0)
      fprintf(stfile, "main\n");
   else
      fprintf(stfile, "%s\n", symtable[index].name);
   fprintf(stfile,
    "*****************************************************\n");
   fprintf(stfile, "No.        name     kind    ");
   fprintf(stfile, "  level    addr  size/val\n");
   fprintf(stfile,
    "-----------------------------------------------------\n");
   for (j=1; j<=tx; j++) {
       fprintf(stfile, "%3d %10s  ", j, symtable[j].name);
       switch (symtable[j].kind) {
          case constobj :
             fprintf(stfile, " CONSTANT                   %6d",
                     symtable[j].size);
             break;
          case varobj :
             fprintf(stfile, " VARIABLE   %6d  %6d",
                     symtable[j].level, symtable[j].addr);
             break;
          case procobj :
             fprintf(stfile, " PROCEDURE  %6d  %6d  %6d",
                     symtable[j].level, symtable[j].addr,
                     symtable[j].size);
             break;
       }
       fprintf(stfile, "\n");
   }
   fprintf(stfile, "\n");
}
