home *** CD-ROM | disk | FTP | other *** search
/ The Education Master 1994 (4th Edition) / EDUCATIONS_MASTER_4TH_EDITION.bin / files / progmisc / qparser2 / cskels / syms.c < prev   
Encoding:
C/C++ Source or Header  |  1993-11-07  |  6.0 KB  |  252 lines

  1. /* syms.c
  2.  
  3.     Symbol table handling for qparser files
  4.  
  5. CUSTOMIZATION INFORMATION:
  6.     If the struct "symtabtype" has been extended, you must extend
  7.        functions "new_sym", "dump_sym", and "free_symtab_item".
  8.  
  9.     If you modify this code, you may want to compile under options
  10.  
  11.       -DDEBUG -DTEST
  12.  
  13.     to produce a standalone test of the symbol table operations.
  14.     */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "decl.h"
  20.  
  21. symtabtype *symtab[HASHSIZE];
  22.  
  23. int clevel= -1;  /* reserved word level */
  24.  
  25. /* ................. */
  26. static int hashit(fsym)
  27.   char *fsym;
  28. { int hashcode= 0;
  29.  
  30.   while (*fsym) hashcode += *(fsym++);
  31.   return hashcode % HASHSIZE;
  32.   }
  33.  
  34. /* ................... */
  35. symtabtype *new_sym(sym, symt)
  36.   char *sym;  /* name */
  37.   int symt;   /* symt */
  38. {
  39.   symtabtype *tsymp;
  40.  
  41.   tsymp= (symtabtype *) malloc(sizeof(*tsymp));
  42.   tsymp->symt= symt;
  43.   tsymp->sym= strdup(sym);
  44.   tsymp->level= clevel;
  45.   /* NOTE: add initialization of any extensions to a "symtabtype" here */
  46.   return(tsymp);
  47.   }
  48.  
  49. /* ................... */
  50. static void free_symtab_item(sp)
  51.   symtabtype *sp;
  52. {
  53.   /* NOTE:  free other space linked to a symtab item here */
  54.   if (sp->sym) free(sp->sym);
  55.   free((char *) sp);
  56.   }
  57.  
  58. /* ................... */
  59. symtabtype *findsym(fsym)
  60.   char *fsym;
  61.     /* Finds a symbol, returning NULL if not there.  Use this for
  62.       variable references, calling error if it returns NULL. */
  63. { symtabtype *sp= symtab[hashit(fsym)];
  64.  
  65.   while (sp && strcmp(sp->sym, fsym)) sp= sp->next;
  66.   return sp;
  67.   }
  68.  
  69. /* ................... */
  70. symtabtype *makesym(fsym, syt)
  71.   char fsym[];
  72.   int syt;
  73.     /* this returns a symbol entry if there; makes a new one if not.
  74.       Useful for FORTRAN-style variable declaration -- declare name
  75.       on first appearance, whether in a declaration or not. */
  76. { int hx= hashit(fsym);
  77.   symtabtype *sp= symtab[hx];
  78.  
  79.   while (sp && strcmp(sp->sym, fsym)) sp= sp->next;
  80.   if (sp) return sp;
  81.   sp= new_sym(fsym, syt);
  82.   sp->level = clevel;
  83.   sp->next = symtab[hx];
  84.   /* NOTE: initialize other parameters in symtab item here */
  85.   symtab[hx] = sp;
  86.   return sp;
  87.   }
  88.  
  89. /* ................... */
  90. symtabtype *forcesym(fsym, syt)
  91.   char fsym[];
  92.   int syt;
  93.     /* This forces a new symbol entry.  Use this for declarations
  94.       to cover a previous declaration with the same name. */
  95. { int hx= hashit(fsym);
  96.   symtabtype *sp= symtab[hx];
  97.  
  98.   sp= new_sym(fsym, syt);
  99.   sp->level = clevel;
  100.   sp->next = symtab[hx];
  101.   symtab[hx] = sp;
  102.   return sp;
  103.   }
  104.  
  105. /* ................... */
  106. void clearsym(clevel)
  107.   int clevel;
  108.     /* Sets the symbol table pointers to remove references to
  109.       everything at level >= clevel, assuming that level numbers
  110.       are monotonic.  Frees memory space of unlinked entries */
  111. { symtabtype *sp;
  112.   int hx;
  113.  
  114.   /* Don't clear the reserved words -- check, just in case */
  115.   if (clevel<0) clevel = 0;
  116.   for (hx = 0; hx < HASHSIZE; hx++) {
  117.     sp = symtab[hx];
  118.     while (sp && sp->level >= clevel) {  /* get rid of this one */
  119.       symtabtype *next= sp->next;
  120.  
  121.       free_symtab_item(sp);
  122.       sp= next;
  123.       }
  124.     symtab[hx] = sp;
  125.     }
  126.   }
  127.  
  128. /* .............. */
  129. void init_sym()
  130. { int ix;
  131.  
  132.   for (ix= 0; ix< HASHSIZE; ix++)
  133.     symtab[ix]= NULL;
  134.   }
  135.  
  136. #if DEBUG == 1
  137.  
  138. /* ................ */
  139. void dump_sym(tsymp)
  140.   symtabtype *tsymp;
  141.   /* output information on the given symbol table entry.  This should
  142.      be extended if more attributes are added */
  143. {
  144.   if (tsymp) {
  145.     printf("%s ", tsymp->sym);
  146.     switch (tsymp->symt) {
  147.       case RESERVED:
  148.         printf(" (RESERVED) token= %d", tsymp->usym.tokval);
  149.         break;
  150.       case SYMERR:
  151.       case USER:
  152.       case INTVAR:
  153.       case REALVAR:
  154.       case STRVAR:
  155.         printf(" (%s)", symtypenames[tsymp->symt]);
  156.         break;
  157.       /* +++ add customization here --- */
  158.       default: printf(" (???)");
  159.       }
  160.     printf("\n");
  161.     }
  162.   }
  163.  
  164. /* ........ */
  165. static int symsort(p1, p2)
  166.   symtabtype **p1, **p2;
  167. {
  168.   return strcmp((*p1)->sym, (*p2)->sym);
  169.   }
  170.  
  171. /* ........ */
  172. void dump_all()
  173. { int hx, count= 0;
  174.   symtabtype *symp, **symarray;
  175.  
  176.   for (hx= 0; hx< HASHSIZE; hx++) {
  177.     symp= symtab[hx];
  178.     while (symp) {
  179.       count++;
  180.       symp= symp->next;
  181.       }
  182.     }
  183.   symarray= (symtabtype **) malloc(count*sizeof(*symarray));
  184.   count= 0;
  185.   for (hx= 0; hx< HASHSIZE; hx++) {
  186.     symp= symtab[hx];
  187.     while (symp) {
  188.       if (symp->level >= 0) symarray[count++]= symp;
  189.       symp= symp->next;
  190.       }
  191.     }
  192.   qsort((char *) symarray, count, sizeof(*symarray), symsort);
  193.   for (hx= 0; hx< count; hx++) {
  194.     dump_sym(symarray[hx]);
  195.     if ((hx % 24) == 23) {
  196.       char rch= resp(" ---SPACE: more, ENTER: return---");
  197.  
  198.       if (rch=='\n') break;
  199.       }
  200.     }
  201.   free((char *) symarray);
  202.   }
  203.  
  204. #ifdef TEST
  205.  
  206. /* a standalone test version.  This expects a file with lines
  207.    like these:
  208.  
  209.     *     (clear the symbol table through 'clevel')
  210.     +     (increase 'clevel' by 1)
  211.     -     (decrease 'clevel' by 1)
  212.     !name   (force the name in as RESERVED, display it)
  213.     ?name   (add the name as RESERVED, show all names)
  214.     name    (add the name as USER, show it)
  215.      */
  216.  
  217. /* ........ */
  218. main()
  219. { char line[80];
  220.  
  221.   init_sym();
  222.   while (fgets(line, 80, stdin)) {
  223.     line[strlen(line)-1]='\0';
  224.     if (*line=='*') {
  225.       clearsym(clevel);
  226.       printf("table cleared through level %d\n", clevel);
  227.       }
  228.     else if (*line=='+') {
  229.       clevel++;
  230.       printf("level now %d\n", clevel);
  231.       }
  232.     else if (*line=='-') {
  233.       clevel--;
  234.       printf("level now %d\n", clevel);
  235.       }
  236.     else if (*line=='!') {
  237.       if (clevel < 0) dump_sym(forcesym(line+1, RESERVED));
  238.       else dump_sym(forcesym(line+1, USER));
  239.       }
  240.     else if (*line=='?') {
  241.       if (line[1]=='\0') dump_all();
  242.       else dump_sym(findsym(line+1));
  243.       }
  244.     else if (clevel < 0) dump_sym(makesym(line, RESERVED));
  245.     else dump_sym(makesym(line, USER));
  246.     }
  247.   exit(0);
  248.   }
  249.  
  250. #endif
  251. #endif
  252.