]> andersk Git - splint.git/blame - src/symtable.c
Fixed all /*@i...@*/ tags (except 1).
[splint.git] / src / symtable.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 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
1b8ae690 43# include "splintMacros.nf"
b73d1009 44# include "basic.h"
616915dd 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
11db3170 522 if (k != SPE_GLOBAL && k != SPE_INVALID) /* fixed for Splint */
616915dd 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);
53306cab 1046 col = 5 + ((int) (lineptr - line)); /* 5 for initial "%LCL "*/
616915dd 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
e5081f8c 1081 (uentry_makeDatatype
1082 (cnamestr, ctype_unknown,
1083 ti->abstract ? ynm_fromBool (ti->modifiable) : MAYBE,
1084 ti->abstract ? qual_createAbstract () : qual_createConcrete (),
1085 fileloc_copy (imploc)));
616915dd 1086 }
1087 }
1088
1089 symtable_enterType (g_symtab, ti);
1090 }
1091 else if (firstWord (line, "var"))
1092 {
1093 varInfo vi;
1094
1095 if (sscanf (line, "var %s %s", namestr, sostr) != 2)
1096 {
1097 lclplainerror
1098 (message ("%q: Imported file contains illegal variable declaration. "
1099 "Skipping this line.",
28bf4b0b 1100 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce))));
616915dd 1101 fileloc_free (imploc);
1102 return;
1103 }
1104
1105 vi = (varInfo) dmalloc (sizeof (*vi));
1106 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1107 lineptr = strchr (line, ' '); /* go past "var" */
1108 llassert (lineptr != NULL);
1109 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1110 llassert (lineptr != NULL);
53306cab 1111 col = 5 + ((int) (lineptr - line)); /* 5 for initial "%LCL "*/
616915dd 1112
1113 if (sort_isNoSort (bsort))
1114 {
1115 lclplainerror (message ("%q: Imported file contains unknown base sort",
28bf4b0b 1116 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1117 bsort = nullSort;
1118 }
1119
1120 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1121 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1122 vi->sort = bsort;
1123 vi->kind = VRK_VAR;
1124 vi->export = TRUE;
1125 (void) symtable_enterVar (g_symtab, vi);
1126 varInfo_free (vi);
1127
1128 if (inImport)
1129 {
1130 cstring cnamestr = cstring_fromChars (namestr);
1131
1132 if (!usymtab_existsGlobEither (cnamestr))
1133 {
1134
1135 (void) usymtab_supEntrySref
1136 (uentry_makeVariable (cnamestr, ctype_unknown,
1137 fileloc_copy (imploc),
1138 FALSE));
1139 }
1140 }
1141 }
1142 else if (firstWord (line, "const"))
1143 {
1144 varInfo vi;
1145
1146 if (sscanf (line, "const %s %s", namestr, sostr) != 2)
1147 {
1148 lclbug (message ("%q: Imported file contains illegal constant declaration: %s",
28bf4b0b 1149 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1150 cstring_fromChars (line)));
1151 fileloc_free (imploc);
1152 return;
1153 }
1154
1155 vi = (varInfo) dmalloc (sizeof (*vi));
1156 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1157 lineptr = strchr (line, ' '); /* go past "var" */
1158 llassert (lineptr != NULL);
1159 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1160 llassert (lineptr != NULL);
1161
53306cab 1162 col = 5 + ((int) (lineptr - line)); /* 5 for initial "%LCL "*/
616915dd 1163
1164 if (sort_isNoSort (bsort))
1165 {
1166 lclplainerror (message ("%q: Imported file contains unknown base sort",
28bf4b0b 1167 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1168 bsort = nullSort;
1169 }
1170
1171 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1172 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1173 vi->sort = bsort;
1174 vi->kind = VRK_CONST;
1175 vi->export = TRUE;
1176 (void) symtable_enterVar (g_symtab, vi);
1177 varInfo_free (vi);
1178
1179 if (inImport)
1180 {
1181 cstring cnamestr = cstring_fromChars (namestr);
1182
1183 if (!usymtab_existsGlobEither (cnamestr))
1184 {
1185
1186 (void) usymtab_addEntry (uentry_makeConstant (cnamestr,
1187 ctype_unknown,
1188 fileloc_copy (imploc)));
1189 }
1190 }
1191 /* must check for "fcnGlobals" before "fcn" */
1192 }
1193 else if (firstWord (line, "fcnGlobals"))
1194 {
1195 pairNodeList globals;
1196 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1197 llassert (lineptr != NULL);
1198 lineptr = strchr (lineptr, ' '); /* go past "fcnGlobals" */
1199 llassert (lineptr != NULL);
1200
1201 /* a quick check for empty fcnGlobals */
1202 if (!isBlankLine (lineptr))
1203 {
1204 globals = parseGlobals (lineptr, srce);
1205 /* should ensure that each global in an imported function
1206 corresponds to some existing global. Since only
1207 "correctly processed" .lcs files are imported, this is
1208 true as an invariant. */
1209 }
1210 else
1211 {
1212 globals = pairNodeList_new ();
1213 }
1214
1215 /* check that they exist, store them on fctInfo */
1216
1217 if (savedFcn != NULL)
1218 {
1219 pairNodeList_free ((*savedFcn)->globals);
1220 (*savedFcn)->globals = globals; /* evs, moved inside if predicate */
1221
1222 (void) symtable_enterFct (g_symtab, *savedFcn);
1223 savedFcn = NULL;
1224 }
1225 else
1226 {
1227 lclplainerror
1228 (message ("%q: Unexpected function globals. "
1229 "Skipping this line: \n%s",
28bf4b0b 1230 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1231 cstring_fromChars (line)));
1232 savedFcn = NULL;
1233 pairNodeList_free (globals);
1234 }
1235 }
1236 else if (firstWord (line, "fcn"))
1237 {
1238 lslOp op;
1239 lslOp op2;
1240
1241 if (savedFcn != (fctInfo *) 0)
1242 {
1243 lclplainerror
1244 (message ("%q: illegal function declaration. Skipping this line:\n%s",
28bf4b0b 1245 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1246 cstring_fromChars (line)));
1247 fileloc_free (imploc);
1248 return;
1249 }
1250
1251 savedFcn = (fctInfo *) dmalloc (sizeof (*savedFcn));
1252
1253 lineptr = strchr (line, 'f'); /* remove any leading blanks */
1254 llassert (lineptr != NULL);
1255 lineptr = strchr (lineptr, ' '); /* go past "fcn" */
1256 llassert (lineptr != NULL);
1257
1258 /* add a newline to the end of the line since parseOpLine expects it */
1259
1260 lineptr2 = strchr (lineptr, '\0');
1261
1262 if (lineptr2 != 0)
1263 {
1264 *lineptr2 = '\n';
1265 *(lineptr2 + 1) = '\0';
1266 }
1267
28bf4b0b 1268 op = parseOpLine (importfile, cstring_fromChars (lineptr + 1));
616915dd 1269
1270 if (op == (lslOp) 0)
1271 {
28bf4b0b 1272 lclplainerror
1273 (message ("%q: illegal function declaration: %s",
1274 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
1275 cstring_fromChars (line)));
616915dd 1276 fileloc_free (imploc);
1277 return;
1278 }
1279
1280 op2 = lslOp_renameSorts (map, op);
1281
1282 llassert (op2 != NULL);
1283
1284 if ((op->name != NULL) && op->name->isOpId)
1285 {
1286 (*savedFcn) = (fctInfo) dmalloc (sizeof (**savedFcn));
1287 (*savedFcn)->id = op->name->content.opid;
1288 (*savedFcn)->signature = signNode_fromsigNode (op2->signature);
1289 (*savedFcn)->globals = pairNodeList_new ();
1290 (*savedFcn)->export = TRUE;
1291
1292 if (inImport)
1293 {
1294 /* 27 Jan 1995 --- added this to be undefined namestr bug */
1295 cstring fname = ltoken_unparse ((*savedFcn)->id);
1296
1297 if (!usymtab_existsGlobEither (fname))
1298 {
28bf4b0b 1299 (void) usymtab_addEntry (uentry_makeFunction
616915dd 1300 (fname, ctype_unknown,
1301 typeId_invalid, globSet_new (),
1302 sRefSet_undefined,
28bf4b0b 1303 warnClause_undefined,
616915dd 1304 fileloc_copy (imploc)));
1305 }
1306 }
1307 }
1308 else
1309 {
1b8ae690 1310 /* evans 2001-05-27: detected by splint after fixing external alias bug. */
28bf4b0b 1311 if (op->name != NULL)
1312 {
1313 ltoken_free (op->name->content.opid);
1314 }
1315
1316 lclplainerror
1317 (message ("%q: unexpected function name: %s",
1318 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
1319 cstring_fromChars (line)));
616915dd 1320 }
1321 }
1322 else if (firstWord (line, "enumConst"))
1323 {
1324 varInfo vi;
1325
1326 if (sscanf (line, "enumConst %s %s", namestr, sostr) != 2)
1327 {
1328 lclplainerror
1329 (message ("%q: Illegal enum constant declaration. "
1330 "Skipping this line:\n%s",
28bf4b0b 1331 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1332 cstring_fromChars (line)));
1333 fileloc_free (imploc);
1334 return;
1335 }
1336
1337 vi = (varInfo) dmalloc (sizeof (*vi));
1338 bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
1339 lineptr = strchr (line, ' '); /* go past "var" */
1340 llassert (lineptr != NULL);
1341 lineptr = strchr (lineptr + 1, ' '); /* go past namestr */
1342 llassert (lineptr != NULL);
1343
53306cab 1344 col = 5 + ((int) (lineptr - line)); /* 5 for initial "%LCL "*/
616915dd 1345 if (sort_isNoSort (bsort))
1346 {
1347 lclplainerror (message ("%q: unknown base sort\n",
28bf4b0b 1348 fileloc_unparseRawCol (importfile, inputStream_thisLineNumber (srce), col)));
616915dd 1349 bsort = nullSort;
1350 }
1351
1352 vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
28bf4b0b 1353 importfile, inputStream_thisLineNumber (srce), col);
616915dd 1354
1355 vi->sort = bsort;
1356 vi->kind = VRK_ENUM;
1357 vi->export = TRUE;
1358 (void) symtable_enterVar (g_symtab, vi);
1359 varInfo_free (vi);
1360
1361 if (inImport)
1362 {
1363 cstring cnamestr = cstring_fromChars (namestr);
1364 if (!usymtab_existsEither (cnamestr))
1365 {
1366 (void) usymtab_addEntry (uentry_makeConstant (cnamestr, ctype_unknown,
1367 fileloc_copy (imploc)));
1368 }
1369 }
1370 }
1371 else if (firstWord (line, "tag"))
1372 {
1373 /* do nothing, sort processing already handles this */
1374 }
1375 else
1376 {
1377 lclplainerror
1378 (message ("%q: Unknown symbol declaration. Skipping this line:\n%s",
28bf4b0b 1379 fileloc_unparseRaw (importfile, inputStream_thisLineNumber (srce)),
616915dd 1380 cstring_fromChars (line)));
1381 }
1382
1383 fileloc_free (imploc);
1384}
1385
1386void
28bf4b0b 1387symtable_import (inputStream imported, ltoken tok, mapping map)
616915dd 1388{
28bf4b0b 1389 char *buf;
1390 cstring importfile;
1391 inputStream lclsource;
616915dd 1392 int old_lsldebug;
1393 bool old_inImport = inImport;
1394
28bf4b0b 1395 buf = inputStream_nextLine (imported);
1396 importfile = inputStream_fileName (imported);
616915dd 1397
1398 llassert (buf != NULL);
1399
1400 if (!firstWord (buf, "%LCLSymbolTable"))
1401 {
1402 lclsource = LCLScanSource ();
1403 lclfatalerror (tok,
1404 message ("Expecting '%%LCLSymbolTable' line in import file %s:\n%s\n",
28bf4b0b 1405 importfile,
616915dd 1406 cstring_fromChars (buf)));
1407 }
1408
1409 old_lsldebug = lsldebug;
1410 lsldebug = 0;
1411 allowed_redeclaration = TRUE;
1412 inImport = TRUE;
1413
1414 for (;;)
1415 {
28bf4b0b 1416 buf = inputStream_nextLine (imported);
616915dd 1417 llassert (buf != NULL);
1418
1419
1420 if (firstWord (buf, "%LCLSymbolTableEnd"))
1421 {
1422 break;
1423 }
1424 else
1425 { /* a good line, remove %LCL from line first */
1426 if (firstWord (buf, "%LCL"))
1427 {
1428 parseLine (buf + 4, imported, map);
1429 }
1430 else
1431 {
1432 lclsource = LCLScanSource ();
1433 lclfatalerror
1434 (tok,
1435 message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
28bf4b0b 1436 importfile,
616915dd 1437 cstring_fromChars (buf)));
1438 }
1439 }
1440 }
1441
1442 /* restore old value */
1443 inImport = old_inImport;
1444 lsldebug = old_lsldebug;
1445 allowed_redeclaration = FALSE;
1446 }
1447
1448static void
1449symtable_dumpId (symtable stable, FILE *f, bool lco)
1450{
1451 idTable *st = stable->idTable;
1452 unsigned int i;
1453 idTableEntry *se;
1454 fctInfo fi;
1455 typeInfo ti;
1456 varInfo vi;
1457
1458 for (i = 1; i < st->size; i++)
1459 {
1460 /* 2/22/93 I think there is a off-by-1 error, 0 entry is never used */
1461 se = st->entries + i;
1462 llassert (se != NULL);
1463
1464
1465 /*@-loopswitchbreak@*/
1466 switch (se->kind)
1467 {
1468 case SYMK_FCN:
1469 {
1470 cstring tmp;
1471
1472 fi = (se->info).fct;
1473
1474 if (lco)
1475 {
1476 fprintf (f, "%%LCL");
1477 }
1478
1479 if (!lco && !fi->export)
1480 {
1481 fprintf (f, "spec ");
1482 }
1483
1484 tmp = signNode_unparse (fi->signature);
1485 fprintf (f, "fcn %s %s \n", ltoken_getTextChars (fi->id),
1486 cstring_toCharsSafe (tmp));
1487 cstring_free (tmp);
1488
1489 tmp = pairNodeList_unparse (fi->globals);
1490 fprintf (f, "%%LCLfcnGlobals %s\n", cstring_toCharsSafe (tmp));
1491 cstring_free (tmp);
1492 break;
1493 }
1494 case SYMK_SCOPE:
1495 if (lco)
1496 {
1497 break;
1498 }
1499
1500 /*@-switchswitchbreak@*/
1501 switch ((se->info).scope->kind)
1502 {
1503 case SPE_GLOBAL:
1504 fprintf (f, "Global scope\n");
1505 break;
1506 case SPE_ABSTRACT:
1507 fprintf (f, "Abstract type scope\n");
1508 break;
1509 case SPE_FCN:
1510 fprintf (f, "Function scope\n");
1511 break;
1512 /* a let scope can only occur in a function scope, should not push
1513 a new scope, so symtable_lookupInScope works properly
1514 case letScope:
1515 fprintf (f, "Let scope\n");
1516 break; */
1517 case SPE_QUANT:
1518 fprintf (f, "Quantifier scope\n");
1519 break;
1520 case SPE_CLAIM:
1521 fprintf (f, "Claim scope\n");
1522 break;
1523 case SPE_INVALID:
1524 break;
1525 }
1526 break;
1527 case SYMK_TYPE:
1528 ti = (se->info).type;
1529 if (lco)
1530 fprintf (f, "%%LCL");
1531 if (!lco && !ti->export)
1532 fprintf (f, "spec ");
1533 fprintf (f, "type %s %s",
1534 ltoken_getTextChars (ti->id), sort_getName (ti->basedOn));
1535 if (ti->abstract)
1536 {
1537 if (ti->modifiable)
1538 fprintf (f, " mutable\n");
1539 else
1540 fprintf (f, " immutable\n");
1541 }
1542 else
1543 fprintf (f, " exposed\n");
1544 break;
1545 case SYMK_VAR:
1546
1547 vi = (se->info).var;
1548 if (lco)
1549 {
1550 fprintf (f, "%%LCL");
1551 }
1552
1553 if (!lco && !vi->export)
1554 {
1555 fprintf (f, "spec ");
1556 }
1557 switch (vi->kind)
1558 {
1559 case VRK_CONST:
1560 fprintf (f, "const %s %s\n",
1561 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1562 break;
1563 case VRK_VAR:
1564 fprintf (f, "var %s %s\n",
1565 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1566 break;
1567 case VRK_ENUM:
1568 fprintf (f, "enumConst %s %s\n",
1569 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1570 break;
1571 default:
1572 if (lco)
1573 {
1574 switch (vi->kind)
1575 {
1576 case VRK_GLOBAL:
1577 fprintf (f, "global %s %s\n", ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1578 break;
1579 case VRK_PRIVATE: /* for private vars within function */
1580 fprintf (f, "local %s %s\n",
1581 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1582 break;
1583 case VRK_LET:
1584 fprintf (f, "let %s %s\n",
1585 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1586 break;
1587 case VRK_PARAM:
1588 fprintf (f, "param %s %s\n",
1589 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1590 break;
1591 case VRK_QUANT:
1592 fprintf (f, "quant %s %s\n",
1593 ltoken_getTextChars (vi->id), sort_getName (vi->sort));
1594 break;
1595 BADDEFAULT;
1596 }
1597 /*@=loopswitchbreak@*/
1598 /*@=switchswitchbreak@*/
1599 }
1600 }
1601 }
1602 }
1603}
1604
1605static /*@exposed@*/ /*@out@*/ idTableEntry *
1606nextFree (idTable * st)
1607{
1608 idTableEntry *ret;
1609 unsigned int n = st->size;
1610
1611 if (n >= st->allocated)
1612 {
1613 /*
1614 ** this loses with the garbage collector
1615 ** (and realloc is notoriously dangerous)
1616 **
1617 ** st->entries = (idTableEntry *) LSLMoreMem (st->entries, (n + DELTA)
1618 ** * sizeof (idTableEntry));
1619 **
1620 ** instead, we copy the symtable...
1621 */
1622
1623 idTableEntry *oldentries = st->entries;
1624 unsigned int i;
1625
1626 st->entries = dmalloc ((n+DELTA) * sizeof (*st->entries));
1627
1628 for (i = 0; i < n; i++)
1629 {
1630 st->entries[i] = oldentries[i];
1631 }
1632
1633 sfree (oldentries);
1634
1635 st->allocated = n + DELTA;
1636 }
1637
1638 ret = &(st->entries[st->size]);
1639 st->size++;
1640 return ret;
1641}
1642
1643
1644static /*@dependent@*/ /*@null@*/ idTableEntry *
1645 symtable_lookup (idTable *st, lsymbol id)
1646{
1647 int n;
1648 idTableEntry *e;
1649
1650 for (n = st->size - 1; n >= 0; n--)
1651 {
1652 e = &(st->entries[n]);
1653
1654 /*@-loopswitchbreak@*/
1655 switch (e->kind)
1656 {
1657 case SYMK_SCOPE:
1658 break;
1659 case SYMK_FCN:
1660 if (ltoken_getText (e->info.fct->id) == id) return e;
1661 break;
1662 case SYMK_TYPE:
1663 if (ltoken_getText (e->info.type->id) == id) return e;
1664 break;
1665 case SYMK_VAR:
1666 if (ltoken_getText (e->info.var->id) == id) return e;
1667 break;
1668 BADDEFAULT;
1669 }
1670 /*@=loopswitchbreak@*/
1671 }
1672
1673 return (idTableEntry *) 0;
1674}
1675
1676
1677static /*@dependent@*/ /*@null@*/ idTableEntry *
1678 symtable_lookupInScope (idTable *st, lsymbol id)
1679{
1680 int n;
1681 idTableEntry *e;
1682 for (n = st->size - 1; n >= 0; n--)
1683 {
1684 e = &(st->entries[n]);
1685 if (e->kind == SYMK_SCOPE)
1686 break;
1687 if (ltoken_getText (e->info.fct->id) == id)
1688 {
1689 return e;
1690 }
1691 }
1692 return (idTableEntry *) 0;
1693}
1694
1695/* hash table implementation */
1696
1697static symbolKey
1698htData_key (htData * x)
1699{
1700 /* assume x points to a valid htData struct */
1701 switch (x->kind)
1702 {
1703 case IK_SORT:
1704 return x->content.sort;
1705 case IK_OP:
1706 { /* get the textSym of the token */
1707 nameNode n = (x->content.op)->name;
1708
1709 if (n->isOpId)
1710 {
1711 return ltoken_getText (n->content.opid);
1712 }
1713 else
1714 {
1715 llassert (n->content.opform != NULL);
1716 return (n->content.opform)->key;
1717 }
1718 }
1719 case IK_TAG:
1720 return ltoken_getText ((x->content).tag->id);
1721 }
1722 BADEXIT;
1723}
1724
1725static void htData_free (/*@null@*/ /*@only@*/ htData *d)
1726{
1727 if (d != NULL)
1728 {
1729 switch (d->kind)
1730 {
1731 case IK_SORT:
1732 break;
1733 case IK_OP:
1734 /* nameNode_free (d->content.op->name);*/
1735 sigNodeSet_free (d->content.op->signatures);
1736 break;
1737 case IK_TAG:
1738 {
1739 switch (d->content.tag->kind)
1740 {
1741 case TAG_STRUCT:
1742 case TAG_UNION:
1743 case TAG_FWDSTRUCT:
1744 case TAG_FWDUNION:
1745 /*
1746 ** no: stDeclNodeList_free (d->content.tag->content.decls);
1747 ** it is dependent!
1748 */
1749 /*@switchbreak@*/ break;
1750 case TAG_ENUM:
1751
1752 /* no: ltokenList_free (d->content.tag->content.enums);
1753 ** it is dependent!
1754 */
1755
1756 /*@switchbreak@*/ break;
1757 }
1758 }
1759 }
1760
1761 sfree (d);
1762 }
1763}
1764
1765static void bucket_free (/*@null@*/ /*@only@*/ bucket *b)
1766{
1767 if (b != NULL)
1768 {
1769 bucket_free (b->next);
1770 htData_free (b->data);
1771 sfree (b);
1772 }
1773}
1774
1775static void symHashTable_free (/*@only@*/ symHashTable *h)
1776{
1777 unsigned int i;
1778
1779 for (i = 0; i < h->size; i++)
1780 {
1781 bucket_free (h->buckets[i]);
1782 }
1783
1784 sfree (h->buckets);
1785 sfree (h);
1786}
1787
1788static /*@only@*/ symHashTable *
1789symHashTable_create (unsigned int size)
1790{
1791 unsigned int i;
1792 symHashTable *t = (symHashTable *) dmalloc (sizeof (*t));
1793
1794 t->buckets = (bucket **) dmalloc ((size + 1) * sizeof (*t->buckets));
1795 t->count = 0;
1796 t->size = size;
1797
1798 for (i = 0; i <= size; i++)
1799 {
1800 t->buckets[i] = (bucket *) NULL;
1801 }
1802
1803 return t;
1804}
1805
1806static /*@null@*/ /*@exposed@*/ htData *
1807symHashTable_get (symHashTable *t, symbolKey key, infoKind kind, /*@null@*/ nameNode n)
1808{
1809 bucket *b;
1810 htEntry *entry;
1811 htData *d;
1812
1813 b = t->buckets[MASH (key, kind)];
1814 if (b == (bucket *) 0)
1815 {
1816 return ((htData *) 0);
1817 }
1818
1819 for (entry = (htEntry *) b; entry != NULL; entry = entry->next)
1820 {
1821 d = entry->data;
1822
1823 if (d->kind == kind && htData_key (d) == key)
1824 if (kind != IK_OP || sameNameNode (n, d->content.op->name))
1825 {
1826 return d;
1827 }
1828 }
1829 return ((htData *) 0);
1830}
1831
1832static bool
1833symHashTable_put (symHashTable *t, /*@only@*/ htData *data)
1834{
1835 /* if key is already taken, don't insert, return FALSE
1836 else insert it and return TRUE. */
1837 symbolKey key;
1838 htData *oldd;
1839 infoKind kind;
1840 nameNode name;
1841
1842 key = htData_key (data);
1843 kind = data->kind;
1844
1845 if (kind == IK_OP && (!data->content.op->name->isOpId))
1846 {
1847 name = data->content.op->name;
1848 }
1849 else
1850 {
1851 name = (nameNode) 0;
1852 }
1853
1854 oldd = symHashTable_get (t, key, kind, name);
1855
1856 if (oldd == (htData *) 0)
1857 {
1858 /*@-deparrays@*/
1859 bucket *new_entry = (bucket *) dmalloc (sizeof (*new_entry));
1860 bucket *b = (t->buckets[MASH (key, kind)]);
1861 htEntry *entry = (htEntry *) b;
1862 /*@=deparrays@*/
1863
1864 new_entry->data = data;
1865 new_entry->next = entry;
1866 t->buckets[MASH (key, kind)] = new_entry;
1867 t->count++;
1868
1869 return TRUE;
1870 }
1871 else
1872 {
1873 htData_free (data);
1874 }
1875
1876 return FALSE;
1877}
1878
1879static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
1880 symHashTable_forcePut (symHashTable *t, /*@only@*/ htData *data)
1881{
1882 /* Put data in, return old value */
1883 symbolKey key;
1884 bucket *b;
1885 htData *oldd;
1886 htEntry *entry, *new_entry;
1887 infoKind kind;
1888 nameNode name;
1889
1890 key = htData_key (data);
1891 kind = data->kind;
1892
1893 if (kind == IK_OP && (!data->content.op->name->isOpId))
1894 {
1895 name = data->content.op->name;
1896 }
1897 else
1898 {
1899 name = (nameNode) 0;
1900 }
1901
1902 oldd = symHashTable_get (t, key, kind, name);
1903
1904 if (oldd == (htData *) 0)
1905 {
1906 new_entry = (htEntry *) dmalloc (sizeof (*new_entry));
1907
1908 /*@-deparrays@*/
1909 b = t->buckets[MASH (key, kind)];
1910 /*@=deparrays@*/
1911
1912 entry = b;
1913 new_entry->data = data;
1914 new_entry->next = entry;
1915 t->buckets[MASH (key, kind)] = new_entry;
1916 t->count++;
1917
1918 return NULL;
1919 }
1920 else
1921 { /* modify in place */
1922 *oldd = *data; /* copy new info over to old info */
1923
1924 /* dangerous: if the data is the same, don't free it */
1925 if (data != oldd)
1926 {
1927 sfree (data);
1928 /*@-branchstate@*/
1929 }
1930 /*@=branchstate@*/
1931
1932 return oldd;
1933 }
1934}
1935
1936#if 0
1937static unsigned int
1938symHashTable_count (symHashTable * t)
1939{
1940 return (t->count);
1941}
1942
1943#endif
1944
1945static void
1946symHashTable_printStats (symHashTable * t)
1947{
1948 int i, bucketCount, setsize, sortCount, opCount, tagCount;
1949 int sortTotal, opTotal, tagTotal;
1950 bucket *b;
1951 htEntry *entry;
1952 htData *d;
1953
1954 sortTotal = 0;
1955 opTotal = 0;
1956 tagTotal = 0;
1957 sortCount = 0;
1958 opCount = 0;
1959 tagCount = 0;
1960
1961 /* for debugging only */
1962 printf ("\n Printing symHashTable stats ... \n");
1963 for (i = 0; i <= HT_MAXINDEX; i++)
1964 {
1965 b = t->buckets[i];
1966 bucketCount = 0;
1967 for (entry = b; entry != NULL; entry = entry->next)
1968 {
1969 d = entry->data;
1970 bucketCount++;
1971 switch (d->kind)
1972 {
1973 case IK_SORT:
1974 sortCount++;
1975 /*@switchbreak@*/ break;
1976 case IK_OP:
1977 {
1978 cstring name = nameNode_unparse (d->content.op->name);
1979 cstring sigs = sigNodeSet_unparse (d->content.op->signatures);
1980 opCount++;
1981 /* had a tt? */
1982 setsize = sigNodeSet_size (d->content.op->signatures);
1983 printf (" Op (%d): %s %s\n", setsize,
1984 cstring_toCharsSafe (name),
1985 cstring_toCharsSafe (sigs));
1986 cstring_free (name);
1987 cstring_free (sigs);
1988 /*@switchbreak@*/ break;
1989 }
1990 case IK_TAG:
1991 tagCount++;
1992 /*@switchbreak@*/ break;
1993 }
1994 }
1995 if (bucketCount > 0)
1996 {
1997 printf (" Bucket %d has count = %d; opCount = %d; sortCount = %d; tagCount = %d\n", i, bucketCount, opCount, sortCount, tagCount);
1998 sortTotal += sortCount;
1999 tagTotal += tagCount;
2000 opTotal += opCount;
2001 }
2002 }
2003 printf ("SymHashTable has total count = %d, opTotal = %d, sortTotal = %d, tagTotal = %d :\n", t->count, opTotal, sortTotal, tagTotal);
2004
2005}
2006
2007void
2008symtable_printStats (symtable s)
2009{
2010 symHashTable_printStats (s->hTable);
2011 /* for debugging only */
2012 printf ("idTable size = %d; allocated = %d\n",
2013 s->idTable->size, s->idTable->allocated);
2014}
2015
2016/*@only@*/ cstring
2017tagKind_unparse (tagKind k)
2018{
2019 switch (k)
2020 {
2021 case TAG_STRUCT:
2022 case TAG_FWDSTRUCT:
2023 return cstring_makeLiteral ("struct");
2024 case TAG_UNION:
2025 case TAG_FWDUNION:
2026 return cstring_makeLiteral ("union");
2027 case TAG_ENUM:
2028 return cstring_makeLiteral ("enum");
2029 }
2030 BADEXIT;
2031}
2032
2033static void tagInfo_free (/*@only@*/ tagInfo tag)
2034{
28bf4b0b 2035 ltoken_free (tag->id);
616915dd 2036 sfree (tag);
2037}
2038
2039/*@observer@*/ sigNodeSet
2040 symtable_possibleOps (symtable tab, nameNode n)
2041{
2042 opInfo oi = symtable_opInfo (tab, n);
2043
2044 if (opInfo_exists (oi))
2045 {
2046 return (oi->signatures);
2047 }
2048
2049 return sigNodeSet_undefined;
2050}
2051
2052bool
2053symtable_opExistsWithArity (symtable tab, nameNode n, int arity)
2054{
2055 opInfo oi = symtable_opInfo (tab, n);
2056
2057 if (opInfo_exists (oi))
2058 {
2059 sigNodeSet sigs = oi->signatures;
2060 sigNodeSet_elements (sigs, sig)
2061 {
2062 if (ltokenList_size (sig->domain) == arity)
2063 return TRUE;
2064 } end_sigNodeSet_elements;
2065 }
2066 return FALSE;
2067}
2068
2069static bool
2070domainMatches (ltokenList domain, sortSetList argSorts)
2071{
2072 /* expect their length to match */
2073 /* each domain sort in op must be an element of
2074 the corresponding set in argSorts. */
2075 bool matched = TRUE;
2076 sort s;
2077
2078 sortSetList_reset (argSorts);
2079 ltokenList_elements (domain, dom)
2080 {
2081 s = sort_fromLsymbol (ltoken_getText (dom));
2082 if (!(sortSet_member (sortSetList_current (argSorts), s)))
2083 {
2084 /* printf (" mismatched element is: %s in %s\n", ltoken_getTextChars (*dom),
2085 sortSet_unparse (sortSetList_current (argSorts))); */
2086 matched = FALSE;
2087 break;
2088 }
2089 sortSetList_advance (argSorts);
2090 } end_ltokenList_elements;
2091
2092 return matched;
2093}
2094
2095/*@only@*/ lslOpSet
2096 symtable_opsWithLegalDomain (symtable tab, /*@temp@*/ /*@null@*/ nameNode n,
53306cab 2097 sortSetList argSorts, sort q)
616915dd 2098{
2099 /* handles nil qual */
2100 lslOpSet ops = lslOpSet_new ();
2101 lslOp op;
2102 sort rangeSort;
2103 opInfo oi;
2104
2105 llassert (n != NULL);
2106 oi = symtable_opInfo (tab, n);
2107
2108 if (opInfo_exists (oi))
2109 {
2110 sigNodeSet sigs = oi->signatures;
2111
2112 sigNodeSet_elements (sigs, sig)
2113 {
2114 if (ltokenList_size (sig->domain) == sortSetList_size (argSorts))
2115 {
2116 rangeSort = sigNode_rangeSort (sig);
2117
53306cab 2118 if ((q == NULL) || (sort_equal (rangeSort, q)))
616915dd 2119 {
2120 if (domainMatches (sig->domain, argSorts))
2121 {
2122 op = (lslOp) dmalloc (sizeof (*op));
2123
2124 /* each domain sort in op must be an element of
2125 the corresponding set in argSorts. */
2126 op->signature = sig;
2127 op->name = nameNode_copy (n);
2128 (void) lslOpSet_insert (ops, op);
2129 }
2130 }
2131 }
2132 } end_sigNodeSet_elements;
2133 }
2134 return ops;
2135}
This page took 0.351474 seconds and 5 git commands to generate.