]> andersk Git - splint.git/blame - src/symtable.c
Updated README version number. (Testing sourceforge)
[splint.git] / src / symtable.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 University of Virginia,
616915dd 4** Massachusetts Institute of Technology
5**
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.
10**
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.
15**
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.
19**
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
23*/
24/*
25** symtable.c
26**
27** Symbol table abstraction
28**
29** AUTHORS:
30**
31** Gary Feldman, Technical Languages and Environments, DECspec project
32** Steve Garland,
33** Massachusetts Institute of Technology
34** Joe Wild, Technical Languages and Environments, DECspec project
35** Yang Meng Tan,
36** Massachusetts Institute of Technology
37**
38** CREATION DATE:
39**
40** 20 January 1991
41*/
42
43# include "lclintMacros.nf"
44# include "llbasic.h"
45# include "gram.h"
46# include "lclscan.h"
47# include "lclsyntable.h"
48# include "lslparse.h"
49
50/*@+ignorequals@*/
51
52static bool isBlankLine (char *p_line);
53static bool inImport = FALSE;
54
55/*@constant static int MAXBUFFLEN;@*/
56# define MAXBUFFLEN 512
57/*@constant static int DELTA;@*/
58# define DELTA 100
59
60static void symHashTable_dump (symHashTable * p_t, FILE * p_f, bool p_lco);
61
62static void tagInfo_free (/*@only@*/ tagInfo p_tag);
63static /*@observer@*/ scopeInfo symtable_scopeInfo (symtable p_stable);
64
65static void symtable_dumpId (symtable p_stable, FILE *p_f, bool p_lco);
66static lsymbol nameNode2key (nameNode p_n);
67
68typedef enum
69{
70 SYMK_FCN, SYMK_SCOPE, SYMK_TYPE, SYMK_VAR
71} symKind;
72
73typedef struct
74{
75 symKind kind;
76 union
77 {
78 /*@only@*/ fctInfo fct;
79 /*@only@*/ scopeInfo scope;
80 /*@only@*/ typeInfo type;
81 /*@only@*/ varInfo var;
82 } info;
83} idTableEntry;
84
28bf4b0b 85typedef struct
616915dd 86{
87 unsigned int size;
88 unsigned int allocated;
89 /*@relnull@*/ idTableEntry *entries;
90 bool exporting;
91} idTable;
92
28bf4b0b 93struct s_symtableStruct
616915dd 94{
95 idTable *idTable; /* data is idTableEntry */
96 symHashTable *hTable; /* data is htData */
28bf4b0b 97 mapping type2sort; /* maps LCL type symbol to LSL sort */
616915dd 98} ;
99
100static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *p_x);
101static /*@out@*/ /*@exposed@*/ idTableEntry *nextFree (idTable * p_st);
102static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookup (idTable * p_st, lsymbol p_id);
103static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookupInScope (idTable * p_st, lsymbol p_id);
104
105static /*@only@*/ idTable *symtable_newIdTable (void);
106static void idTableEntry_free (idTableEntry p_x);
107
108/* Local implementatio of hash table */
109
110static bool allowed_redeclaration = FALSE;
111static symbolKey htData_key (htData *p_x);
112
113static void symHashTable_free (/*@only@*/ symHashTable *p_h);
114static /*@only@*/ symHashTable *symHashTable_create (unsigned int p_size);
115static /*@null@*/ /*@exposed@*/ htData *
116 symHashTable_get (symHashTable * p_t, symbolKey p_key, infoKind p_kind,
117 /*@null@*/ nameNode p_n);
118static bool symHashTable_put (symHashTable *p_t, /*@only@*/ htData *p_data);
119static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
120 symHashTable_forcePut (symHashTable * p_t, /*@only@*/ htData *p_data);
121/* static unsigned int symHashTable_count (symHashTable * t); */
122
123static void idTable_free (/*@only@*/ idTable *p_st);
124
125void varInfo_free (/*@only@*/ varInfo v)
126{
28bf4b0b 127 ltoken_free (v->id);
616915dd 128 sfree (v);
129}
130
131static /*@only@*/ varInfo varInfo_copy (varInfo v)
132{
133 varInfo ret = (varInfo) dmalloc (sizeof (*ret));
134
135 ret->id = ltoken_copy (v->id);
136 ret->sort = v->sort;
137 ret->kind = v->kind;
138 ret->export = v->export;
139
140 return ret;
141}
142
143void symtable_free (symtable stable)
144{
145 /* symtable_printStats (stable); */
146
147 idTable_free (stable->idTable);
148 symHashTable_free (stable->hTable);
149 mapping_free (stable->type2sort);
150 sfree (stable);
151}
152
153static void idTable_free (idTable *st)
154{
155 unsigned int i;
156
157 for (i = 0; i < st->size; i++)
158 {
159 idTableEntry_free (st->entries[i]);
160 }
161
162 sfree (st->entries);
163 sfree (st);
164}
165
166static void fctInfo_free (/*@only@*/ fctInfo f)
167{
168 signNode_free (f->signature);
169 pairNodeList_free (f->globals);
170 ltoken_free (f->id);
171 sfree (f);
172}
173
174static void typeInfo_free (/*@only@*/ typeInfo t)
175{
28bf4b0b 176 ltoken_free (t->id);
616915dd 177 sfree (t);
178}
179
180static void scopeInfo_free (/*@only@*/ scopeInfo s)
181{
182 sfree (s);
183}
184
185static void idTableEntry_free (idTableEntry x)
186{
187 switch (x.kind)
188 {
189 case SYMK_FCN:
190 fctInfo_free (x.info.fct);
191 break;
192 case SYMK_SCOPE:
193 scopeInfo_free (x.info.scope);
194 break;
195 case SYMK_TYPE:
196 typeInfo_free (x.info.type);
197 break;
198 case SYMK_VAR:
199 varInfo_free (x.info.var);
200 break;
201 }
202}
203
204static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *x)
205{
206 switch (x->kind)
207 {
208 case SYMK_FCN:
209 return (x->info.fct->id);
210 case SYMK_SCOPE:
211 return ltoken_undefined;
212 case SYMK_TYPE:
213 return (x->info.type->id);
214 case SYMK_VAR:
215 return (x->info.var->id);
216 }
217
8250fa4a 218 BADBRANCHRET (ltoken_undefined);
616915dd 219}
220
221/*@only@*/ symtable
222symtable_new (void)
223{
224 symtable stable = (symtable) dmalloc (sizeof (*stable));
225 idTableEntry *e;
226
227 stable->idTable = symtable_newIdTable ();
228 stable->hTable = symHashTable_create (HT_MAXINDEX);
229 stable->type2sort = mapping_create ();
230
231 /* add builtin synonym: Bool -> bool */
232
233 mapping_bind (stable->type2sort, lsymbol_getBool (), lsymbol_getbool ());
234
235 /*
236 ** done by symtable_newIdTable
237 ** st->allocated = 0;
238 ** st->entries = (idTableEntry *) 0;
239 ** st->exporting = TRUE;
240 */
241
242 /* this is global scope */
243 e = nextFree (stable->idTable);
244 e->kind = SYMK_SCOPE;
245 (e->info).scope = (scopeInfo) dmalloc (sizeof (*((e->info).scope)));
246 (e->info).scope->kind = SPE_GLOBAL;
247
248 return stable;
249}
250
251static /*@only@*/ idTable *symtable_newIdTable (void)
252{
253 idTable *st = (idTable *) dmalloc (sizeof (*st));
254
255 st->size = 0;
256 st->allocated = 0;
257 st->entries = (idTableEntry *) 0;
258 st->exporting = TRUE;
259
260 /* this was being done twice!
261 e = nextFree (st);
262 e->kind = SYMK_SCOPE;
263 (e->info).scope.kind = globScope;
264 */
265
266 return st;
267}
268
269static lsymbol
270nameNode2key (nameNode n)
271{
272 unsigned int ret;
273
274 if (n->isOpId)
275 {
276 ret = ltoken_getText (n->content.opid);
277 }
278 else
279 {
280 /* use opForm's key as its Identifier */
281 llassert (n->content.opform != NULL);
282 ret = (n->content.opform)->key;
283 }
284
285 return ret;
286}
287
288/*
289** requires: nameNode n is already in st.
290*/
291
292static bool
293htData_insertSignature (htData *d, /*@owned@*/ sigNode oi)
294{
295 sigNodeSet set = d->content.op->signatures;
296
297
298 if (oi != (sigNode) 0)
299 {
300 return (sigNodeSet_insert (set, oi));
301 }
302 return FALSE;
303}
304
305void
306symtable_enterOp (symtable st, /*@only@*/ /*@notnull@*/ nameNode n,
307 /*@owned@*/ sigNode oi)
308{
309 /*
310 ** Operators are overloaded, we allow entering opInfo more than once,
311 ** even if it's the same signature.
312 **
313 ** Assumes all sorts are already entered into the symbol table
314 */
315
316 symHashTable *ht = st->hTable;
317 htData *d;
318 lsymbol id;
319
320
321
322 id = nameNode2key (n);
323
324 d = symHashTable_get (ht, id, IK_OP, n);
325
326 if (d == (htData *) 0)
327 { /* first signature of this operator */
328 opInfo op = (opInfo) dmalloc (sizeof (*op));
329 htData *nd = (htData *) dmalloc (sizeof (*nd));
330
331 op->name = n;
332
333 if (oi != (sigNode) 0)
334 {
335 op->signatures = sigNodeSet_singleton (oi);
336 ht->count++;
337 }
338 else
339 {
340 op->signatures = sigNodeSet_new ();
341 sigNode_markOwned (oi);
342 }
343
344 nd->kind = IK_OP;
345 nd->content.op = op;
346 (void) symHashTable_put (ht, nd);
347 }
348 else
349 {
350
351 nameNode_free (n); /*<<<??? */
352
353 if (htData_insertSignature (d, oi))
354 {
355 ht->count++;
356 }
357 }
358}
359
360bool
361 symtable_enterTag (symtable st, tagInfo ti)
362{
363 /* put ti only if it is not already in symtable */
364 symHashTable *ht = st->hTable;
365 htData *d;
366 symbolKey key = ltoken_getText (ti->id);
367
368 d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
369 if (d == (htData *) 0)
370 {
371 d = (htData *) dmalloc (sizeof (*d));
372 d->kind = IK_TAG;
373 d->content.tag = ti;
374 d->content.tag->imported = context_inImport ();
375 (void) symHashTable_put (ht, d);
376 return TRUE;
377 }
378 else
379 {
380 if (d->content.tag->imported)
381 {
382 d->content.tag = ti;
383 d->content.tag->imported = context_inImport ();
384 return TRUE;
385 }
386 else
387 {
388 tagInfo_free (ti);
389 return FALSE;
390 }
391 }
392}
393
394bool
395symtable_enterTagForce (symtable st, tagInfo ti)
396{
397 /* put ti, force-put if necessary */
398 symHashTable *ht = st->hTable;
399 htData *d;
400 symbolKey key = ltoken_getText (ti->id);
401
402 d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
403
404 if (d == (htData *) 0)
405 {
406 d = (htData *) dmalloc (sizeof (*d));
407
408 d->kind = IK_TAG;
409 d->content.tag = ti;
410 d->content.tag->imported = context_inImport ();
411 (void) symHashTable_put (ht, d);
412 return TRUE;
413 }
414 else
415 {
416
417 d->kind = IK_TAG;
418 d->content.tag = ti;
419 d->content.tag->imported = context_inImport ();
420 /* interpret return data later, htData * */
421 /*@i@*/ (void) symHashTable_forcePut (ht, d);
422 return FALSE;
423 }
424}
425
426/*@null@*/ opInfo
427symtable_opInfo (symtable st, /*@notnull@*/ nameNode n)
428{
429 symHashTable *ht = st->hTable;
430 lsymbol i = nameNode2key (n);
431
432 htData *d;
433 d = symHashTable_get (ht, i, IK_OP, n);
434 if (d == (htData *) 0)
435 {
436 return (opInfo)NULL;
437 }
438
439 return (d->content.op);
440}
441
442/*@null@*/ tagInfo
443symtable_tagInfo (symtable st, lsymbol i)
444{
445 symHashTable *ht = st->hTable;
446 htData *d;
447 d = symHashTable_get (ht, i, IK_TAG, 0);
448
449 if (d == (htData *) 0)
450 {
451 return (tagInfo) NULL;
452 }
453
454 return (d->content.tag);
455}
456
457void
458 symtable_enterScope (symtable stable, scopeInfo si)
459{
460 idTable *st = stable->idTable;
461 idTableEntry *e = nextFree (st);
462 if (si->kind == SPE_GLOBAL)
463 llbuglit ("symtable_enterScope: SPE_GLOBAL");
464 e->kind = SYMK_SCOPE;
465 (e->info).scope = si;
466}
467
468void
469symtable_exitScope (symtable stable)
470{
471 idTable *st = stable->idTable;
472 int n;
473
474 if (st->entries != NULL)
475 {
476 for (n = st->size - 1; (st->entries[n]).kind != SYMK_SCOPE; n--)
477 {
478 ;
479 }
480 }
481 else
482 {
483 llcontbuglit ("symtable_exitScope: no scope to exit");
484 n = 0;
485 }
486
487 st->size = n;
488}
489
490bool
491symtable_enterFct (symtable stable, fctInfo fi)
492{
493 idTable *st = stable->idTable;
494 idTableEntry *e;
495 bool redecl = FALSE;
496
497 if (!allowed_redeclaration &&
498 symtable_lookup (st, ltoken_getText (fi->id)) != (idTableEntry *) 0)
499 {
500 lclRedeclarationError (fi->id);
501 redecl = TRUE;
502 }
503
504 e = nextFree (st);
505 e->kind = SYMK_FCN;
506 fi->export = st->exporting; /* && !fi->private; */
507 (e->info).fct = fi;
508
509 return redecl;
510}
511
512void
513symtable_enterType (symtable stable, /*@only@*/ typeInfo ti)
514{
515 idTable *st = stable->idTable;
516 idTableEntry *e;
517 bool insertp = TRUE;
518 scopeKind k = (symtable_scopeInfo (stable))->kind;
519
520 /* symtable_disp (stable); */
521
522 if (k != SPE_GLOBAL && k != SPE_INVALID) /* fixed for LCLint */
523 {
524 llbug (message ("%q: symtable_enterType: expect global scope. (type: %s)",
525 ltoken_unparseLoc (ti->id),
526 ltoken_getRawString (ti->id)));
527 }
528
529 if (!allowed_redeclaration &&
530 symtable_lookup (st, ltoken_getText (ti->id)) != (idTableEntry *) 0)
531 {
532 /* ignore if Bool is re-entered */
533 if (ltoken_getText (ti->id) == lsymbol_getBool () ||
534 ltoken_getText (ti->id) == lsymbol_getbool ())
535 {
536 insertp = FALSE;
537 }
538 else
539 {
540 lclRedeclarationError (ti->id);
541 }
542 }
543 if (insertp)
544 {
545 /* make sure it is a type TYPEDEF_NAME; */
546
547 if (ltoken_getCode (ti->id) != LLT_TYPEDEF_NAME)
548 {
549 lclbug (message ("symtable_enterType: gets a simpleId, expect a type: %s",
550 ltoken_getRawString (ti->id)));
551 }
552
553 e = nextFree (st);
554 e->kind = SYMK_TYPE;
555 ti->export = st->exporting;/* && !ti->private; */
556 (e->info).type = ti;
557 mapping_bind (stable->type2sort, ltoken_getText (ti->id),
558 sort_getLsymbol (sort_makeVal (sort_getUnderlying (ti->basedOn))));
559 }
560 else
561 {
562 typeInfo_free (ti);
563 }
564}
565
566lsymbol
567lsymbol_sortFromType (symtable s, lsymbol typename)
568{
569 lsymbol inter;
570 lsymbol out;
571 ltoken tok;
572 /* check the synonym table first */
573 if (LCLIsSyn (typename))
574 {
575 tok = LCLGetTokenForSyn (typename);
576 inter = ltoken_getText (tok);
577 /* printf ("In lsymbol_sortFromType: %s -> %s\n",
578 lsymbol_toChars (typename), lsymbol_toChars (inter)); */
579 }
580 else
581 {
582 inter = typename;
583 }
584
585 /* now map LCL type to sort */
586 out = mapping_find (s->type2sort, inter);
587
588 if (out == lsymbol_undefined)
589 {
590 return inter;
591 }
592
593 return out;
594}
595
596/* really temp! */
597
598/*
599** returns true is vi is a redeclaration
600*/
601
602bool
603symtable_enterVar (symtable stable, /*@temp@*/ varInfo vi)
604{
605 idTable *st = stable->idTable;
606 bool insertp = TRUE;
607 bool redecl = FALSE;
608
609
610 /* symtable_disp (symtab); */
611
612 if (!allowed_redeclaration &&
613 (symtable_lookupInScope (st, ltoken_getText (vi->id)) != (idTableEntry *) 0))
614 {
615 if (ltoken_getText (vi->id) == lsymbol_getTRUE () ||
616 ltoken_getText (vi->id) == lsymbol_getFALSE ())
617 {
618 insertp = FALSE;
619 }
620 else
621 {
622 if (usymtab_existsEither (ltoken_getRawString (vi->id)))
623 {
624 lclRedeclarationError (vi->id);
625 redecl = TRUE;
626 }
627 else
628 {
629 llbuglit ("redeclared somethingerother?!");
630 }
631 }
632 }
633
634 if (insertp)
635 {
636 idTableEntry *e = nextFree (st);
637
638 e->kind = SYMK_VAR;
639 vi->export = st->exporting && /* !vi.private && */
640 (vi->kind == VRK_VAR || vi->kind == VRK_CONST || vi->kind == VRK_ENUM);
641 (e->info).var = varInfo_copy (vi);
642 }
643
644 return (redecl);
645}
646
647bool
648symtable_exists (symtable stable, lsymbol i)
649{
650 idTable *st = stable->idTable;
651 return symtable_lookup (st, i) != (idTableEntry *) 0;
652}
653
654/*@null@*/ typeInfo
655symtable_typeInfo (symtable stable, lsymbol i)
656{
657 idTable *st;
658 idTableEntry *e;
659
660 st = stable->idTable;
661 e = symtable_lookup (st, i);
662
663 if (e == (idTableEntry *) 0 || e->kind != SYMK_TYPE)
664 {
665 return (typeInfo) NULL;
666 }
667
668 return (e->info).type;
669}
670
671/*@null@*/ varInfo
672symtable_varInfo (symtable stable, lsymbol i)
673{
674 idTable *st = stable->idTable;
675 idTableEntry *e;
676
677 e = symtable_lookup (st, i);
678
679 if (e == (idTableEntry *) 0 || e->kind != SYMK_VAR)
680 {
681 return (varInfo) NULL;
682 }
683
684 return (e->info).var;
685}
686
687/*@null@*/ varInfo
688symtable_varInfoInScope (symtable stable, lsymbol id)
689{
690 /* if current scope is a SPE_QUANT, can go beyond current scope */
691 idTable *st = stable->idTable;
692 idTableEntry *e2 = (idTableEntry *) 0;
693 int n;
694
695 for (n = st->size - 1; n >= 0; n--)
696 {
697 ltoken tok;
698
699 e2 = &(st->entries[n]);
700
701 if (e2->kind == SYMK_SCOPE && e2->info.scope->kind != SPE_QUANT)
702 {
703 return (varInfo) NULL;
704 }
705
706 tok = idTableEntry_getId (e2);
707
708 if (e2->kind == SYMK_VAR && ltoken_getText (tok) == id)
709 {
710 return (e2->info).var;
711 }
712 }
713
714 return (varInfo) NULL;
715}
716
717scopeInfo
718symtable_scopeInfo (symtable stable)
719{
720 idTable *st = stable->idTable;
721 int n;
722 idTableEntry *e;
723
724 for (n = st->size - 1; n >= 0; n--)
725 {
726 e = &(st->entries[n]);
727 if (e->kind == SYMK_SCOPE)
728 return (e->info).scope;
729 }
730
731 lclfatalbug ("symtable_scopeInfo: not found");
732 BADEXIT;
733}
734
735void
736symtable_export (symtable stable, bool yesNo)
737{
738 idTable *st = stable->idTable;
739 st->exporting = yesNo;
740 (void) sort_setExporting (yesNo);
741}
742
743static void
744symHashTable_dump (symHashTable * t, FILE * f, bool lco)
745{
746 /* like symHashTable_dump2 but for output to .lcs file */
747 int i, size;
748 bucket *b;
749 htEntry *entry;
750 htData *d;
751 ltoken tok;
752 sigNodeSet sigs;
753
754 for (i = 0; i <= HT_MAXINDEX; i++)
755 {
756 b = t->buckets[i];
757
758 for (entry = b; entry != NULL; entry = entry->next)
759 {
760 d = entry->data;
761
762 switch (d->kind)
763 {
764 case IK_SORT:
765 /*@switchbreak@*/ break;
766 case IK_OP:
767 {
768 char *name = cstring_toCharsSafe (nameNode_unparse (d->content.op->name));
769 sigs = d->content.op->signatures;
770 size = sigNodeSet_size (sigs);
771
772
773 sigNodeSet_elements (sigs, x)
774 {
775 cstring s = sigNode_unparse (x);
776
777 if (lco)
778 {
779 fprintf (f, "%%LCL");
780 }
781
782 fprintf (f, "op %s %s\n", name, cstring_toCharsSafe (s));
783 cstring_free (s);
784 } end_sigNodeSet_elements;
785
786 sfree (name);
787 /*@switchbreak@*/ break;
788 }
789 case IK_TAG:
790 tok = d->content.tag->id;
791
792 if (!ltoken_isUndefined (tok))
793 {
794 cstring s = tagKind_unparse (d->content.tag->kind);
795
796 if (lco)
797 {
798 fprintf (f, "%%LCL");
799 }
800
801 fprintf (f, "tag %s %s\n", ltoken_getTextChars (tok),
802 cstring_toCharsSafe (s));
803 cstring_free (s);
804 }
805 /*@switchbreak@*/ break;
806 }
807 }
808 }
809}
810
811void
812symtable_dump (symtable stable, FILE * f, bool lco)
813{
814 symHashTable *ht = stable->hTable;
815
816
817 fprintf (f, "%s\n", BEGINSYMTABLE);
818
819 symHashTable_dump (ht, f, lco);
820
821 symtable_dumpId (stable, f, lco);
822
823 fprintf (f, "%s\n", SYMTABLEEND);
824 }
825
826lsymbol
28bf4b0b 827lsymbol_translateSort (mapping m, lsymbol s)
616915dd 828{
829 lsymbol res = mapping_find (m, s);
830 if (res == lsymbol_undefined)
831 return s;
832 return res;
833}
834
835static /*@null@*/ lslOp
28bf4b0b 836 lslOp_renameSorts (mapping map,/*@returned@*/ /*@null@*/ lslOp op)
616915dd 837{
838 sigNode sign;
839
840 if (op != (lslOp) 0)
841 {
842 ltokenList domain;
843 ltoken range;
844
845 sign = op->signature;
846 range = sign->range;
847 domain = sign->domain;
848
849 ltokenList_elements (domain, dt)
850 {
851 ltoken_setText (dt,
852 lsymbol_translateSort (map, ltoken_getText (dt)));
853 } end_ltokenList_elements;
854
855 /*@-onlytrans@*/ /* A memory leak... */
856 op->signature = makesigNode (sign->tok, domain, range);
857 /*@=onlytrans@*/
858 }
859
860 return op;
861}
862
863static /*@null@*/ signNode
864 signNode_fromsigNode (sigNode s)
865{
866 signNode sign;
867 sortList slist;
868
869 if (s == (sigNode) 0)
870 {
871 return (signNode) 0;
872 }
873
874 sign = (signNode) dmalloc (sizeof (*sign));
875 slist = sortList_new ();
876 sign->tok = ltoken_copy (s->tok);
877 sign->key = s->key;
878 sign->range = sort_makeSort (ltoken_undefined, ltoken_getText (s->range));
879
880 ltokenList_elements (s->domain, dt)
881 {
882 sortList_addh (slist, sort_makeSort (ltoken_undefined, ltoken_getText (dt)));
883 } end_ltokenList_elements;
884
885 sign->domain = slist;
886 return sign;
887}
888
889
890/** 2.4.3 ymtan 93.09.23 -- fixed bug in parseGlobals: removed ";" at the
891 ** end of pairNode (gstr).
892 */
893
894static /*@only@*/ pairNodeList
28bf4b0b 895parseGlobals (char *line, inputStream srce)
616915dd 896{
897 pairNodeList plist = pairNodeList_new ();
898 pairNode p;
899 int semi_index;
900 char *lineptr, sostr[MAXBUFFLEN], gstr[MAXBUFFLEN];
901
902 /* line is not all blank */
903 /* expected format: "sort1 g1; sort2 g2; sort3 g3;" */
904 lineptr = line;
905
906 while (!isBlankLine (lineptr))
907 {
908 if (sscanf (lineptr, "%s %s", &(sostr[0]), gstr) != 2)
909 {
910 lclplainerror
911 (message
912 ("%q: Imported file contains illegal function global declaration.\n"
913 "Skipping rest of the line: %s (%s)",
28bf4b0b 914 fileloc_unparseRaw (inputStream_fileName (srce),
915 inputStream_thisLineNumber (srce)),
616915dd 916 cstring_fromChars (line),
917 cstring_fromChars (lineptr)));
918 return plist;
919 }
920
921 p = (pairNode) dmalloc (sizeof (*p));
922
923 /* Note: remove the ";" separator at the end of gstr */
924 semi_index = size_toInt (strlen (gstr));
925 gstr[semi_index - 1] = '\0';
926
927 p->tok = ltoken_create (NOTTOKEN, lsymbol_fromChars (gstr));
928 p->sort = sort_makeSort (ltoken_undefined, lsymbol_fromChars (sostr));
929
930 pairNodeList_addh (plist, p);
931 lineptr = strchr (lineptr, ';'); /* go pass the next; */
932
933 llassert (lineptr != NULL);
934 lineptr = lineptr + 1;
935 }
936
937 return plist;
938}
939
940static bool
941isBlankLine (char *line)
942{
943 int i;
944
945 if (line == NULL) return TRUE;
946
947 for (i = 0; line[i] != '\0'; i++)
948 {
949 if (line[i] == ' ')
950 continue;
951 if (line[i] == '\t')
952 continue;
953 if (line[i] == '\n')
954 return TRUE;
955 return FALSE;
956 }
957 return TRUE;
958}
959
960typedef /*@only@*/ fctInfo o_fctInfo;
961
962static void
28bf4b0b 963parseLine (char *line, inputStream srce, mapping map)
616915dd 964{
965 static /*@owned@*/ o_fctInfo *savedFcn = NULL;
28bf4b0b 966 char *lineptr, *lineptr2;
967 cstring importfile = inputStream_fileName (srce);
616915dd 968 char namestr[MAXBUFFLEN], kstr[20], sostr[MAXBUFFLEN];
969 sort bsort, nullSort = sort_makeNoSort ();
970 int col = 0;
971 fileloc imploc = fileloc_undefined;
972
973
974 if (inImport)
975 {
28bf4b0b 976 imploc = fileloc_createImport (importfile, inputStream_thisLineNumber (srce));
616915dd 977 }
978
979 if (firstWord (line, "op"))
980 {
981 lslOp op;
982
983 lineptr = strchr (line, 'o'); /* remove any leading blanks */
984 llassert (lineptr != NULL);
985 lineptr = strchr (lineptr, ' '); /* go past "op" */
986 llassert (lineptr != NULL);
987
988 /* add a newline to the end of the line since parseOpLine expects it */
989 lineptr2 = strchr (lineptr, '\0');
990
991 if (lineptr2 != 0)
992 {
993 *lineptr2 = '\n';
994 *(lineptr2 + 1) = '\0';
995 }
996
28bf4b0b 997 llassert (cstring_isDefined (importfile));
998 op = parseOpLine (importfile, cstring_fromChars (lineptr + 1));
616915dd 999
1000 if (op == (lslOp) 0)
1001 {
1002 lclplainerror
1003 (message
1004 ("%q: Imported file contains illegal operator declaration:\n "
1005 "skipping this line: %s",
28bf4b0b 1006 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1007 cstring_fromChars (line)));
1008 fileloc_free (imploc);
1009 return;
1010 }
1011
1012 op = lslOp_renameSorts (map, op);
1013
1014 llassert (op != NULL);
1015 llassert (op->name != NULL);
1016
1017 symtable_enterOp (g_symtab, op->name,
1018 sigNode_copy (op->signature));
1019 /*@-mustfree@*/ } /*@=mustfree@*/
1020 else if (firstWord (line, "type"))
1021 {
1022 typeInfo ti;
1023
1024 if (sscanf (line, "type %s %s %s", namestr, sostr, kstr) != 3)
1025 {
1026 lclplainerror
1027 (message ("%q: illegal type declaration:\n skipping this line: %s",
28bf4b0b 1028 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1029 cstring_fromChars (line)));
1030 fileloc_free (imploc);
1031 return;
1032 }
1033
1034 ti = (typeInfo) dmalloc (sizeof (*ti));
1035 ti->id = ltoken_createFull (LLT_TYPEDEF_NAME, lsymbol_fromChars (namestr),
28bf4b0b 1036 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1037
1038 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1039
1040 if (sort_isNoSort (bsort))
1041 {
1042 lineptr = strchr (line, ' '); /* go past "type" */
1043 llassert (lineptr != NULL);
1044 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1045 llassert (lineptr != NULL);
1046 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1047
1048 lclbug (message ("%q: Imported files contains unknown base sort",
28bf4b0b 1049 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1050
1051 bsort = nullSort;
1052 }
1053 ti->basedOn = bsort;
1054
1055 if (strcmp (kstr, "exposed") == 0)
1056 {
1057 ti->abstract = FALSE;
1058 ti->modifiable = TRUE;
1059 }
1060 else
1061 {
1062 ti->abstract = TRUE;
1063 if (strcmp (kstr, "mutable") == 0)
1064 ti->modifiable = TRUE;
1065 else
1066 ti->modifiable = FALSE;
1067 }
1068 ti->export = TRUE;
1069
1070 /*
1071 ** sort of a hack to get imports to work...
1072 */
1073
1074 if (inImport)
1075 {
1076 cstring cnamestr = cstring_fromChars (namestr);
1077
1078 if (!usymtab_existsGlobEither (cnamestr))
1079 {
1080 (void) usymtab_addEntry
1081 (uentry_makeDatatype (cnamestr, ctype_unknown,
1082 ti->abstract ? ynm_fromBool (ti->modifiable) : MAYBE,
1083 ti->abstract ? YES : NO,
1084 fileloc_copy (imploc)));
1085 }
1086 }
1087
1088 symtable_enterType (g_symtab, ti);
1089 }
1090 else if (firstWord (line, "var"))
1091 {
1092 varInfo vi;
1093
1094 if (sscanf (line, "var %s %s", namestr, sostr) != 2)
1095 {
1096 lclplainerror
1097 (message ("%q: Imported file contains illegal variable declaration. "
1098 "Skipping this line.",
28bf4b0b 1099 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce))));
616915dd 1100 fileloc_free (imploc);
1101 return;
1102 }
1103
1104 vi = (varInfo) dmalloc (sizeof (*vi));
1105 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1106 lineptr = strchr (line, ' '); /* go past "var" */
1107 llassert (lineptr != NULL);
1108 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1109 llassert (lineptr != NULL);
1110 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1111
1112 if (sort_isNoSort (bsort))
1113 {
1114 lclplainerror (message ("%q: Imported file contains unknown base sort",
28bf4b0b 1115 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1116 bsort = nullSort;
1117 }
1118
1119 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1120 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1121 vi->sort = bsort;
1122 vi->kind = VRK_VAR;
1123 vi->export = TRUE;
1124 (void) symtable_enterVar (g_symtab, vi);
1125 varInfo_free (vi);
1126
1127 if (inImport)
1128 {
1129 cstring cnamestr = cstring_fromChars (namestr);
1130
1131 if (!usymtab_existsGlobEither (cnamestr))
1132 {
1133
1134 (void) usymtab_supEntrySref
1135 (uentry_makeVariable (cnamestr, ctype_unknown,
1136 fileloc_copy (imploc),
1137 FALSE));
1138 }
1139 }
1140 }
1141 else if (firstWord (line, "const"))
1142 {
1143 varInfo vi;
1144
1145 if (sscanf (line, "const %s %s", namestr, sostr) != 2)
1146 {
1147 lclbug (message ("%q: Imported file contains illegal constant declaration: %s",
28bf4b0b 1148 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1149 cstring_fromChars (line)));
1150 fileloc_free (imploc);
1151 return;
1152 }
1153
1154 vi = (varInfo) dmalloc (sizeof (*vi));
1155 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1156 lineptr = strchr (line, ' '); /* go past "var" */
1157 llassert (lineptr != NULL);
1158 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1159 llassert (lineptr != NULL);
1160
1161 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1162
1163 if (sort_isNoSort (bsort))
1164 {
1165 lclplainerror (message ("%q: Imported file contains unknown base sort",
28bf4b0b 1166 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1167 bsort = nullSort;
1168 }
1169
1170 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1171 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1172 vi->sort = bsort;
1173 vi->kind = VRK_CONST;
1174 vi->export = TRUE;
1175 (void) symtable_enterVar (g_symtab, vi);
1176 varInfo_free (vi);
1177
1178 if (inImport)
1179 {
1180 cstring cnamestr = cstring_fromChars (namestr);
1181
1182 if (!usymtab_existsGlobEither (cnamestr))
1183 {
1184
1185 (void) usymtab_addEntry (uentry_makeConstant (cnamestr,
1186 ctype_unknown,
1187 fileloc_copy (imploc)));
1188 }
1189 }
1190 /* must check for "fcnGlobals" before "fcn" */
1191 }
1192 else if (firstWord (line, "fcnGlobals"))
1193 {
1194 pairNodeList globals;
1195 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1196 llassert (lineptr != NULL);
1197 lineptr = strchr (lineptr, ' '); /* go past "fcnGlobals" */
1198 llassert (lineptr != NULL);
1199
1200 /* a quick check for empty fcnGlobals */
1201 if (!isBlankLine (lineptr))
1202 {
1203 globals = parseGlobals (lineptr, srce);
1204 /* should ensure that each global in an imported function
1205 corresponds to some existing global. Since only
1206 "correctly processed" .lcs files are imported, this is
1207 true as an invariant. */
1208 }
1209 else
1210 {
1211 globals = pairNodeList_new ();
1212 }
1213
1214 /* check that they exist, store them on fctInfo */
1215
1216 if (savedFcn != NULL)
1217 {
1218 pairNodeList_free ((*savedFcn)->globals);
1219 (*savedFcn)->globals = globals; /* evs, moved inside if predicate */
1220
1221 (void) symtable_enterFct (g_symtab, *savedFcn);
1222 savedFcn = NULL;
1223 }
1224 else
1225 {
1226 lclplainerror
1227 (message ("%q: Unexpected function globals. "
1228 "Skipping this line: \n%s",
28bf4b0b 1229 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1230 cstring_fromChars (line)));
1231 savedFcn = NULL;
1232 pairNodeList_free (globals);
1233 }
1234 }
1235 else if (firstWord (line, "fcn"))
1236 {
1237 lslOp op;
1238 lslOp op2;
1239
1240 if (savedFcn != (fctInfo *) 0)
1241 {
1242 lclplainerror
1243 (message ("%q: illegal function declaration. Skipping this line:\n%s",
28bf4b0b 1244 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1245 cstring_fromChars (line)));
1246 fileloc_free (imploc);
1247 return;
1248 }
1249
1250 savedFcn = (fctInfo *) dmalloc (sizeof (*savedFcn));
1251
1252 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1253 llassert (lineptr != NULL);
1254 lineptr = strchr (lineptr, ' '); /* go past "fcn" */
1255 llassert (lineptr != NULL);
1256
1257 /* add a newline to the end of the line since parseOpLine expects it */
1258
1259 lineptr2 = strchr (lineptr, '\0');
1260
1261 if (lineptr2 != 0)
1262 {
1263 *lineptr2 = '\n';
1264 *(lineptr2 + 1) = '\0';
1265 }
1266
28bf4b0b 1267 op = parseOpLine (importfile, cstring_fromChars (lineptr + 1));
616915dd 1268
1269 if (op == (lslOp) 0)
1270 {
28bf4b0b 1271 lclplainerror
1272 (message ("%q: illegal function declaration: %s",
1273 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
1274 cstring_fromChars (line)));
616915dd 1275 fileloc_free (imploc);
1276 return;
1277 }
1278
1279 op2 = lslOp_renameSorts (map, op);
1280
1281 llassert (op2 != NULL);
1282
1283 if ((op->name != NULL) && op->name->isOpId)
1284 {
1285 (*savedFcn) = (fctInfo) dmalloc (sizeof (**savedFcn));
1286 (*savedFcn)->id = op->name->content.opid;
1287 (*savedFcn)->signature = signNode_fromsigNode (op2->signature);
1288 (*savedFcn)->globals = pairNodeList_new ();
1289 (*savedFcn)->export = TRUE;
1290
1291 if (inImport)
1292 {
1293 /* 27 Jan 1995 --- added this to be undefined namestr bug */
1294 cstring fname = ltoken_unparse ((*savedFcn)->id);
1295
1296 if (!usymtab_existsGlobEither (fname))
1297 {
28bf4b0b 1298 (void) usymtab_addEntry (uentry_makeFunction
616915dd 1299 (fname, ctype_unknown,
1300 typeId_invalid, globSet_new (),
1301 sRefSet_undefined,
28bf4b0b 1302 warnClause_undefined,
616915dd 1303 fileloc_copy (imploc)));
1304 }
1305 }
1306 }
1307 else
1308 {
28bf4b0b 1309 /* evans 2001-05-27: detected by lclint after fixing external alias bug. */
1310 if (op->name != NULL)
1311 {
1312 ltoken_free (op->name->content.opid);
1313 }
1314
1315 lclplainerror
1316 (message ("%q: unexpected function name: %s",
1317 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
1318 cstring_fromChars (line)));
616915dd 1319 }
1320 }
1321 else if (firstWord (line, "enumConst"))
1322 {
1323 varInfo vi;
1324
1325 if (sscanf (line, "enumConst %s %s", namestr, sostr) != 2)
1326 {
1327 lclplainerror
1328 (message ("%q: Illegal enum constant declaration. "
1329 "Skipping this line:\n%s",
28bf4b0b 1330 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1331 cstring_fromChars (line)));
1332 fileloc_free (imploc);
1333 return;
1334 }
1335
1336 vi = (varInfo) dmalloc (sizeof (*vi));
1337 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1338 lineptr = strchr (line, ' '); /* go past "var" */
1339 llassert (lineptr != NULL);
1340 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1341 llassert (lineptr != NULL);
1342
1343 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
1344 if (sort_isNoSort (bsort))
1345 {
1346 lclplainerror (message ("%q: unknown base sort\n",
28bf4b0b 1347 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1348 bsort = nullSort;
1349 }
1350
1351 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1352 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1353
1354 vi->sort = bsort;
1355 vi->kind = VRK_ENUM;
1356 vi->export = TRUE;
1357 (void) symtable_enterVar (g_symtab, vi);
1358 varInfo_free (vi);
1359
1360 if (inImport)
1361 {
1362 cstring cnamestr = cstring_fromChars (namestr);
1363 if (!usymtab_existsEither (cnamestr))
1364 {
1365 (void) usymtab_addEntry (uentry_makeConstant (cnamestr, ctype_unknown,
1366 fileloc_copy (imploc)));
1367 }
1368 }
1369 }
1370 else if (firstWord (line, "tag"))
1371 {
1372 /* do nothing, sort processing already handles this */
1373 }
1374 else
1375 {
1376 lclplainerror
1377 (message ("%q: Unknown symbol declaration. Skipping this line:\n%s",
28bf4b0b 1378 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1379 cstring_fromChars (line)));
1380 }
1381
1382 fileloc_free (imploc);
1383}
1384
1385void
28bf4b0b 1386symtable_import (inputStream imported, ltoken tok, mapping map)
616915dd 1387{
28bf4b0b 1388 char *buf;
1389 cstring importfile;
1390 inputStream lclsource;
616915dd 1391 int old_lsldebug;
1392 bool old_inImport = inImport;
1393
28bf4b0b 1394 buf = inputStream_nextLine (imported);
1395 importfile = inputStream_fileName (imported);
616915dd 1396
1397 llassert (buf != NULL);
1398
1399 if (!firstWord (buf, "%LCLSymbolTable"))
1400 {
1401 lclsource = LCLScanSource ();
1402 lclfatalerror (tok,
1403 message ("Expecting '%%LCLSymbolTable' line in import file %s:\n%s\n",
28bf4b0b 1404 importfile,
616915dd 1405 cstring_fromChars (buf)));
1406 }
1407
1408 old_lsldebug = lsldebug;
1409 lsldebug = 0;
1410 allowed_redeclaration = TRUE;
1411 inImport = TRUE;
1412
1413 for (;;)
1414 {
28bf4b0b 1415 buf = inputStream_nextLine (imported);
616915dd 1416 llassert (buf != NULL);
1417
1418
1419 if (firstWord (buf, "%LCLSymbolTableEnd"))
1420 {
1421 break;
1422 }
1423 else
1424 { /* a good line, remove %LCL from line first */
1425 if (firstWord (buf, "%LCL"))
1426 {
1427 parseLine (buf + 4, imported, map);
1428 }
1429 else
1430 {
1431 lclsource = LCLScanSource ();
1432 lclfatalerror
1433 (tok,
1434 message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
28bf4b0b 1435 importfile,
616915dd 1436 cstring_fromChars (buf)));
1437 }
1438 }
1439 }
1440
1441 /* restore old value */
1442 inImport = old_inImport;
1443 lsldebug = old_lsldebug;
1444 allowed_redeclaration = FALSE;
1445 }
1446
1447static void
1448symtable_dumpId (symtable stable, FILE *f, bool lco)
1449{
1450 idTable *st = stable->idTable;
1451 unsigned int i;
1452 idTableEntry *se;
1453 fctInfo fi;
1454 typeInfo ti;
1455 varInfo vi;
1456
1457 for (i = 1; i < st->size; i++)
1458 {
1459 /* 2/22/93 I think there is a off-by-1 error, 0 entry is never used */
1460 se = st->entries + i;
1461 llassert (se != NULL);
1462
1463
1464 /*@-loopswitchbreak@*/
1465 switch (se->kind)
1466 {
1467 case SYMK_FCN:
1468 {
1469 cstring tmp;
1470
1471 fi = (se->info).fct;
1472
1473 if (lco)
1474 {
1475 fprintf (f, "%%LCL");
1476 }
1477
1478 if (!lco && !fi->export)
1479 {
1480 fprintf (f, "spec ");
1481 }
1482
1483 tmp = signNode_unparse (fi->signature);
1484 fprintf (f, "fcn %s %s \n", ltoken_getTextChars (fi->id),
1485 cstring_toCharsSafe (tmp));
1486 cstring_free (tmp);
1487
1488 tmp = pairNodeList_unparse (fi->globals);
1489 fprintf (f, "%%LCLfcnGlobals %s\n", cstring_toCharsSafe (tmp));
1490 cstring_free (tmp);
1491 break;
1492 }
1493 case SYMK_SCOPE:
1494 if (lco)
1495 {
1496 break;
1497 }
1498
1499 /*@-switchswitchbreak@*/
1500 switch ((se->info).scope->kind)
1501 {
1502 case SPE_GLOBAL:
1503 fprintf (f, "Global scope\n");
1504 break;
1505 case SPE_ABSTRACT:
1506 fprintf (f, "Abstract type scope\n");
1507 break;
1508 case SPE_FCN:
1509 fprintf (f, "Function scope\n");
1510 break;
1511 /* a let scope can only occur in a function scope, should not push
1512 a new scope, so symtable_lookupInScope works properly
1513 case letScope:
1514 fprintf (f, "Let scope\n");
1515 break; */
1516 case SPE_QUANT:
1517 fprintf (f, "Quantifier scope\n");
1518 break;
1519 case SPE_CLAIM:
1520 fprintf (f, "Claim scope\n");
1521 break;
1522 case SPE_INVALID:
1523 break;
1524 }
1525 break;
1526 case SYMK_TYPE:
1527 ti = (se->info).type;
1528 if (lco)
1529 fprintf (f, "%%LCL");
1530 if (!lco && !ti->export)
1531 fprintf (f, "spec ");
1532 fprintf (f, "type %s %s",
1533 ltoken_getTextChars (ti->id), sort_getName (ti->basedOn));
1534 if (ti->abstract)
1535 {
1536 if (ti->modifiable)
1537 fprintf (f, " mutable\n");
1538 else
1539 fprintf (f, " immutable\n");
1540 }
1541 else
1542 fprintf (f, " exposed\n");
1543 break;
1544 case SYMK_VAR:
1545
1546 vi = (se->info).var;
1547 if (lco)
1548 {
1549 fprintf (f, "%%LCL");
1550 }
1551
1552 if (!lco && !vi->export)
1553 {
1554 fprintf (f, "spec ");
1555 }
1556 switch (vi->kind)
1557 {
1558 case VRK_CONST:
1559 fprintf (f, "const %s %s\n",
1560 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1561 break;
1562 case VRK_VAR:
1563 fprintf (f, "var %s %s\n",
1564 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1565 break;
1566 case VRK_ENUM:
1567 fprintf (f, "enumConst %s %s\n",
1568 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1569 break;
1570 default:
1571 if (lco)
1572 {
1573 switch (vi->kind)
1574 {
1575 case VRK_GLOBAL:
1576 fprintf (f, "global %s %s\n", ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1577 break;
1578 case VRK_PRIVATE: /* for private vars within function */
1579 fprintf (f, "local %s %s\n",
1580 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1581 break;
1582 case VRK_LET:
1583 fprintf (f, "let %s %s\n",
1584 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1585 break;
1586 case VRK_PARAM:
1587 fprintf (f, "param %s %s\n",
1588 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1589 break;
1590 case VRK_QUANT:
1591 fprintf (f, "quant %s %s\n",
1592 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1593 break;
1594 BADDEFAULT;
1595 }
1596 /*@=loopswitchbreak@*/
1597 /*@=switchswitchbreak@*/
1598 }
1599 }
1600 }
1601 }
1602}
1603
1604static /*@exposed@*/ /*@out@*/ idTableEntry *
1605nextFree (idTable * st)
1606{
1607 idTableEntry *ret;
1608 unsigned int n = st->size;
1609
1610 if (n >= st->allocated)
1611 {
1612 /*
1613 ** this loses with the garbage collector
1614 ** (and realloc is notoriously dangerous)
1615 **
1616 ** st->entries = (idTableEntry *) LSLMoreMem (st->entries, (n + DELTA)
1617 ** * sizeof (idTableEntry));
1618 **
1619 ** instead, we copy the symtable...
1620 */
1621
1622 idTableEntry *oldentries = st->entries;
1623 unsigned int i;
1624
1625 st->entries = dmalloc ((n+DELTA) * sizeof (*st->entries));
1626
1627 for (i = 0; i < n; i++)
1628 {
1629 st->entries[i] = oldentries[i];
1630 }
1631
1632 sfree (oldentries);
1633
1634 st->allocated = n + DELTA;
1635 }
1636
1637 ret = &(st->entries[st->size]);
1638 st->size++;
1639 return ret;
1640}
1641
1642
1643static /*@dependent@*/ /*@null@*/ idTableEntry *
1644 symtable_lookup (idTable *st, lsymbol id)
1645{
1646 int n;
1647 idTableEntry *e;
1648
1649 for (n = st->size - 1; n >= 0; n--)
1650 {
1651 e = &(st->entries[n]);
1652
1653 /*@-loopswitchbreak@*/
1654 switch (e->kind)
1655 {
1656 case SYMK_SCOPE:
1657 break;
1658 case SYMK_FCN:
1659 if (ltoken_getText (e->info.fct->id) == id) return e;
1660 break;
1661 case SYMK_TYPE:
1662 if (ltoken_getText (e->info.type->id) == id) return e;
1663 break;
1664 case SYMK_VAR:
1665 if (ltoken_getText (e->info.var->id) == id) return e;
1666 break;
1667 BADDEFAULT;
1668 }
1669 /*@=loopswitchbreak@*/
1670 }
1671
1672 return (idTableEntry *) 0;
1673}
1674
1675
1676static /*@dependent@*/ /*@null@*/ idTableEntry *
1677 symtable_lookupInScope (idTable *st, lsymbol id)
1678{
1679 int n;
1680 idTableEntry *e;
1681 for (n = st->size - 1; n >= 0; n--)
1682 {
1683 e = &(st->entries[n]);
1684 if (e->kind == SYMK_SCOPE)
1685 break;
1686 if (ltoken_getText (e->info.fct->id) == id)
1687 {
1688 return e;
1689 }
1690 }
1691 return (idTableEntry *) 0;
1692}
1693
1694/* hash table implementation */
1695
1696static symbolKey
1697htData_key (htData * x)
1698{
1699 /* assume x points to a valid htData struct */
1700 switch (x->kind)
1701 {
1702 case IK_SORT:
1703 return x->content.sort;
1704 case IK_OP:
1705 { /* get the textSym of the token */
1706 nameNode n = (x->content.op)->name;
1707
1708 if (n->isOpId)
1709 {
1710 return ltoken_getText (n->content.opid);
1711 }
1712 else
1713 {
1714 llassert (n->content.opform != NULL);
1715 return (n->content.opform)->key;
1716 }
1717 }
1718 case IK_TAG:
1719 return ltoken_getText ((x->content).tag->id);
1720 }
1721 BADEXIT;
1722}
1723
1724static void htData_free (/*@null@*/ /*@only@*/ htData *d)
1725{
1726 if (d != NULL)
1727 {
1728 switch (d->kind)
1729 {
1730 case IK_SORT:
1731 break;
1732 case IK_OP:
1733 /* nameNode_free (d->content.op->name);*/
1734 sigNodeSet_free (d->content.op->signatures);
1735 break;
1736 case IK_TAG:
1737 {
1738 switch (d->content.tag->kind)
1739 {
1740 case TAG_STRUCT:
1741 case TAG_UNION:
1742 case TAG_FWDSTRUCT:
1743 case TAG_FWDUNION:
1744 /*
1745 ** no: stDeclNodeList_free (d->content.tag->content.decls);
1746 ** it is dependent!
1747 */
1748 /*@switchbreak@*/ break;
1749 case TAG_ENUM:
1750
1751 /* no: ltokenList_free (d->content.tag->content.enums);
1752 ** it is dependent!
1753 */
1754
1755 /*@switchbreak@*/ break;
1756 }
1757 }
1758 }
1759
1760 sfree (d);
1761 }
1762}
1763
1764static void bucket_free (/*@null@*/ /*@only@*/ bucket *b)
1765{
1766 if (b != NULL)
1767 {
1768 bucket_free (b->next);
1769 htData_free (b->data);
1770 sfree (b);
1771 }
1772}
1773
1774static void symHashTable_free (/*@only@*/ symHashTable *h)
1775{
1776 unsigned int i;
1777
1778 for (i = 0; i < h->size; i++)
1779 {
1780 bucket_free (h->buckets[i]);
1781 }
1782
1783 sfree (h->buckets);
1784 sfree (h);
1785}
1786
1787static /*@only@*/ symHashTable *
1788symHashTable_create (unsigned int size)
1789{
1790 unsigned int i;
1791 symHashTable *t = (symHashTable *) dmalloc (sizeof (*t));
1792
1793 t->buckets = (bucket **) dmalloc ((size + 1) * sizeof (*t->buckets));
1794 t->count = 0;
1795 t->size = size;
1796
1797 for (i = 0; i <= size; i++)
1798 {
1799 t->buckets[i] = (bucket *) NULL;
1800 }
1801
1802 return t;
1803}
1804
1805static /*@null@*/ /*@exposed@*/ htData *
1806symHashTable_get (symHashTable *t, symbolKey key, infoKind kind, /*@null@*/ nameNode n)
1807{
1808 bucket *b;
1809 htEntry *entry;
1810 htData *d;
1811
1812 b = t->buckets[MASH (key, kind)];
1813 if (b == (bucket *) 0)
1814 {
1815 return ((htData *) 0);
1816 }
1817
1818 for (entry = (htEntry *) b; entry != NULL; entry = entry->next)
1819 {
1820 d = entry->data;
1821
1822 if (d->kind == kind && htData_key (d) == key)
1823 if (kind != IK_OP || sameNameNode (n, d->content.op->name))
1824 {
1825 return d;
1826 }
1827 }
1828 return ((htData *) 0);
1829}
1830
1831static bool
1832symHashTable_put (symHashTable *t, /*@only@*/ htData *data)
1833{
1834 /* if key is already taken, don't insert, return FALSE
1835 else insert it and return TRUE. */
1836 symbolKey key;
1837 htData *oldd;
1838 infoKind kind;
1839 nameNode name;
1840
1841 key = htData_key (data);
1842 kind = data->kind;
1843
1844 if (kind == IK_OP && (!data->content.op->name->isOpId))
1845 {
1846 name = data->content.op->name;
1847 }
1848 else
1849 {
1850 name = (nameNode) 0;
1851 }
1852
1853 oldd = symHashTable_get (t, key, kind, name);
1854
1855 if (oldd == (htData *) 0)
1856 {
1857 /*@-deparrays@*/
1858 bucket *new_entry = (bucket *) dmalloc (sizeof (*new_entry));
1859 bucket *b = (t->buckets[MASH (key, kind)]);
1860 htEntry *entry = (htEntry *) b;
1861 /*@=deparrays@*/
1862
1863 new_entry->data = data;
1864 new_entry->next = entry;
1865 t->buckets[MASH (key, kind)] = new_entry;
1866 t->count++;
1867
1868 return TRUE;
1869 }
1870 else
1871 {
1872 htData_free (data);
1873 }
1874
1875 return FALSE;
1876}
1877
1878static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
1879 symHashTable_forcePut (symHashTable *t, /*@only@*/ htData *data)
1880{
1881 /* Put data in, return old value */
1882 symbolKey key;
1883 bucket *b;
1884 htData *oldd;
1885 htEntry *entry, *new_entry;
1886 infoKind kind;
1887 nameNode name;
1888
1889 key = htData_key (data);
1890 kind = data->kind;
1891
1892 if (kind == IK_OP && (!data->content.op->name->isOpId))
1893 {
1894 name = data->content.op->name;
1895 }
1896 else
1897 {
1898 name = (nameNode) 0;
1899 }
1900
1901 oldd = symHashTable_get (t, key, kind, name);
1902
1903 if (oldd == (htData *) 0)
1904 {
1905 new_entry = (htEntry *) dmalloc (sizeof (*new_entry));
1906
1907 /*@-deparrays@*/
1908 b = t->buckets[MASH (key, kind)];
1909 /*@=deparrays@*/
1910
1911 entry = b;
1912 new_entry->data = data;
1913 new_entry->next = entry;
1914 t->buckets[MASH (key, kind)] = new_entry;
1915 t->count++;
1916
1917 return NULL;
1918 }
1919 else
1920 { /* modify in place */
1921 *oldd = *data; /* copy new info over to old info */
1922
1923 /* dangerous: if the data is the same, don't free it */
1924 if (data != oldd)
1925 {
1926 sfree (data);
1927 /*@-branchstate@*/
1928 }
1929 /*@=branchstate@*/
1930
1931 return oldd;
1932 }
1933}
1934
1935#if 0
1936static unsigned int
1937symHashTable_count (symHashTable * t)
1938{
1939 return (t->count);
1940}
1941
1942#endif
1943
1944static void
1945symHashTable_printStats (symHashTable * t)
1946{
1947 int i, bucketCount, setsize, sortCount, opCount, tagCount;
1948 int sortTotal, opTotal, tagTotal;
1949 bucket *b;
1950 htEntry *entry;
1951 htData *d;
1952
1953 sortTotal = 0;
1954 opTotal = 0;
1955 tagTotal = 0;
1956 sortCount = 0;
1957 opCount = 0;
1958 tagCount = 0;
1959
1960 /* for debugging only */
1961 printf ("\n Printing symHashTable stats ... \n");
1962 for (i = 0; i <= HT_MAXINDEX; i++)
1963 {
1964 b = t->buckets[i];
1965 bucketCount = 0;
1966 for (entry = b; entry != NULL; entry = entry->next)
1967 {
1968 d = entry->data;
1969 bucketCount++;
1970 switch (d->kind)
1971 {
1972 case IK_SORT:
1973 sortCount++;
1974 /*@switchbreak@*/ break;
1975 case IK_OP:
1976 {
1977 cstring name = nameNode_unparse (d->content.op->name);
1978 cstring sigs = sigNodeSet_unparse (d->content.op->signatures);
1979 opCount++;
1980 /* had a tt? */
1981 setsize = sigNodeSet_size (d->content.op->signatures);
1982 printf (" Op (%d): %s %s\n", setsize,
1983 cstring_toCharsSafe (name),
1984 cstring_toCharsSafe (sigs));
1985 cstring_free (name);
1986 cstring_free (sigs);
1987 /*@switchbreak@*/ break;
1988 }
1989 case IK_TAG:
1990 tagCount++;
1991 /*@switchbreak@*/ break;
1992 }
1993 }
1994 if (bucketCount > 0)
1995 {
1996 printf (" Bucket %d has count = %d; opCount = %d; sortCount = %d; tagCount = %d\n", i, bucketCount, opCount, sortCount, tagCount);
1997 sortTotal += sortCount;
1998 tagTotal += tagCount;
1999 opTotal += opCount;
2000 }
2001 }
2002 printf ("SymHashTable has total count = %d, opTotal = %d, sortTotal = %d, tagTotal = %d :\n", t->count, opTotal, sortTotal, tagTotal);
2003
2004}
2005
2006void
2007symtable_printStats (symtable s)
2008{
2009 symHashTable_printStats (s->hTable);
2010 /* for debugging only */
2011 printf ("idTable size = %d; allocated = %d\n",
2012 s->idTable->size, s->idTable->allocated);
2013}
2014
2015/*@only@*/ cstring
2016tagKind_unparse (tagKind k)
2017{
2018 switch (k)
2019 {
2020 case TAG_STRUCT:
2021 case TAG_FWDSTRUCT:
2022 return cstring_makeLiteral ("struct");
2023 case TAG_UNION:
2024 case TAG_FWDUNION:
2025 return cstring_makeLiteral ("union");
2026 case TAG_ENUM:
2027 return cstring_makeLiteral ("enum");
2028 }
2029 BADEXIT;
2030}
2031
2032static void tagInfo_free (/*@only@*/ tagInfo tag)
2033{
28bf4b0b 2034 ltoken_free (tag->id);
616915dd 2035 sfree (tag);
2036}
2037
2038/*@observer@*/ sigNodeSet
2039 symtable_possibleOps (symtable tab, nameNode n)
2040{
2041 opInfo oi = symtable_opInfo (tab, n);
2042
2043 if (opInfo_exists (oi))
2044 {
2045 return (oi->signatures);
2046 }
2047
2048 return sigNodeSet_undefined;
2049}
2050
2051bool
2052symtable_opExistsWithArity (symtable tab, nameNode n, int arity)
2053{
2054 opInfo oi = symtable_opInfo (tab, n);
2055
2056 if (opInfo_exists (oi))
2057 {
2058 sigNodeSet sigs = oi->signatures;
2059 sigNodeSet_elements (sigs, sig)
2060 {
2061 if (ltokenList_size (sig->domain) == arity)
2062 return TRUE;
2063 } end_sigNodeSet_elements;
2064 }
2065 return FALSE;
2066}
2067
2068static bool
2069domainMatches (ltokenList domain, sortSetList argSorts)
2070{
2071 /* expect their length to match */
2072 /* each domain sort in op must be an element of
2073 the corresponding set in argSorts. */
2074 bool matched = TRUE;
2075 sort s;
2076
2077 sortSetList_reset (argSorts);
2078 ltokenList_elements (domain, dom)
2079 {
2080 s = sort_fromLsymbol (ltoken_getText (dom));
2081 if (!(sortSet_member (sortSetList_current (argSorts), s)))
2082 {
2083 /* printf (" mismatched element is: %s in %s\n", ltoken_getTextChars (*dom),
2084 sortSet_unparse (sortSetList_current (argSorts))); */
2085 matched = FALSE;
2086 break;
2087 }
2088 sortSetList_advance (argSorts);
2089 } end_ltokenList_elements;
2090
2091 return matched;
2092}
2093
2094/*@only@*/ lslOpSet
2095 symtable_opsWithLegalDomain (symtable tab, /*@temp@*/ /*@null@*/ nameNode n,
2096 sortSetList argSorts, sort qual)
2097{
2098 /* handles nil qual */
2099 lslOpSet ops = lslOpSet_new ();
2100 lslOp op;
2101 sort rangeSort;
2102 opInfo oi;
2103
2104 llassert (n != NULL);
2105 oi = symtable_opInfo (tab, n);
2106
2107 if (opInfo_exists (oi))
2108 {
2109 sigNodeSet sigs = oi->signatures;
2110
2111 sigNodeSet_elements (sigs, sig)
2112 {
2113 if (ltokenList_size (sig->domain) == sortSetList_size (argSorts))
2114 {
2115 rangeSort = sigNode_rangeSort (sig);
2116
28bf4b0b 2117 if ((qual == 0) || (sort_equal (rangeSort, qual)))
616915dd 2118 {
2119 if (domainMatches (sig->domain, argSorts))
2120 {
2121 op = (lslOp) dmalloc (sizeof (*op));
2122
2123 /* each domain sort in op must be an element of
2124 the corresponding set in argSorts. */
2125 op->signature = sig;
2126 op->name = nameNode_copy (n);
2127 (void) lslOpSet_insert (ops, op);
2128 }
2129 }
2130 }
2131 } end_sigNodeSet_elements;
2132 }
2133 return ops;
2134}
This page took 0.902551 seconds and 5 git commands to generate.