home *** CD-ROM | disk | FTP | other *** search
- /* syms.c
-
- Symbol table handling for qparser files
-
- CUSTOMIZATION INFORMATION:
- If the struct "symtabtype" has been extended, you must extend
- functions "new_sym", "dump_sym", and "free_symtab_item".
-
- If you modify this code, you may want to compile under options
-
- -DDEBUG -DTEST
-
- to produce a standalone test of the symbol table operations.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "decl.h"
-
- symtabtype *symtab[HASHSIZE];
-
- int clevel= -1; /* reserved word level */
-
- /* ................. */
- static int hashit(fsym)
- char *fsym;
- { int hashcode= 0;
-
- while (*fsym) hashcode += *(fsym++);
- return hashcode % HASHSIZE;
- }
-
- /* ................... */
- symtabtype *new_sym(sym, symt)
- char *sym; /* name */
- int symt; /* symt */
- {
- symtabtype *tsymp;
-
- tsymp= (symtabtype *) malloc(sizeof(*tsymp));
- tsymp->symt= symt;
- tsymp->sym= strdup(sym);
- tsymp->level= clevel;
- /* NOTE: add initialization of any extensions to a "symtabtype" here */
- return(tsymp);
- }
-
- /* ................... */
- static void free_symtab_item(sp)
- symtabtype *sp;
- {
- /* NOTE: free other space linked to a symtab item here */
- if (sp->sym) free(sp->sym);
- free((char *) sp);
- }
-
- /* ................... */
- symtabtype *findsym(fsym)
- char *fsym;
- /* Finds a symbol, returning NULL if not there. Use this for
- variable references, calling error if it returns NULL. */
- { symtabtype *sp= symtab[hashit(fsym)];
-
- while (sp && strcmp(sp->sym, fsym)) sp= sp->next;
- return sp;
- }
-
- /* ................... */
- symtabtype *makesym(fsym, syt)
- char fsym[];
- int syt;
- /* this returns a symbol entry if there; makes a new one if not.
- Useful for FORTRAN-style variable declaration -- declare name
- on first appearance, whether in a declaration or not. */
- { int hx= hashit(fsym);
- symtabtype *sp= symtab[hx];
-
- while (sp && strcmp(sp->sym, fsym)) sp= sp->next;
- if (sp) return sp;
- sp= new_sym(fsym, syt);
- sp->level = clevel;
- sp->next = symtab[hx];
- /* NOTE: initialize other parameters in symtab item here */
- symtab[hx] = sp;
- return sp;
- }
-
- /* ................... */
- symtabtype *forcesym(fsym, syt)
- char fsym[];
- int syt;
- /* This forces a new symbol entry. Use this for declarations
- to cover a previous declaration with the same name. */
- { int hx= hashit(fsym);
- symtabtype *sp= symtab[hx];
-
- sp= new_sym(fsym, syt);
- sp->level = clevel;
- sp->next = symtab[hx];
- symtab[hx] = sp;
- return sp;
- }
-
- /* ................... */
- void clearsym(clevel)
- int clevel;
- /* Sets the symbol table pointers to remove references to
- everything at level >= clevel, assuming that level numbers
- are monotonic. Frees memory space of unlinked entries */
- { symtabtype *sp;
- int hx;
-
- /* Don't clear the reserved words -- check, just in case */
- if (clevel<0) clevel = 0;
- for (hx = 0; hx < HASHSIZE; hx++) {
- sp = symtab[hx];
- while (sp && sp->level >= clevel) { /* get rid of this one */
- symtabtype *next= sp->next;
-
- free_symtab_item(sp);
- sp= next;
- }
- symtab[hx] = sp;
- }
- }
-
- /* .............. */
- void init_sym()
- { int ix;
-
- for (ix= 0; ix< HASHSIZE; ix++)
- symtab[ix]= NULL;
- }
-
- #if DEBUG == 1
-
- /* ................ */
- void dump_sym(tsymp)
- symtabtype *tsymp;
- /* output information on the given symbol table entry. This should
- be extended if more attributes are added */
- {
- if (tsymp) {
- printf("%s ", tsymp->sym);
- switch (tsymp->symt) {
- case RESERVED:
- printf(" (RESERVED) token= %d", tsymp->usym.tokval);
- break;
- case SYMERR:
- case USER:
- case INTVAR:
- case REALVAR:
- case STRVAR:
- printf(" (%s)", symtypenames[tsymp->symt]);
- break;
- /* +++ add customization here --- */
- default: printf(" (???)");
- }
- printf("\n");
- }
- }
-
- /* ........ */
- static int symsort(p1, p2)
- symtabtype **p1, **p2;
- {
- return strcmp((*p1)->sym, (*p2)->sym);
- }
-
- /* ........ */
- void dump_all()
- { int hx, count= 0;
- symtabtype *symp, **symarray;
-
- for (hx= 0; hx< HASHSIZE; hx++) {
- symp= symtab[hx];
- while (symp) {
- count++;
- symp= symp->next;
- }
- }
- symarray= (symtabtype **) malloc(count*sizeof(*symarray));
- count= 0;
- for (hx= 0; hx< HASHSIZE; hx++) {
- symp= symtab[hx];
- while (symp) {
- if (symp->level >= 0) symarray[count++]= symp;
- symp= symp->next;
- }
- }
- qsort((char *) symarray, count, sizeof(*symarray), symsort);
- for (hx= 0; hx< count; hx++) {
- dump_sym(symarray[hx]);
- if ((hx % 24) == 23) {
- char rch= resp(" ---SPACE: more, ENTER: return---");
-
- if (rch=='\n') break;
- }
- }
- free((char *) symarray);
- }
-
- #ifdef TEST
-
- /* a standalone test version. This expects a file with lines
- like these:
-
- * (clear the symbol table through 'clevel')
- + (increase 'clevel' by 1)
- - (decrease 'clevel' by 1)
- !name (force the name in as RESERVED, display it)
- ?name (add the name as RESERVED, show all names)
- name (add the name as USER, show it)
- */
-
- /* ........ */
- main()
- { char line[80];
-
- init_sym();
- while (fgets(line, 80, stdin)) {
- line[strlen(line)-1]='\0';
- if (*line=='*') {
- clearsym(clevel);
- printf("table cleared through level %d\n", clevel);
- }
- else if (*line=='+') {
- clevel++;
- printf("level now %d\n", clevel);
- }
- else if (*line=='-') {
- clevel--;
- printf("level now %d\n", clevel);
- }
- else if (*line=='!') {
- if (clevel < 0) dump_sym(forcesym(line+1, RESERVED));
- else dump_sym(forcesym(line+1, USER));
- }
- else if (*line=='?') {
- if (line[1]=='\0') dump_all();
- else dump_sym(findsym(line+1));
- }
- else if (clevel < 0) dump_sym(makesym(line, RESERVED));
- else dump_sym(makesym(line, USER));
- }
- exit(0);
- }
-
- #endif
- #endif