2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
27 ** Symbol table abstraction
31 ** Gary Feldman, Technical Languages and Environments, DECspec project
33 ** Massachusetts Institute of Technology
34 ** Joe Wild, Technical Languages and Environments, DECspec project
36 ** Massachusetts Institute of Technology
43 # include "lclintMacros.nf"
47 # include "lclsyntable.h"
48 # include "lslparse.h"
52 static bool isBlankLine (char *p_line);
53 static bool inImport = FALSE;
55 /*@constant static int MAXBUFFLEN;@*/
56 # define MAXBUFFLEN 512
57 /*@constant static int DELTA;@*/
60 static void symHashTable_dump (symHashTable * p_t, FILE * p_f, bool p_lco);
62 static void tagInfo_free (/*@only@*/ tagInfo p_tag);
63 static /*@observer@*/ scopeInfo symtable_scopeInfo (symtable p_stable);
65 static void symtable_dumpId (symtable p_stable, FILE *p_f, bool p_lco);
66 static lsymbol nameNode2key (nameNode p_n);
70 SYMK_FCN, SYMK_SCOPE, SYMK_TYPE, SYMK_VAR
78 /*@only@*/ fctInfo fct;
79 /*@only@*/ scopeInfo scope;
80 /*@only@*/ typeInfo type;
81 /*@only@*/ varInfo var;
85 typedef struct _idTable
88 unsigned int allocated;
89 /*@relnull@*/ idTableEntry *entries;
93 struct _symtableStruct
95 idTable *idTable; /* data is idTableEntry */
96 symHashTable *hTable; /* data is htData */
97 mapping *type2sort; /* maps LCL type symbol to LSL sort */
100 static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *p_x);
101 static /*@out@*/ /*@exposed@*/ idTableEntry *nextFree (idTable * p_st);
102 static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookup (idTable * p_st, lsymbol p_id);
103 static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookupInScope (idTable * p_st, lsymbol p_id);
105 static /*@only@*/ idTable *symtable_newIdTable (void);
106 static void idTableEntry_free (idTableEntry p_x);
108 /* Local implementatio of hash table */
110 static bool allowed_redeclaration = FALSE;
111 static symbolKey htData_key (htData *p_x);
113 static void symHashTable_free (/*@only@*/ symHashTable *p_h);
114 static /*@only@*/ symHashTable *symHashTable_create (unsigned int p_size);
115 static /*@null@*/ /*@exposed@*/ htData *
116 symHashTable_get (symHashTable * p_t, symbolKey p_key, infoKind p_kind,
117 /*@null@*/ nameNode p_n);
118 static bool symHashTable_put (symHashTable *p_t, /*@only@*/ htData *p_data);
119 static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
120 symHashTable_forcePut (symHashTable * p_t, /*@only@*/ htData *p_data);
121 /* static unsigned int symHashTable_count (symHashTable * t); */
123 static void idTable_free (/*@only@*/ idTable *p_st);
125 void varInfo_free (/*@only@*/ varInfo v)
130 static /*@only@*/ varInfo varInfo_copy (varInfo v)
132 varInfo ret = (varInfo) dmalloc (sizeof (*ret));
134 ret->id = ltoken_copy (v->id);
137 ret->export = v->export;
142 void symtable_free (symtable stable)
144 /* symtable_printStats (stable); */
146 idTable_free (stable->idTable);
147 symHashTable_free (stable->hTable);
148 mapping_free (stable->type2sort);
152 static void idTable_free (idTable *st)
156 for (i = 0; i < st->size; i++)
158 idTableEntry_free (st->entries[i]);
165 static void fctInfo_free (/*@only@*/ fctInfo f)
167 signNode_free (f->signature);
168 pairNodeList_free (f->globals);
173 static void typeInfo_free (/*@only@*/ typeInfo t)
178 static void scopeInfo_free (/*@only@*/ scopeInfo s)
183 static void idTableEntry_free (idTableEntry x)
188 fctInfo_free (x.info.fct);
191 scopeInfo_free (x.info.scope);
194 typeInfo_free (x.info.type);
197 varInfo_free (x.info.var);
202 static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *x)
207 return (x->info.fct->id);
209 return ltoken_undefined;
211 return (x->info.type->id);
213 return (x->info.var->id);
222 symtable stable = (symtable) dmalloc (sizeof (*stable));
225 stable->idTable = symtable_newIdTable ();
226 stable->hTable = symHashTable_create (HT_MAXINDEX);
227 stable->type2sort = mapping_create ();
229 /* add builtin synonym: Bool -> bool */
231 mapping_bind (stable->type2sort, lsymbol_getBool (), lsymbol_getbool ());
234 ** done by symtable_newIdTable
235 ** st->allocated = 0;
236 ** st->entries = (idTableEntry *) 0;
237 ** st->exporting = TRUE;
240 /* this is global scope */
241 e = nextFree (stable->idTable);
242 e->kind = SYMK_SCOPE;
243 (e->info).scope = (scopeInfo) dmalloc (sizeof (*((e->info).scope)));
244 (e->info).scope->kind = SPE_GLOBAL;
249 static /*@only@*/ idTable *symtable_newIdTable (void)
251 idTable *st = (idTable *) dmalloc (sizeof (*st));
255 st->entries = (idTableEntry *) 0;
256 st->exporting = TRUE;
258 /* this was being done twice!
260 e->kind = SYMK_SCOPE;
261 (e->info).scope.kind = globScope;
268 nameNode2key (nameNode n)
274 ret = ltoken_getText (n->content.opid);
278 /* use opForm's key as its Identifier */
279 llassert (n->content.opform != NULL);
280 ret = (n->content.opform)->key;
287 ** requires: nameNode n is already in st.
291 htData_insertSignature (htData *d, /*@owned@*/ sigNode oi)
293 sigNodeSet set = d->content.op->signatures;
296 if (oi != (sigNode) 0)
298 return (sigNodeSet_insert (set, oi));
304 symtable_enterOp (symtable st, /*@only@*/ /*@notnull@*/ nameNode n,
305 /*@owned@*/ sigNode oi)
308 ** Operators are overloaded, we allow entering opInfo more than once,
309 ** even if it's the same signature.
311 ** Assumes all sorts are already entered into the symbol table
314 symHashTable *ht = st->hTable;
320 id = nameNode2key (n);
322 d = symHashTable_get (ht, id, IK_OP, n);
324 if (d == (htData *) 0)
325 { /* first signature of this operator */
326 opInfo op = (opInfo) dmalloc (sizeof (*op));
327 htData *nd = (htData *) dmalloc (sizeof (*nd));
331 if (oi != (sigNode) 0)
333 op->signatures = sigNodeSet_singleton (oi);
338 op->signatures = sigNodeSet_new ();
339 sigNode_markOwned (oi);
344 (void) symHashTable_put (ht, nd);
349 nameNode_free (n); /*<<<??? */
351 if (htData_insertSignature (d, oi))
359 symtable_enterTag (symtable st, tagInfo ti)
361 /* put ti only if it is not already in symtable */
362 symHashTable *ht = st->hTable;
364 symbolKey key = ltoken_getText (ti->id);
366 d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
367 if (d == (htData *) 0)
369 d = (htData *) dmalloc (sizeof (*d));
372 d->content.tag->imported = context_inImport ();
373 (void) symHashTable_put (ht, d);
378 if (d->content.tag->imported)
381 d->content.tag->imported = context_inImport ();
393 symtable_enterTagForce (symtable st, tagInfo ti)
395 /* put ti, force-put if necessary */
396 symHashTable *ht = st->hTable;
398 symbolKey key = ltoken_getText (ti->id);
400 d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
402 if (d == (htData *) 0)
404 d = (htData *) dmalloc (sizeof (*d));
408 d->content.tag->imported = context_inImport ();
409 (void) symHashTable_put (ht, d);
417 d->content.tag->imported = context_inImport ();
418 /* interpret return data later, htData * */
419 /*@i@*/ (void) symHashTable_forcePut (ht, d);
425 symtable_opInfo (symtable st, /*@notnull@*/ nameNode n)
427 symHashTable *ht = st->hTable;
428 lsymbol i = nameNode2key (n);
431 d = symHashTable_get (ht, i, IK_OP, n);
432 if (d == (htData *) 0)
437 return (d->content.op);
441 symtable_tagInfo (symtable st, lsymbol i)
443 symHashTable *ht = st->hTable;
445 d = symHashTable_get (ht, i, IK_TAG, 0);
447 if (d == (htData *) 0)
449 return (tagInfo) NULL;
452 return (d->content.tag);
456 symtable_enterScope (symtable stable, scopeInfo si)
458 idTable *st = stable->idTable;
459 idTableEntry *e = nextFree (st);
460 if (si->kind == SPE_GLOBAL)
461 llbuglit ("symtable_enterScope: SPE_GLOBAL");
462 e->kind = SYMK_SCOPE;
463 (e->info).scope = si;
467 symtable_exitScope (symtable stable)
469 idTable *st = stable->idTable;
472 if (st->entries != NULL)
474 for (n = st->size - 1; (st->entries[n]).kind != SYMK_SCOPE; n--)
481 llcontbuglit ("symtable_exitScope: no scope to exit");
489 symtable_enterFct (symtable stable, fctInfo fi)
491 idTable *st = stable->idTable;
495 if (!allowed_redeclaration &&
496 symtable_lookup (st, ltoken_getText (fi->id)) != (idTableEntry *) 0)
498 lclRedeclarationError (fi->id);
504 fi->export = st->exporting; /* && !fi->private; */
511 symtable_enterType (symtable stable, /*@only@*/ typeInfo ti)
513 idTable *st = stable->idTable;
516 scopeKind k = (symtable_scopeInfo (stable))->kind;
518 /* symtable_disp (stable); */
520 if (k != SPE_GLOBAL && k != SPE_INVALID) /* fixed for LCLint */
522 llbug (message ("%q: symtable_enterType: expect global scope. (type: %s)",
523 ltoken_unparseLoc (ti->id),
524 ltoken_getRawString (ti->id)));
527 if (!allowed_redeclaration &&
528 symtable_lookup (st, ltoken_getText (ti->id)) != (idTableEntry *) 0)
530 /* ignore if Bool is re-entered */
531 if (ltoken_getText (ti->id) == lsymbol_getBool () ||
532 ltoken_getText (ti->id) == lsymbol_getbool ())
538 lclRedeclarationError (ti->id);
543 /* make sure it is a type TYPEDEF_NAME; */
545 if (ltoken_getCode (ti->id) != LLT_TYPEDEF_NAME)
547 lclbug (message ("symtable_enterType: gets a simpleId, expect a type: %s",
548 ltoken_getRawString (ti->id)));
553 ti->export = st->exporting;/* && !ti->private; */
555 mapping_bind (stable->type2sort, ltoken_getText (ti->id),
556 sort_getLsymbol (sort_makeVal (sort_getUnderlying (ti->basedOn))));
565 lsymbol_sortFromType (symtable s, lsymbol typename)
570 /* check the synonym table first */
571 if (LCLIsSyn (typename))
573 tok = LCLGetTokenForSyn (typename);
574 inter = ltoken_getText (tok);
575 /* printf ("In lsymbol_sortFromType: %s -> %s\n",
576 lsymbol_toChars (typename), lsymbol_toChars (inter)); */
583 /* now map LCL type to sort */
584 out = mapping_find (s->type2sort, inter);
586 if (out == lsymbol_undefined)
597 ** returns true is vi is a redeclaration
601 symtable_enterVar (symtable stable, /*@temp@*/ varInfo vi)
603 idTable *st = stable->idTable;
608 /* symtable_disp (symtab); */
610 if (!allowed_redeclaration &&
611 (symtable_lookupInScope (st, ltoken_getText (vi->id)) != (idTableEntry *) 0))
613 if (ltoken_getText (vi->id) == lsymbol_getTRUE () ||
614 ltoken_getText (vi->id) == lsymbol_getFALSE ())
620 if (usymtab_existsEither (ltoken_getRawString (vi->id)))
622 lclRedeclarationError (vi->id);
627 llbuglit ("redeclared somethingerother?!");
634 idTableEntry *e = nextFree (st);
637 vi->export = st->exporting && /* !vi.private && */
638 (vi->kind == VRK_VAR || vi->kind == VRK_CONST || vi->kind == VRK_ENUM);
639 (e->info).var = varInfo_copy (vi);
646 symtable_exists (symtable stable, lsymbol i)
648 idTable *st = stable->idTable;
649 return symtable_lookup (st, i) != (idTableEntry *) 0;
653 symtable_typeInfo (symtable stable, lsymbol i)
658 st = stable->idTable;
659 e = symtable_lookup (st, i);
661 if (e == (idTableEntry *) 0 || e->kind != SYMK_TYPE)
663 return (typeInfo) NULL;
666 return (e->info).type;
670 symtable_varInfo (symtable stable, lsymbol i)
672 idTable *st = stable->idTable;
675 e = symtable_lookup (st, i);
677 if (e == (idTableEntry *) 0 || e->kind != SYMK_VAR)
679 return (varInfo) NULL;
682 return (e->info).var;
686 symtable_varInfoInScope (symtable stable, lsymbol id)
688 /* if current scope is a SPE_QUANT, can go beyond current scope */
689 idTable *st = stable->idTable;
690 idTableEntry *e2 = (idTableEntry *) 0;
693 for (n = st->size - 1; n >= 0; n--)
697 e2 = &(st->entries[n]);
699 if (e2->kind == SYMK_SCOPE && e2->info.scope->kind != SPE_QUANT)
701 return (varInfo) NULL;
704 tok = idTableEntry_getId (e2);
706 if (e2->kind == SYMK_VAR && ltoken_getText (tok) == id)
708 return (e2->info).var;
712 return (varInfo) NULL;
716 symtable_scopeInfo (symtable stable)
718 idTable *st = stable->idTable;
722 for (n = st->size - 1; n >= 0; n--)
724 e = &(st->entries[n]);
725 if (e->kind == SYMK_SCOPE)
726 return (e->info).scope;
729 lclfatalbug ("symtable_scopeInfo: not found");
734 symtable_export (symtable stable, bool yesNo)
736 idTable *st = stable->idTable;
737 st->exporting = yesNo;
738 (void) sort_setExporting (yesNo);
742 symHashTable_dump (symHashTable * t, FILE * f, bool lco)
744 /* like symHashTable_dump2 but for output to .lcs file */
752 for (i = 0; i <= HT_MAXINDEX; i++)
756 for (entry = b; entry != NULL; entry = entry->next)
763 /*@switchbreak@*/ break;
766 char *name = cstring_toCharsSafe (nameNode_unparse (d->content.op->name));
767 sigs = d->content.op->signatures;
768 size = sigNodeSet_size (sigs);
771 sigNodeSet_elements (sigs, x)
773 cstring s = sigNode_unparse (x);
777 fprintf (f, "%%LCL");
780 fprintf (f, "op %s %s\n", name, cstring_toCharsSafe (s));
782 } end_sigNodeSet_elements;
785 /*@switchbreak@*/ break;
788 tok = d->content.tag->id;
790 if (!ltoken_isUndefined (tok))
792 cstring s = tagKind_unparse (d->content.tag->kind);
796 fprintf (f, "%%LCL");
799 fprintf (f, "tag %s %s\n", ltoken_getTextChars (tok),
800 cstring_toCharsSafe (s));
803 /*@switchbreak@*/ break;
810 symtable_dump (symtable stable, FILE * f, bool lco)
812 symHashTable *ht = stable->hTable;
815 fprintf (f, "%s\n", BEGINSYMTABLE);
817 symHashTable_dump (ht, f, lco);
819 symtable_dumpId (stable, f, lco);
821 fprintf (f, "%s\n", SYMTABLEEND);
825 lsymbol_translateSort (mapping * m, lsymbol s)
827 lsymbol res = mapping_find (m, s);
828 if (res == lsymbol_undefined)
833 static /*@null@*/ lslOp
834 lslOp_renameSorts (mapping *map,/*@returned@*/ /*@null@*/ lslOp op)
843 sign = op->signature;
845 domain = sign->domain;
847 ltokenList_elements (domain, dt)
850 lsymbol_translateSort (map, ltoken_getText (dt)));
851 } end_ltokenList_elements;
853 /*@-onlytrans@*/ /* A memory leak... */
854 op->signature = makesigNode (sign->tok, domain, range);
861 static /*@null@*/ signNode
862 signNode_fromsigNode (sigNode s)
867 if (s == (sigNode) 0)
872 sign = (signNode) dmalloc (sizeof (*sign));
873 slist = sortList_new ();
874 sign->tok = ltoken_copy (s->tok);
876 sign->range = sort_makeSort (ltoken_undefined, ltoken_getText (s->range));
878 ltokenList_elements (s->domain, dt)
880 sortList_addh (slist, sort_makeSort (ltoken_undefined, ltoken_getText (dt)));
881 } end_ltokenList_elements;
883 sign->domain = slist;
888 /** 2.4.3 ymtan 93.09.23 -- fixed bug in parseGlobals: removed ";" at the
889 ** end of pairNode (gstr).
892 static /*@only@*/ pairNodeList
893 parseGlobals (char *line, tsource *srce)
895 pairNodeList plist = pairNodeList_new ();
898 char *lineptr, sostr[MAXBUFFLEN], gstr[MAXBUFFLEN];
900 /* line is not all blank */
901 /* expected format: "sort1 g1; sort2 g2; sort3 g3;" */
904 while (!isBlankLine (lineptr))
906 if (sscanf (lineptr, "%s %s", &(sostr[0]), gstr) != 2)
910 ("%q: Imported file contains illegal function global declaration.\n"
911 "Skipping rest of the line: %s (%s)",
912 fileloc_unparseRaw (cstring_fromChars (tsource_fileName (srce)),
913 tsource_thisLineNumber (srce)),
914 cstring_fromChars (line),
915 cstring_fromChars (lineptr)));
919 p = (pairNode) dmalloc (sizeof (*p));
921 /* Note: remove the ";" separator at the end of gstr */
922 semi_index = size_toInt (strlen (gstr));
923 gstr[semi_index - 1] = '\0';
925 p->tok = ltoken_create (NOTTOKEN, lsymbol_fromChars (gstr));
926 p->sort = sort_makeSort (ltoken_undefined, lsymbol_fromChars (sostr));
928 pairNodeList_addh (plist, p);
929 lineptr = strchr (lineptr, ';'); /* go pass the next; */
931 llassert (lineptr != NULL);
932 lineptr = lineptr + 1;
939 isBlankLine (char *line)
943 if (line == NULL) return TRUE;
945 for (i = 0; line[i] != '\0'; i++)
958 typedef /*@only@*/ fctInfo o_fctInfo;
961 parseLine (char *line, tsource *srce, mapping * map)
963 static /*@owned@*/ o_fctInfo *savedFcn = NULL;
964 char *lineptr, *lineptr2, *cimportfile = tsource_fileName (srce);
965 cstring importfile = cstring_fromChars (cimportfile);
966 char namestr[MAXBUFFLEN], kstr[20], sostr[MAXBUFFLEN];
967 sort bsort, nullSort = sort_makeNoSort ();
969 fileloc imploc = fileloc_undefined;
974 imploc = fileloc_createImport (importfile, tsource_thisLineNumber (srce));
977 if (firstWord (line, "op"))
981 lineptr = strchr (line, 'o'); /* remove any leading blanks */
982 llassert (lineptr != NULL);
983 lineptr = strchr (lineptr, ' '); /* go past "op" */
984 llassert (lineptr != NULL);
986 /* add a newline to the end of the line since parseOpLine expects it */
987 lineptr2 = strchr (lineptr, '\0');
992 *(lineptr2 + 1) = '\0';
995 llassert (cimportfile != NULL);
996 op = parseOpLine (cimportfile, lineptr + 1);
1002 ("%q: Imported file contains illegal operator declaration:\n "
1003 "skipping this line: %s",
1004 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1005 cstring_fromChars (line)));
1006 fileloc_free (imploc);
1010 op = lslOp_renameSorts (map, op);
1012 llassert (op != NULL);
1013 llassert (op->name != NULL);
1015 symtable_enterOp (g_symtab, op->name,
1016 sigNode_copy (op->signature));
1017 /*@-mustfree@*/ } /*@=mustfree@*/
1018 else if (firstWord (line, "type"))
1022 if (sscanf (line, "type %s %s %s", namestr, sostr, kstr) != 3)
1025 (message ("%q: illegal type declaration:\n skipping this line: %s",
1026 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1027 cstring_fromChars (line)));
1028 fileloc_free (imploc);
1032 ti = (typeInfo) dmalloc (sizeof (*ti));
1033 ti->id = ltoken_createFull (LLT_TYPEDEF_NAME, lsymbol_fromChars (namestr),
1034 importfile, tsource_thisLineNumber (srce), col);
1036 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1038 if (sort_isNoSort (bsort))
1040 lineptr = strchr (line, ' '); /* go past "type" */
1041 llassert (lineptr != NULL);
1042 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1043 llassert (lineptr != NULL);
1044 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1046 lclbug (message ("%q: Imported files contains unknown base sort",
1047 fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
1051 ti->basedOn = bsort;
1053 if (strcmp (kstr, "exposed") == 0)
1055 ti->abstract = FALSE;
1056 ti->modifiable = TRUE;
1060 ti->abstract = TRUE;
1061 if (strcmp (kstr, "mutable") == 0)
1062 ti->modifiable = TRUE;
1064 ti->modifiable = FALSE;
1069 ** sort of a hack to get imports to work...
1074 cstring cnamestr = cstring_fromChars (namestr);
1076 if (!usymtab_existsGlobEither (cnamestr))
1078 (void) usymtab_addEntry
1079 (uentry_makeDatatype (cnamestr, ctype_unknown,
1080 ti->abstract ? ynm_fromBool (ti->modifiable) : MAYBE,
1081 ti->abstract ? YES : NO,
1082 fileloc_copy (imploc)));
1086 symtable_enterType (g_symtab, ti);
1088 else if (firstWord (line, "var"))
1092 if (sscanf (line, "var %s %s", namestr, sostr) != 2)
1095 (message ("%q: Imported file contains illegal variable declaration. "
1096 "Skipping this line.",
1097 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce))));
1098 fileloc_free (imploc);
1102 vi = (varInfo) dmalloc (sizeof (*vi));
1103 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1104 lineptr = strchr (line, ' '); /* go past "var" */
1105 llassert (lineptr != NULL);
1106 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1107 llassert (lineptr != NULL);
1108 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1110 if (sort_isNoSort (bsort))
1112 lclplainerror (message ("%q: Imported file contains unknown base sort",
1113 fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
1117 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
1118 importfile, tsource_thisLineNumber (srce), col);
1122 (void) symtable_enterVar (g_symtab, vi);
1127 cstring cnamestr = cstring_fromChars (namestr);
1129 if (!usymtab_existsGlobEither (cnamestr))
1132 (void) usymtab_supEntrySref
1133 (uentry_makeVariable (cnamestr, ctype_unknown,
1134 fileloc_copy (imploc),
1139 else if (firstWord (line, "const"))
1143 if (sscanf (line, "const %s %s", namestr, sostr) != 2)
1145 lclbug (message ("%q: Imported file contains illegal constant declaration: %s",
1146 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1147 cstring_fromChars (line)));
1148 fileloc_free (imploc);
1152 vi = (varInfo) dmalloc (sizeof (*vi));
1153 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1154 lineptr = strchr (line, ' '); /* go past "var" */
1155 llassert (lineptr != NULL);
1156 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1157 llassert (lineptr != NULL);
1159 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1161 if (sort_isNoSort (bsort))
1163 lclplainerror (message ("%q: Imported file contains unknown base sort",
1164 fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
1168 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
1169 importfile, tsource_thisLineNumber (srce), col);
1171 vi->kind = VRK_CONST;
1173 (void) symtable_enterVar (g_symtab, vi);
1178 cstring cnamestr = cstring_fromChars (namestr);
1180 if (!usymtab_existsGlobEither (cnamestr))
1183 (void) usymtab_addEntry (uentry_makeConstant (cnamestr,
1185 fileloc_copy (imploc)));
1188 /* must check for "fcnGlobals" before "fcn" */
1190 else if (firstWord (line, "fcnGlobals"))
1192 pairNodeList globals;
1193 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1194 llassert (lineptr != NULL);
1195 lineptr = strchr (lineptr, ' '); /* go past "fcnGlobals" */
1196 llassert (lineptr != NULL);
1198 /* a quick check for empty fcnGlobals */
1199 if (!isBlankLine (lineptr))
1201 globals = parseGlobals (lineptr, srce);
1202 /* should ensure that each global in an imported function
1203 corresponds to some existing global. Since only
1204 "correctly processed" .lcs files are imported, this is
1205 true as an invariant. */
1209 globals = pairNodeList_new ();
1212 /* check that they exist, store them on fctInfo */
1214 if (savedFcn != NULL)
1216 pairNodeList_free ((*savedFcn)->globals);
1217 (*savedFcn)->globals = globals; /* evs, moved inside if predicate */
1219 (void) symtable_enterFct (g_symtab, *savedFcn);
1225 (message ("%q: Unexpected function globals. "
1226 "Skipping this line: \n%s",
1227 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1228 cstring_fromChars (line)));
1230 pairNodeList_free (globals);
1233 else if (firstWord (line, "fcn"))
1238 if (savedFcn != (fctInfo *) 0)
1241 (message ("%q: illegal function declaration. Skipping this line:\n%s",
1242 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1243 cstring_fromChars (line)));
1244 fileloc_free (imploc);
1248 savedFcn = (fctInfo *) dmalloc (sizeof (*savedFcn));
1250 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1251 llassert (lineptr != NULL);
1252 lineptr = strchr (lineptr, ' '); /* go past "fcn" */
1253 llassert (lineptr != NULL);
1255 /* add a newline to the end of the line since parseOpLine expects it */
1257 lineptr2 = strchr (lineptr, '\0');
1262 *(lineptr2 + 1) = '\0';
1265 op = parseOpLine (cimportfile, lineptr + 1);
1267 if (op == (lslOp) 0)
1269 lclplainerror (message ("%q: illegal function declaration: %s",
1270 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1271 cstring_fromChars (line)));
1272 fileloc_free (imploc);
1276 op2 = lslOp_renameSorts (map, op);
1278 llassert (op2 != NULL);
1280 if ((op->name != NULL) && op->name->isOpId)
1282 (*savedFcn) = (fctInfo) dmalloc (sizeof (**savedFcn));
1283 (*savedFcn)->id = op->name->content.opid;
1284 (*savedFcn)->signature = signNode_fromsigNode (op2->signature);
1285 (*savedFcn)->globals = pairNodeList_new ();
1286 (*savedFcn)->export = TRUE;
1290 /* 27 Jan 1995 --- added this to be undefined namestr bug */
1291 cstring fname = ltoken_unparse ((*savedFcn)->id);
1293 if (!usymtab_existsGlobEither (fname))
1295 (void) usymtab_addEntry (uentry_makeFunction
1296 (fname, ctype_unknown,
1297 typeId_invalid, globSet_new (),
1299 fileloc_copy (imploc)));
1305 lclplainerror (message ("%q: unexpected function name: %s",
1306 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1307 cstring_fromChars (line)));
1310 else if (firstWord (line, "enumConst"))
1314 if (sscanf (line, "enumConst %s %s", namestr, sostr) != 2)
1317 (message ("%q: Illegal enum constant declaration. "
1318 "Skipping this line:\n%s",
1319 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1320 cstring_fromChars (line)));
1321 fileloc_free (imploc);
1325 vi = (varInfo) dmalloc (sizeof (*vi));
1326 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1327 lineptr = strchr (line, ' '); /* go past "var" */
1328 llassert (lineptr != NULL);
1329 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1330 llassert (lineptr != NULL);
1332 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1333 if (sort_isNoSort (bsort))
1335 lclplainerror (message ("%q: unknown base sort\n",
1336 fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
1340 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
1341 importfile, tsource_thisLineNumber (srce), col);
1344 vi->kind = VRK_ENUM;
1346 (void) symtable_enterVar (g_symtab, vi);
1351 cstring cnamestr = cstring_fromChars (namestr);
1352 if (!usymtab_existsEither (cnamestr))
1354 (void) usymtab_addEntry (uentry_makeConstant (cnamestr, ctype_unknown,
1355 fileloc_copy (imploc)));
1359 else if (firstWord (line, "tag"))
1361 /* do nothing, sort processing already handles this */
1366 (message ("%q: Unknown symbol declaration. Skipping this line:\n%s",
1367 fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)),
1368 cstring_fromChars (line)));
1371 fileloc_free (imploc);
1375 symtable_import (tsource *imported, ltoken tok, mapping * map)
1377 char *buf, *importfile;
1380 bool old_inImport = inImport;
1382 buf = tsource_nextLine (imported);
1383 importfile = tsource_fileName (imported);
1385 llassert (buf != NULL);
1387 if (!firstWord (buf, "%LCLSymbolTable"))
1389 lclsource = LCLScanSource ();
1391 message ("Expecting '%%LCLSymbolTable' line in import file %s:\n%s\n",
1392 cstring_fromChars (importfile),
1393 cstring_fromChars (buf)));
1396 old_lsldebug = lsldebug;
1398 allowed_redeclaration = TRUE;
1403 buf = tsource_nextLine (imported);
1404 llassert (buf != NULL);
1407 if (firstWord (buf, "%LCLSymbolTableEnd"))
1412 { /* a good line, remove %LCL from line first */
1413 if (firstWord (buf, "%LCL"))
1415 parseLine (buf + 4, imported, map);
1419 lclsource = LCLScanSource ();
1422 message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
1423 cstring_fromChars (importfile),
1424 cstring_fromChars (buf)));
1429 /* restore old value */
1430 inImport = old_inImport;
1431 lsldebug = old_lsldebug;
1432 allowed_redeclaration = FALSE;
1436 symtable_dumpId (symtable stable, FILE *f, bool lco)
1438 idTable *st = stable->idTable;
1445 for (i = 1; i < st->size; i++)
1447 /* 2/22/93 I think there is a off-by-1 error, 0 entry is never used */
1448 se = st->entries + i;
1449 llassert (se != NULL);
1452 /*@-loopswitchbreak@*/
1459 fi = (se->info).fct;
1463 fprintf (f, "%%LCL");
1466 if (!lco && !fi->export)
1468 fprintf (f, "spec ");
1471 tmp = signNode_unparse (fi->signature);
1472 fprintf (f, "fcn %s %s \n", ltoken_getTextChars (fi->id),
1473 cstring_toCharsSafe (tmp));
1476 tmp = pairNodeList_unparse (fi->globals);
1477 fprintf (f, "%%LCLfcnGlobals %s\n", cstring_toCharsSafe (tmp));
1487 /*@-switchswitchbreak@*/
1488 switch ((se->info).scope->kind)
1491 fprintf (f, "Global scope\n");
1494 fprintf (f, "Abstract type scope\n");
1497 fprintf (f, "Function scope\n");
1499 /* a let scope can only occur in a function scope, should not push
1500 a new scope, so symtable_lookupInScope works properly
1502 fprintf (f, "Let scope\n");
1505 fprintf (f, "Quantifier scope\n");
1508 fprintf (f, "Claim scope\n");
1515 ti = (se->info).type;
1517 fprintf (f, "%%LCL");
1518 if (!lco && !ti->export)
1519 fprintf (f, "spec ");
1520 fprintf (f, "type %s %s",
1521 ltoken_getTextChars (ti->id), sort_getName (ti->basedOn));
1525 fprintf (f, " mutable\n");
1527 fprintf (f, " immutable\n");
1530 fprintf (f, " exposed\n");
1534 vi = (se->info).var;
1537 fprintf (f, "%%LCL");
1540 if (!lco && !vi->export)
1542 fprintf (f, "spec ");
1547 fprintf (f, "const %s %s\n",
1548 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1551 fprintf (f, "var %s %s\n",
1552 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1555 fprintf (f, "enumConst %s %s\n",
1556 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1564 fprintf (f, "global %s %s\n", ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1566 case VRK_PRIVATE: /* for private vars within function */
1567 fprintf (f, "local %s %s\n",
1568 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1571 fprintf (f, "let %s %s\n",
1572 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1575 fprintf (f, "param %s %s\n",
1576 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1579 fprintf (f, "quant %s %s\n",
1580 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1584 /*@=loopswitchbreak@*/
1585 /*@=switchswitchbreak@*/
1592 static /*@exposed@*/ /*@out@*/ idTableEntry *
1593 nextFree (idTable * st)
1596 unsigned int n = st->size;
1598 if (n >= st->allocated)
1601 ** this loses with the garbage collector
1602 ** (and realloc is notoriously dangerous)
1604 ** st->entries = (idTableEntry *) LSLMoreMem (st->entries, (n + DELTA)
1605 ** * sizeof (idTableEntry));
1607 ** instead, we copy the symtable...
1610 idTableEntry *oldentries = st->entries;
1613 st->entries = dmalloc ((n+DELTA) * sizeof (*st->entries));
1615 for (i = 0; i < n; i++)
1617 st->entries[i] = oldentries[i];
1622 st->allocated = n + DELTA;
1625 ret = &(st->entries[st->size]);
1631 static /*@dependent@*/ /*@null@*/ idTableEntry *
1632 symtable_lookup (idTable *st, lsymbol id)
1637 for (n = st->size - 1; n >= 0; n--)
1639 e = &(st->entries[n]);
1641 /*@-loopswitchbreak@*/
1647 if (ltoken_getText (e->info.fct->id) == id) return e;
1650 if (ltoken_getText (e->info.type->id) == id) return e;
1653 if (ltoken_getText (e->info.var->id) == id) return e;
1657 /*@=loopswitchbreak@*/
1660 return (idTableEntry *) 0;
1664 static /*@dependent@*/ /*@null@*/ idTableEntry *
1665 symtable_lookupInScope (idTable *st, lsymbol id)
1669 for (n = st->size - 1; n >= 0; n--)
1671 e = &(st->entries[n]);
1672 if (e->kind == SYMK_SCOPE)
1674 if (ltoken_getText (e->info.fct->id) == id)
1679 return (idTableEntry *) 0;
1682 /* hash table implementation */
1685 htData_key (htData * x)
1687 /* assume x points to a valid htData struct */
1691 return x->content.sort;
1693 { /* get the textSym of the token */
1694 nameNode n = (x->content.op)->name;
1698 return ltoken_getText (n->content.opid);
1702 llassert (n->content.opform != NULL);
1703 return (n->content.opform)->key;
1707 return ltoken_getText ((x->content).tag->id);
1712 static void htData_free (/*@null@*/ /*@only@*/ htData *d)
1721 /* nameNode_free (d->content.op->name);*/
1722 sigNodeSet_free (d->content.op->signatures);
1726 switch (d->content.tag->kind)
1733 ** no: stDeclNodeList_free (d->content.tag->content.decls);
1736 /*@switchbreak@*/ break;
1739 /* no: ltokenList_free (d->content.tag->content.enums);
1743 /*@switchbreak@*/ break;
1752 static void bucket_free (/*@null@*/ /*@only@*/ bucket *b)
1756 bucket_free (b->next);
1757 htData_free (b->data);
1762 static void symHashTable_free (/*@only@*/ symHashTable *h)
1766 for (i = 0; i < h->size; i++)
1768 bucket_free (h->buckets[i]);
1775 static /*@only@*/ symHashTable *
1776 symHashTable_create (unsigned int size)
1779 symHashTable *t = (symHashTable *) dmalloc (sizeof (*t));
1781 t->buckets = (bucket **) dmalloc ((size + 1) * sizeof (*t->buckets));
1785 for (i = 0; i <= size; i++)
1787 t->buckets[i] = (bucket *) NULL;
1793 static /*@null@*/ /*@exposed@*/ htData *
1794 symHashTable_get (symHashTable *t, symbolKey key, infoKind kind, /*@null@*/ nameNode n)
1800 b = t->buckets[MASH (key, kind)];
1801 if (b == (bucket *) 0)
1803 return ((htData *) 0);
1806 for (entry = (htEntry *) b; entry != NULL; entry = entry->next)
1810 if (d->kind == kind && htData_key (d) == key)
1811 if (kind != IK_OP || sameNameNode (n, d->content.op->name))
1816 return ((htData *) 0);
1820 symHashTable_put (symHashTable *t, /*@only@*/ htData *data)
1822 /* if key is already taken, don't insert, return FALSE
1823 else insert it and return TRUE. */
1829 key = htData_key (data);
1832 if (kind == IK_OP && (!data->content.op->name->isOpId))
1834 name = data->content.op->name;
1838 name = (nameNode) 0;
1841 oldd = symHashTable_get (t, key, kind, name);
1843 if (oldd == (htData *) 0)
1846 bucket *new_entry = (bucket *) dmalloc (sizeof (*new_entry));
1847 bucket *b = (t->buckets[MASH (key, kind)]);
1848 htEntry *entry = (htEntry *) b;
1851 new_entry->data = data;
1852 new_entry->next = entry;
1853 t->buckets[MASH (key, kind)] = new_entry;
1866 static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
1867 symHashTable_forcePut (symHashTable *t, /*@only@*/ htData *data)
1869 /* Put data in, return old value */
1873 htEntry *entry, *new_entry;
1877 key = htData_key (data);
1880 if (kind == IK_OP && (!data->content.op->name->isOpId))
1882 name = data->content.op->name;
1886 name = (nameNode) 0;
1889 oldd = symHashTable_get (t, key, kind, name);
1891 if (oldd == (htData *) 0)
1893 new_entry = (htEntry *) dmalloc (sizeof (*new_entry));
1896 b = t->buckets[MASH (key, kind)];
1900 new_entry->data = data;
1901 new_entry->next = entry;
1902 t->buckets[MASH (key, kind)] = new_entry;
1908 { /* modify in place */
1909 *oldd = *data; /* copy new info over to old info */
1911 /* dangerous: if the data is the same, don't free it */
1925 symHashTable_count (symHashTable * t)
1933 symHashTable_printStats (symHashTable * t)
1935 int i, bucketCount, setsize, sortCount, opCount, tagCount;
1936 int sortTotal, opTotal, tagTotal;
1948 /* for debugging only */
1949 printf ("\n Printing symHashTable stats ... \n");
1950 for (i = 0; i <= HT_MAXINDEX; i++)
1954 for (entry = b; entry != NULL; entry = entry->next)
1962 /*@switchbreak@*/ break;
1965 cstring name = nameNode_unparse (d->content.op->name);
1966 cstring sigs = sigNodeSet_unparse (d->content.op->signatures);
1969 setsize = sigNodeSet_size (d->content.op->signatures);
1970 printf (" Op (%d): %s %s\n", setsize,
1971 cstring_toCharsSafe (name),
1972 cstring_toCharsSafe (sigs));
1973 cstring_free (name);
1974 cstring_free (sigs);
1975 /*@switchbreak@*/ break;
1979 /*@switchbreak@*/ break;
1982 if (bucketCount > 0)
1984 printf (" Bucket %d has count = %d; opCount = %d; sortCount = %d; tagCount = %d\n", i, bucketCount, opCount, sortCount, tagCount);
1985 sortTotal += sortCount;
1986 tagTotal += tagCount;
1990 printf ("SymHashTable has total count = %d, opTotal = %d, sortTotal = %d, tagTotal = %d :\n", t->count, opTotal, sortTotal, tagTotal);
1995 symtable_printStats (symtable s)
1997 symHashTable_printStats (s->hTable);
1998 /* for debugging only */
1999 printf ("idTable size = %d; allocated = %d\n",
2000 s->idTable->size, s->idTable->allocated);
2004 tagKind_unparse (tagKind k)
2010 return cstring_makeLiteral ("struct");
2013 return cstring_makeLiteral ("union");
2015 return cstring_makeLiteral ("enum");
2020 static void tagInfo_free (/*@only@*/ tagInfo tag)
2025 /*@observer@*/ sigNodeSet
2026 symtable_possibleOps (symtable tab, nameNode n)
2028 opInfo oi = symtable_opInfo (tab, n);
2030 if (opInfo_exists (oi))
2032 return (oi->signatures);
2035 return sigNodeSet_undefined;
2039 symtable_opExistsWithArity (symtable tab, nameNode n, int arity)
2041 opInfo oi = symtable_opInfo (tab, n);
2043 if (opInfo_exists (oi))
2045 sigNodeSet sigs = oi->signatures;
2046 sigNodeSet_elements (sigs, sig)
2048 if (ltokenList_size (sig->domain) == arity)
2050 } end_sigNodeSet_elements;
2056 domainMatches (ltokenList domain, sortSetList argSorts)
2058 /* expect their length to match */
2059 /* each domain sort in op must be an element of
2060 the corresponding set in argSorts. */
2061 bool matched = TRUE;
2064 sortSetList_reset (argSorts);
2065 ltokenList_elements (domain, dom)
2067 s = sort_fromLsymbol (ltoken_getText (dom));
2068 if (!(sortSet_member (sortSetList_current (argSorts), s)))
2070 /* printf (" mismatched element is: %s in %s\n", ltoken_getTextChars (*dom),
2071 sortSet_unparse (sortSetList_current (argSorts))); */
2075 sortSetList_advance (argSorts);
2076 } end_ltokenList_elements;
2082 symtable_opsWithLegalDomain (symtable tab, /*@temp@*/ /*@null@*/ nameNode n,
2083 sortSetList argSorts, sort qual)
2085 /* handles nil qual */
2086 lslOpSet ops = lslOpSet_new ();
2091 llassert (n != NULL);
2092 oi = symtable_opInfo (tab, n);
2094 if (opInfo_exists (oi))
2096 sigNodeSet sigs = oi->signatures;
2098 sigNodeSet_elements (sigs, sig)
2100 if (ltokenList_size (sig->domain) == sortSetList_size (argSorts))
2102 rangeSort = sigNode_rangeSort (sig);
2104 if ((qual == 0) || (sort_equal (&rangeSort, &qual)))
2106 if (domainMatches (sig->domain, argSorts))
2108 op = (lslOp) dmalloc (sizeof (*op));
2110 /* each domain sort in op must be an element of
2111 the corresponding set in argSorts. */
2112 op->signature = sig;
2113 op->name = nameNode_copy (n);
2114 (void) lslOpSet_insert (ops, op);
2118 } end_sigNodeSet_elements;