2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
29 ** NOTE: The structure of this module follows a similar one
30 ** used in the previous LCL checker. However, all other
31 ** details are quite different.
35 ** Massachusetts Institute of Technology
38 # include "lclintMacros.nf"
40 # include "llgrammar.h"
45 static lsymbol newStructTag (void) /*@*/ ;
46 static lsymbol newEnumTag (void) /*@*/ ;
47 static lsymbol newUnionTag (void) /*@*/ ;
49 /*@constant static int MAXBUFFLEN; @*/
50 # define MAXBUFFLEN 1024
52 /*@constant static int DELTA; @*/
55 /*@constant static int NOSORTHANDLE; @*/
56 # define NOSORTHANDLE 0
58 /*@constant static int HOFSORTHANDLE; @*/
59 # define HOFSORTHANDLE 1
63 static void sort_addTupleMembers (sort p_tupleSort, sort p_strSort)
64 /*@modifies internalState@*/ ;
66 static bool sort_isNewEntry (sortNode p_s) /*@*/ ;
68 static sort sort_enterNew (/*@special@*/ sortNode p_s)
69 /*@uses p_s.kind, p_s.name, p_s.members@*/
70 /*@releases p_s.members@*/
71 /*@modifies internalState@*/ ;
73 static sort sort_enterGlobal (sortNode p_s) /*@modifies internalState@*/ ;
75 static sort sort_enterNewForce (/*@special@*/ sortNode p_s)
76 /*@uses p_s.kind, p_s.name, p_s.members@*/
77 /*@releases p_s.members@*/
78 /*@modifies internalState@*/ ;
80 static void genPtrOps (sort p_baseSort, sort p_ptrSort, sort p_arraySort);
81 static void genArrOps (sort p_baseSort, sort p_arraySort, int p_dim,
83 static void genVecOps (sort p_baseSort, sort p_vecSort, int p_dim);
84 static void genTupleOps (sort p_tupleSort);
85 static void genUnionOps (sort p_tupleSort);
86 static void genStrOps (sort p_strSort, sort p_tupleSort);
87 static void genEnumOps (sort p_enumSort);
89 static void overloadPtrFcns (sort p_ptrSort);
90 static void overloadIsSub (sort p_s, int p_dim);
91 static void overloadSizeof (sort p_domainSort);
93 /*@observer@*/ static cstring sort_unparseKind (sortKind p_k) /*@*/ ;
95 static /*@observer@*/ cstring
96 sort_unparseKindName (sortNode p_s) /*@*/ ;
99 sortTag_toSymbol (char *p_kind, ltoken p_tagid, /*@out@*/ bool *p_isNew);
102 overloadUnaryTok (/*@only@*/ nameNode p_nn,
103 sort p_domainSort, /*@only@*/ ltoken p_range);
105 overloadUnary (/*@only@*/ nameNode p_nn,
106 sort p_domainSort, sort p_rangeSort);
108 overloadBinary (/*@only@*/ nameNode p_nn,
109 sort p_s, /*@only@*/ ltoken p_dTok, sort p_rs);
110 static /*@only@*/ nameNode makeFieldOp (lsymbol p_field);
111 static /*@only@*/ nameNode makeArrowFieldOp (lsymbol p_field);
114 static lsymbol sp (lsymbol p_s1, lsymbol p_s2);
115 static void sortError (ltoken p_t, sort p_oldsort, sortNode p_newnode);
127 static sort sort_void;
128 static sort char_obj_ptrSort;
129 static sort char_obj_ArrSort;
131 /* This is used to uniqueize sort names, for anonymous C types */
132 static int sortUID = 1;
134 static /*@only@*/ /*@null@*/ sortNode *sortTable = (sortNode *) 0;
135 static int sortTableSize = 0;
136 static int sortTableAlloc = 0;
138 /* Important to keep sorts in some order because importing routines
139 for sorts rely on this order to ensure that when we encounter a sort
140 S1 that is based on sort S2, S2 is before S1 in the imported file. */
142 static bool exporting = TRUE;
144 static lsymbol underscoreSymbol;
145 static /*@only@*/ ltoken intToken;
147 static /*@owned@*/ nameNode arrayRefNameNode;
148 static /*@owned@*/ nameNode ptr2arrayNameNode;
149 static /*@owned@*/ nameNode deRefNameNode;
150 static /*@owned@*/ nameNode nilNameNode;
151 static /*@owned@*/ nameNode plusNameNode;
152 static /*@owned@*/ nameNode minusNameNode;
153 static /*@owned@*/ nameNode condNameNode;
154 static /*@owned@*/ nameNode eqNameNode;
155 static /*@owned@*/ nameNode neqNameNode;
157 static sortNode noSort;
159 static sortNode HOFSort =
165 FALSE, /* was lsymbolNULL */
168 smemberInfo_undefined,
175 static ob_mstring sortKindName[] =
177 "FIRSTSORT", "NOSORT", "HOFSORT",
178 "PRIMITIVE", "SYNONYM", "POINTER", "OBJ", "ARRAY", "VECTOR",
179 "STRUCT", "TUPLE", "UNION", "UNIONVAL", "ENUM", "LASTSORT"
182 static void smemberInfo_free (/*@null@*/ /*@only@*/ smemberInfo *mem)
187 static void sortNode_free (/*@special@*/ sortNode sn)
188 /*@uses sn.members@*/
189 /*@releases sn.members@*/
191 smemberInfo_free (sn.members);
195 sort_destroyMod (void)
196 /*@globals killed sortTable, killed arrayRefNameNode,
197 killed ptr2arrayNameNode,killed deRefNameNode,
198 killed nilNameNode, killed plusNameNode,
199 killed minusNameNode, killed condNameNode,
200 killed eqNameNode, killed neqNameNode @*/
202 if (sortTable != NULL)
206 for (i = 0; i < sortTableSize; i++)
208 sortNode_free (sortTable[i]);
211 nameNode_free (arrayRefNameNode);
212 nameNode_free (ptr2arrayNameNode);
213 nameNode_free (deRefNameNode);
214 nameNode_free (nilNameNode);
215 nameNode_free (plusNameNode);
216 nameNode_free (minusNameNode);
217 nameNode_free (condNameNode);
218 nameNode_free (eqNameNode);
219 nameNode_free (neqNameNode);
227 sort_makeNoSort (void)
233 sort_makeHOFSort (sort base)
238 outSort.kind = SRT_HOF;
239 outSort.name = cstring_toSymbol (message ("_HOF_sort_%d", sortTableSize));
240 outSort.tag = lsymbol_undefined;
241 outSort.baseSort = base;
242 outSort.objSort = NOSORTHANDLE;
243 outSort.members = smemberInfo_undefined;
244 outSort.export = exporting;
245 outSort.imported = context_inImport ();
246 outSort.mutable = FALSE;
247 outSort.abstract = FALSE;
249 llassert (sortTable != NULL);
251 outSort.handle = handle = sortTableSize;
252 sortTable[handle] = outSort;
259 sort_construct (lsymbol name, sortKind kind, sort baseSort,
261 bool mut, sort objSort, /*@null@*/ smemberInfo *members)
266 handle = sort_lookupName (name);
270 outSort.tag = tagName;
271 outSort.realtag = TRUE;
272 outSort.baseSort = baseSort;
273 outSort.objSort = objSort;
274 outSort.members = members;
275 outSort.mutable = mut;
276 outSort.export = exporting;
277 outSort.imported = context_inImport ();
278 outSort.abstract = FALSE;
279 outSort.handle = handle;
281 if (handle == NOSORTHANDLE)
283 outSort.handle = handle = sort_enterNew (outSort);
288 llassert (sortTable != NULL);
290 if (sortTable[handle].kind != kind)
292 sortError (ltoken_undefined, handle, outSort);
293 smemberInfo_free (outSort.members);
299 /* evs --- added 11 Mar 1994
300 ** the new entry should supercede the old one, since
301 ** it could be a forward reference to a struct, etc.
304 sortTable[handle] = outSort;
311 sort_constructAbstract (lsymbol name, bool mut, sort baseSort)
322 handle = sort_lookupName (name);
325 outSort.tag = lsymbol_undefined;
326 outSort.baseSort = baseSort;
327 outSort.objSort = NOSORTHANDLE;
328 outSort.members = smemberInfo_undefined;
329 outSort.mutable = mut;
330 outSort.export = exporting;
331 outSort.imported = context_inImport ();
332 outSort.abstract = TRUE;
333 outSort.handle = handle;
335 if (handle == NOSORTHANDLE)
337 outSort.handle = handle = sort_enterNew (outSort);
338 /* do not make sort operators. */
342 llassert (sortTable != NULL);
344 if (sortTable[handle].kind != kind)
346 sortError (ltoken_undefined, handle, outSort);
349 smemberInfo_free (outSort.members);
356 sort_makeSort (/*@unused@*/ ltoken t, lsymbol n)
359 ** Expects n to be a new sort.
360 ** Generate a sort with the given name. Useful for LSL sorts.
363 sort handle = sort_lookupName (n);
365 if (handle == NOSORTHANDLE)
369 outSort.handle = handle;
370 outSort.kind = SRT_PRIM;
372 outSort.tag = lsymbol_undefined;
373 outSort.baseSort = NOSORTHANDLE;
374 outSort.objSort = NOSORTHANDLE;
375 outSort.members = smemberInfo_undefined;
376 outSort.export = exporting;
377 outSort.mutable = FALSE;
378 outSort.imported = context_inImport ();
379 outSort.abstract = FALSE;
381 /* Put into sort table, sort_enter checks for duplicates. */
382 outSort.handle = handle = sort_enterNew (outSort);
386 /* don't override old info */
394 sort_makeSortNoOps (/*@unused@*/ ltoken t, lsymbol n) /*@modifies internalState@*/
398 handle = sort_lookupName (n);
400 if (handle == NOSORTHANDLE)
404 outSort.handle = handle;
405 outSort.kind = SRT_PRIM;
407 outSort.tag = lsymbol_undefined;
408 outSort.baseSort = NOSORTHANDLE;
409 outSort.objSort = NOSORTHANDLE;
410 outSort.members = smemberInfo_undefined;
411 outSort.export = exporting;
412 outSort.mutable = FALSE;
413 outSort.imported = context_inImport ();
414 outSort.abstract = FALSE;
415 /* Put into sort table, sort_enter checks for duplicates. */
416 outSort.handle = handle = sort_enterNew (outSort);
417 } /* don't override old info */
423 sort_makeLiteralSort (ltoken t, lsymbol n)
424 /*@modifies internalState@*/
427 ** Like sort_makeSort, in addition, generate sizeof operator
428 ** t not currently used, may be useful for generating error msgs later
429 ** Also useful for abstract types, need sizeof operator.
432 sort handle = sort_makeSort (t, n);
434 overloadSizeof (handle);
439 sort_makeSyn (ltoken t, sort s, lsymbol n)
441 /* make a synonym sort with name n that is == to sort s */
442 /* expect n to be a new sort name */
445 /* must not clash with any LSL sorts */
446 lsymbol newname = sp (underscoreSymbol, n);
448 if (n == lsymbol_undefined)
450 llbuglit ("sort_makeSyn: synonym must have name");
453 handle = sort_lookupName (newname);
455 outSort.kind = SRT_SYN;
456 outSort.name = newname;
457 outSort.baseSort = s;
458 outSort.objSort = NOSORTHANDLE;
459 /* info is not duplicated */
460 outSort.tag = lsymbol_undefined;
461 outSort.members = smemberInfo_undefined;
462 outSort.export = exporting;
463 outSort.mutable = FALSE;
464 outSort.imported = context_inImport ();
465 outSort.abstract = FALSE;
466 outSort.handle = handle;
468 if (handle == NOSORTHANDLE)
470 outSort.handle = handle = sort_enterNew (outSort);
471 /* No operators to generate for synonyms */
475 llassert (sortTable != NULL);
477 if (sortTable[handle].kind != SRT_SYN)
479 sortError (t, handle, outSort);
482 smemberInfo_free (outSort.members);
489 sort_makeFormal (sort insort)
494 sor = sort_getUnderlying (insort);
496 s = sort_lookup (sor);
501 handle = sort_makeTuple (ltoken_undefined, sor);
504 handle = sort_makeUnionVal (ltoken_undefined, sor);
514 sort_makeGlobal (sort insort)
516 /* Make a Obj if not an array or a struct */
519 sor = sort_getUnderlying (insort);
521 s = sort_lookup (sor);
534 llcontbuglit ("sort_makeGlobal: can't make vectors, tuples, or unionvals global");
537 handle = sort_makeObj (sor);
544 sort_makeObj (sort sor)
546 sortNode baseSortNode, outSort;
547 sort baseSort, handle;
550 /* skip the synonym sort */
551 baseSort = sort_getUnderlying (sor);
552 baseSortNode = sort_quietLookup (baseSort);
553 switch (baseSortNode.kind)
559 if (baseSortNode.objSort != 0)
560 return baseSortNode.objSort;
561 else /* must have well-defined objSort field */
563 llcontbuglit ("sort_makeObj: Inconsistent vector reps:invalid objSort field");
568 /* need to map *_Struct_Tuple to *_Struct and *_Union_UnionVal to
569 *_Union, according to sort naming conventions */
570 if (baseSortNode.baseSort != NOSORTHANDLE)
571 /* for tuples and unionvals, baseSort field keeps the map from
572 value sort to obj sort. */
573 return baseSortNode.baseSort;
574 else /* valid tuples and unionvals must have baseSort fields */
576 llcontbuglit ("sort_makeObj: Inconsistent tuples or unionvals reps: invalid baseSort field");
580 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
581 lsymbol_fromChars ("_Obj"));
582 handle = sort_lookupName (name);
584 outSort.kind = SRT_OBJ;
585 /* must not clash with any LSL sorts */
587 outSort.tag = lsymbol_undefined;
588 outSort.baseSort = baseSort;
589 outSort.objSort = NOSORTHANDLE;
590 outSort.members = smemberInfo_undefined;
591 outSort.mutable = TRUE;
592 outSort.export = exporting;
593 outSort.abstract = FALSE;
594 outSort.handle = handle;
595 outSort.imported = TRUE;
597 if (handle == NOSORTHANDLE)
599 if (sort_isNewEntry (outSort))
601 outSort.handle = handle = sort_enterNew (outSort);
605 outSort.handle = handle = sort_enterNew (outSort);
610 llassert (sortTable != NULL);
612 if (sortTable[handle].kind != SRT_OBJ)
614 sortError (ltoken_undefined, handle, outSort);
617 smemberInfo_free (outSort.members);
625 sort_makePtr (ltoken t, sort baseSort)
628 sort handle, arrayHandle;
631 s = sort_lookup (baseSort);
633 if (s.kind == SRT_HOF)
637 if (s.kind == SRT_NONE)
642 if (s.kind != SRT_ARRAY && s.kind != SRT_STRUCT &&
644 /* && s.kind != SRT_OBJ) */
645 /* base is not an SRT_ARRAY, struct or union. Need to insert a obj. */
646 baseSort = sort_makeObj (baseSort);
648 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
649 lsymbol_fromChars ("_Ptr"));
650 handle = sort_lookupName (name);
652 outSort.kind = SRT_PTR;
654 outSort.tag = lsymbol_undefined;
655 outSort.baseSort = baseSort;
656 outSort.objSort = NOSORTHANDLE;
657 outSort.members = smemberInfo_undefined;
658 outSort.mutable = FALSE;
659 outSort.export = exporting;
660 outSort.imported = context_inImport ();
661 outSort.abstract = FALSE;
662 outSort.handle = handle;
664 if (handle == NOSORTHANDLE)
666 if (sort_isNewEntry (outSort))
668 outSort.handle = handle = sort_enterNew (outSort);
669 arrayHandle = sort_makeArr (t, baseSort);
670 genPtrOps (baseSort, handle, arrayHandle);
674 outSort.handle = handle = sort_enterNew (outSort);
679 llassert (sortTable != NULL);
681 if (sortTable[handle].kind != SRT_PTR)
683 sortError (t, handle, outSort);
685 smemberInfo_free (outSort.members);
691 sort_makePtrN (sort s, int pointers)
693 llassert (pointers >= 0);
701 return sort_makePtrN (sort_makePtr (ltoken_undefined, s),
707 sort_makeArr (ltoken t, sort baseSort)
709 sortNode s, outSort, old;
710 sort handle, vecHandle;
714 s = sort_lookup (baseSort);
716 if (s.kind == SRT_HOF)
718 if (s.kind == SRT_NONE)
721 if (s.kind != SRT_ARRAY && s.kind != SRT_STRUCT &&
722 s.kind != SRT_UNION && s.kind != SRT_OBJ)
723 /* base is not an array, struct or obj. Need to insert a Obj. */
724 baseSort = sort_makeObj (baseSort);
726 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
727 lsymbol_fromChars ("_Arr"));
728 handle = sort_lookupName (name);
730 /* must not clash with any LSL sorts */
732 outSort.kind = SRT_ARRAY;
733 outSort.baseSort = baseSort;
734 outSort.objSort = NOSORTHANDLE;
735 outSort.members = smemberInfo_undefined;
736 outSort.mutable = TRUE;
737 outSort.export = exporting;
738 outSort.imported = context_inImport ();
739 outSort.abstract = FALSE;
740 outSort.handle = handle;
742 if (handle == NOSORTHANDLE)
744 if (sort_isNewEntry (outSort))
746 outSort.handle = handle = sort_enterNew (outSort);
748 for (old = outSort, dim = 0;
749 old.kind == SRT_ARRAY;
750 dim++, old = sort_lookup (old.baseSort))
755 vecHandle = sort_makeVec (t, handle);
756 genArrOps (baseSort, handle, dim, vecHandle);
760 outSort.handle = handle = sort_enterNew (outSort);
765 llassert (sortTable != NULL);
767 if (sortTable[handle].kind != SRT_ARRAY)
769 sortError (t, handle, outSort);
772 smemberInfo_free (outSort.members);
779 sort_makeVec (ltoken t, sort arraySort)
781 sortNode s, outSort, old;
782 sort baseSort, handle, elementSort;
783 int dim; /* array dimension count. */
786 s = sort_lookup (arraySort);
788 if (s.kind == SRT_HOF)
790 if (s.kind == SRT_NONE)
793 if (s.kind != SRT_ARRAY)
795 llbug (message ("sort_makeVec: only arrays can become vectors: given sort is %s",
796 sort_unparseKind (s.kind)));
799 if (s.baseSort == NOSORTHANDLE)
800 llbuglit ("sort_makeVec: arrays must have base (element) sort");
802 /* Vectors return "values", so make array elements values. */
804 baseSort = s.baseSort;
805 elementSort = sort_makeVal (baseSort);
807 name = sp (sp (underscoreSymbol, sort_getLsymbol (elementSort)),
808 lsymbol_fromChars ("_Vec"));
809 handle = sort_lookupName (name);
811 outSort.baseSort = elementSort;
813 outSort.objSort = arraySort;
814 outSort.kind = SRT_VECTOR;
815 outSort.members = smemberInfo_undefined;
816 outSort.mutable = FALSE;
817 outSort.export = exporting;
818 outSort.imported = context_inImport ();
819 outSort.abstract = FALSE;
820 outSort.handle = handle;
822 if (handle == NOSORTHANDLE)
824 if (sort_isNewEntry (outSort))
826 outSort.handle = handle = sort_enterNew (outSort);
828 for (old = outSort, dim = 0;
829 old.kind == SRT_VECTOR;
830 dim++, old = sort_lookup (old.baseSort))
835 genVecOps (elementSort, handle, dim);
839 outSort.handle = handle = sort_enterNew (outSort);
844 llassert (sortTable != NULL);
846 if (sortTable[handle].kind != SRT_VECTOR)
848 sortError (t, handle, outSort);
851 smemberInfo_free (outSort.members);
858 sort_makeVal (sort sor)
863 llassert (sortTable != NULL);
864 s = sort_quietLookup (sor);
876 /* Do nothing for basic types and pointers. */
880 return sort_makeVal (sortTable[sor].baseSort);
882 /* Strip out the last Obj's */
883 if (s.baseSort == NOSORTHANDLE)
885 llbuglit ("sort_makeVal: expecting a base sort for Obj");
887 retSort = s.baseSort;
890 retSort = sort_makeVec (ltoken_undefined, sor);
893 retSort = sort_makeTuple (ltoken_undefined, sor);
896 retSort = sort_makeUnionVal (ltoken_undefined, sor);
899 llbuglit ("sort_makeVal: invalid sort kind");
901 rsn = sort_quietLookup (retSort);
902 if (rsn.kind == SRT_NONE)
904 llfatalbug (message ("sort_makeVal: invalid return sort kind: %d", (int)rsn.kind));
910 sort_makeImmutable (ltoken t, lsymbol name)
915 handle = sort_lookupName (name);
917 outSort.kind = SRT_PRIM;
919 outSort.baseSort = NOSORTHANDLE;
920 outSort.objSort = NOSORTHANDLE;
921 outSort.members = smemberInfo_undefined;
922 outSort.export = exporting;
923 outSort.mutable = FALSE;
924 outSort.imported = context_inImport ();
925 outSort.abstract = TRUE;
926 outSort.handle = handle;
928 if (handle == NOSORTHANDLE)
930 outSort.handle = handle = sort_enterNew (outSort);
931 overloadSizeof (handle);
935 llassert (sortTable != NULL);
937 if ((sortTable[handle].kind != SRT_PRIM) &&
938 (sortTable[handle].abstract) &&
939 (!sortTable[handle].mutable))
941 sortError (t, handle, outSort);
944 smemberInfo_free (outSort.members);
951 sort_makeMutable (ltoken t, lsymbol name)
953 sort immutable_old, handle, baseSort;
956 immutable_old = sort_lookupName (name);
958 /* First generate the value sort */
959 baseSort = sort_makeImmutable (t, name);
961 llassert (sortTable != NULL);
963 /* to prevent duplicate error messages */
964 if (immutable_old != NOSORTHANDLE &&
965 (sortTable[baseSort].kind != SRT_PRIM) &&
966 (sortTable[baseSort].abstract) &&
967 (!sortTable[baseSort].mutable))
969 /* already complained */
970 handle = NOSORTHANDLE;
973 { /* sort_makeImmutable must have succeeded */
976 /* must not clash with any LSL sorts */
977 objName = sp (sp (underscoreSymbol, name),
978 lsymbol_fromChars ("_Obj"));
979 handle = sort_lookupName (objName);
981 outSort.kind = SRT_OBJ;
982 outSort.name = objName;
983 outSort.tag = lsymbol_undefined;
984 outSort.baseSort = baseSort;
985 outSort.objSort = NOSORTHANDLE;
986 outSort.members = smemberInfo_undefined;
987 outSort.mutable = TRUE;
988 outSort.export = exporting;
989 outSort.imported = context_inImport ();
990 outSort.abstract = TRUE;
991 outSort.handle = handle;
993 if (handle == NOSORTHANDLE)
995 if (sort_isNewEntry (outSort))
997 outSort.handle = handle = sort_enterNew (outSort);
1001 handle = sort_enterNew (outSort);
1006 llassert (sortTable != NULL);
1008 if ((sortTable[handle].kind != SRT_OBJ)
1009 && sortTable[handle].abstract
1010 && sortTable[handle].mutable)
1012 sortError (t, handle, outSort);
1015 smemberInfo_free (outSort.members);
1022 sort_makeStr (ltoken opttagid)
1029 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1030 /* isNewTag true means that the name generated is new */
1032 if (ltoken_isUndefined (opttagid))
1034 opttagid = ltoken_create (simpleId, newStructTag ());
1036 outSort.realtag = FALSE;
1040 outSort.realtag = TRUE;
1043 name = sortTag_toSymbol ("Struct", opttagid, &isNewTag);
1045 llassert (sortTable != NULL);
1046 handle = sort_lookupName (name);
1047 outSort.name = name;
1048 outSort.kind = SRT_STRUCT;
1049 outSort.tag = ltoken_getText (opttagid);
1050 outSort.baseSort = NOSORTHANDLE;
1051 outSort.objSort = NOSORTHANDLE;
1052 outSort.members = smemberInfo_undefined;
1053 outSort.export = exporting;
1054 outSort.mutable = TRUE;
1055 outSort.imported = context_inImport ();
1056 outSort.abstract = FALSE;
1057 outSort.handle = handle;
1059 if (handle == NOSORTHANDLE)
1061 if (sort_isNewEntry (outSort))
1063 outSort.handle = handle = sort_enterNew (outSort);
1067 outSort.handle = handle = sort_enterNewForce (outSort);
1072 if (sortTable[handle].kind != SRT_STRUCT)
1074 sortError (opttagid, handle, outSort);
1077 smemberInfo_free (outSort.members);
1084 sort_updateStr (sort strSort, /*@only@*/ smemberInfo *info)
1086 /* expect strSort to be in sort table but not yet filled in */
1087 /* return TRUE if it is "new" */
1091 llassert (sortTable != NULL);
1092 sn = sort_lookup (strSort);
1094 if (sn.members == (smemberInfo *) 0)
1096 sortTable[strSort].members = info;
1097 tupleSort = sort_makeTuple (ltoken_undefined, strSort);
1098 genStrOps (strSort, tupleSort);
1103 smemberInfo_free (info);
1109 sort_makeTuple (ltoken t, sort strSort)
1112 sortNode outSort, s = sort_lookup (strSort);
1115 if (s.kind != SRT_STRUCT)
1117 llfatalbug (message ("sort_makeTuple: Only structs can become tuples: given sort is %s",
1118 sort_unparseKind (s.kind)));
1121 name = sp (s.name, lsymbol_fromChars ("_Tuple"));
1122 llassert (sortTable != NULL);
1123 handle = sort_lookupName (name);
1125 outSort.kind = SRT_TUPLE;
1126 outSort.name = name;
1127 outSort.tag = s.tag;
1128 outSort.realtag = s.realtag;
1129 outSort.baseSort = strSort;
1130 outSort.objSort = NOSORTHANDLE;
1131 outSort.members = smemberInfo_undefined;
1132 outSort.export = exporting;
1133 outSort.abstract = FALSE;
1134 outSort.imported = context_inImport ();
1135 outSort.mutable = FALSE;
1136 outSort.handle = handle;
1138 if (handle == NOSORTHANDLE)
1140 if (sort_isNewEntry (outSort))
1142 outSort.handle = handle = sort_enterNew (outSort);
1144 sort_addTupleMembers (handle, strSort);
1145 genTupleOps (handle);
1149 outSort.handle = handle = sort_enterNew (outSort);
1154 if (sortTable[handle].kind != SRT_TUPLE)
1156 sortError (t, handle, outSort);
1159 smemberInfo_free (outSort.members);
1166 sort_addTupleMembers (sort tupleSort, sort strSort)
1168 smemberInfo *mem, *tail = smemberInfo_undefined;
1169 smemberInfo *top = smemberInfo_undefined;
1170 smemberInfo *newinfo;
1172 /* make sure it works for empty smemberInfo */
1174 llassert (sortTable != NULL);
1176 for (mem = sortTable[strSort].members;
1177 mem != smemberInfo_undefined; mem = mem->next)
1179 newinfo = (smemberInfo *) dmalloc (sizeof (*newinfo));
1180 newinfo->name = mem->name;
1181 newinfo->sort = sort_makeVal (mem->sort);
1182 newinfo->next = smemberInfo_undefined;
1184 if (top == smemberInfo_undefined)
1185 { /* start of iteration */
1191 llassert (tail != smemberInfo_undefined);
1193 tail->next = newinfo;
1195 /*@-branchstate@*/ /* tail is dependent */
1200 sortTable[tupleSort].members = top;
1204 void genTupleOps (sort tupleSort)
1209 unsigned int memCount;
1210 ltokenList domain = ltokenList_new ();
1217 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (tupleSort));
1219 llassert (sortTable != NULL);
1220 for (m = sortTable[tupleSort].members;
1221 m != smemberInfo_undefined; m = m->next)
1223 fieldsort = sort_makeVal (m->sort);
1224 overloadUnary (makeFieldOp (m->name), tupleSort, fieldsort);
1226 dom = ltoken_createType (simpleId, SID_SORT,
1227 sort_getLsymbol (fieldsort));
1228 ltokenList_addh (domain, dom);
1232 /* For tuples only: [__, ...]: memSorts, ... -> tupleSort */
1233 signature = makesigNode (ltoken_undefined, domain, range);
1234 u.middle = memCount;
1236 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked),
1237 OPF_BMIDDLE, u, ltoken_copy (ltoken_rbracket));
1239 nn = makeNameNodeForm (opform);
1240 symtable_enterOp (g_symtab, nn, signature);
1243 ** should not be able to take sizeof (struct^) ...
1248 void genUnionOps (sort tupleSort)
1250 /* like genTupleOps but no constructor [ ...]: -> unionSort */
1254 llassert (sortTable != NULL);
1255 for (m = sortTable[tupleSort].members;
1256 m != smemberInfo_undefined; m = m->next)
1258 /* Generate __.memName: strSort ->memSortObj */
1259 overloadUnary (makeFieldOp (m->name), tupleSort, m->sort);
1260 /* printf ("making __.%s: %s -> %s\n", lsymbol_toChars (m->name),
1261 sort_getName (tupleSort), sort_getName (m->sort)); */
1262 /* __->memName : Union_Ptr -> memSortObj */
1263 sort = sort_makePtr (ltoken_undefined, tupleSort);
1264 overloadUnary (makeArrowFieldOp (m->name), sort, m->sort);
1265 /* printf ("making __->%s: %s -> %s\n", lsymbol_toChars (m->name),
1266 sort_getName (sort), sort_getName (m->sort)); */
1271 void genStrOps (sort strSort, /*@unused@*/ sort tupleSort)
1276 llassert (sortTable != NULL);
1277 for (m = sortTable[strSort].members;
1278 m != smemberInfo_undefined; m = m->next)
1280 /* Generate __.memName: strSort ->memSortObj */
1281 overloadUnary (makeFieldOp (m->name), strSort, m->sort);
1282 /* printf ("making __.%s: %s -> %s\n", lsymbol_toChars (m->name),
1283 sort_getName (strSort), sort_getName (m->sort)); */
1284 /* __->memName : Struct_Ptr -> memSortObj */
1285 sort = sort_makePtr (ltoken_undefined, strSort);
1286 overloadUnary (makeArrowFieldOp (m->name), sort, m->sort);
1287 /* printf ("making __->%s: %s -> %s\n", lsymbol_toChars (m->name),
1288 sort_getName (sort), sort_getName (m->sort)); */
1290 /* Generate fresh, trashed, modifies, unchanged: struct/union -> bool */
1291 /* Generate __any, __pre, __post: nStruct -> nTuple */
1292 /* Generate sizeof: strSort -> int */
1293 /* overloadStateFcns (strSort, tupleSort); */
1297 sort_makeUnion (ltoken opttagid)
1304 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1305 /* isNewTag true means that the name generated is new */
1307 if (ltoken_isUndefined (opttagid))
1309 opttagid = ltoken_create (simpleId, newUnionTag ());
1310 outSort.realtag = FALSE;
1313 outSort.realtag = TRUE;
1315 llassert (sortTable != NULL);
1316 name = sortTag_toSymbol ("Union", opttagid, &isNewTag);
1317 handle = sort_lookupName (name);
1318 outSort.name = name;
1319 outSort.kind = SRT_UNION;
1320 outSort.tag = ltoken_getText (opttagid);
1321 outSort.baseSort = NOSORTHANDLE;
1322 outSort.objSort = NOSORTHANDLE;
1323 outSort.members = smemberInfo_undefined;
1324 outSort.export = exporting;
1325 outSort.mutable = TRUE;
1326 outSort.imported = context_inImport ();
1327 outSort.abstract = FALSE;
1328 outSort.handle = handle;
1330 if (handle == NOSORTHANDLE)
1332 if (sort_isNewEntry (outSort))
1334 outSort.handle = handle = sort_enterNew (outSort);
1338 outSort.handle = handle = sort_enterNewForce (outSort);
1343 if (sortTable[handle].kind != SRT_UNION)
1345 sortError (opttagid, handle, outSort);
1348 smemberInfo_free (outSort.members);
1355 sort_updateUnion (sort unionSort, /*@only@*/ smemberInfo *info)
1357 /* expect unionSort to be in sort table but not yet filled in */
1358 /* return TRUE if it is "new" */
1362 llassert (sortTable != NULL);
1364 sn = sort_lookup (unionSort);
1366 if (sn.members == (smemberInfo *) 0)
1368 sortTable[unionSort].members = info;
1369 uValSort = sort_makeUnionVal (ltoken_undefined, unionSort);
1370 /* same as struct operations */
1371 genStrOps (unionSort, uValSort);
1376 smemberInfo_free (info);
1382 sort_makeUnionVal (ltoken t, sort unionSort)
1385 sortNode outSort, s = sort_lookup (unionSort);
1388 if (s.kind != SRT_UNION)
1390 llfatalbug (message ("sort_makeUnion: only unions can become unionVals: given sort is: %s",
1391 sort_unparseKind (s.kind)));
1394 llassert (sortTable != NULL);
1396 name = sp (s.name, lsymbol_fromChars ("_UnionVal"));
1397 handle = sort_lookupName (name);
1399 outSort.kind = SRT_UNIONVAL;
1400 outSort.name = name;
1401 outSort.tag = s.tag;
1402 outSort.realtag = s.realtag;
1403 outSort.baseSort = unionSort;
1404 outSort.objSort = NOSORTHANDLE;
1405 outSort.members = smemberInfo_undefined;
1406 outSort.export = exporting;
1407 outSort.abstract = FALSE;
1408 outSort.imported = context_inImport ();
1409 outSort.mutable = FALSE;
1410 outSort.handle = handle;
1412 if (handle == NOSORTHANDLE)
1414 if (sort_isNewEntry (outSort))
1416 outSort.handle = handle = sort_enterNew (outSort);
1418 /* Add members to the unionVal's. */
1419 /* same as structs and tuples */
1421 sort_addTupleMembers (handle, unionSort);
1422 genUnionOps (handle);
1426 outSort.handle = handle = sort_enterNew (outSort);
1431 if (sortTable[handle].kind != SRT_UNIONVAL)
1433 sortError (t, handle, outSort);
1436 smemberInfo_free (outSort.members);
1445 static int ecount = 0;
1447 return (cstring_toSymbol (message ("e%s%de", context_moduleName (), ecount++)));
1453 static int ecount = 0;
1455 return (cstring_toSymbol (message ("s%s%ds", context_moduleName (), ecount++)));
1461 static int ecount = 0;
1463 return (cstring_toSymbol (message ("u%s%du", context_moduleName (), ecount++)));
1467 sort_makeEnum (ltoken opttagid)
1474 llassert (sortTable != NULL);
1476 if (ltoken_isUndefined (opttagid))
1478 opttagid = ltoken_create (simpleId, newEnumTag ());
1479 outSort.realtag = FALSE;
1482 outSort.realtag = TRUE;
1484 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1486 name = sortTag_toSymbol ("Enum", opttagid, &isNew);
1487 handle = sort_lookupName (name);
1488 outSort.name = name;
1489 outSort.kind = SRT_ENUM;
1490 outSort.tag = ltoken_getText (opttagid);
1491 outSort.baseSort = NOSORTHANDLE;
1492 outSort.objSort = NOSORTHANDLE;
1493 outSort.members = smemberInfo_undefined;
1494 outSort.export = exporting;
1495 outSort.mutable = FALSE;
1496 outSort.imported = context_inImport ();
1497 outSort.abstract = FALSE;
1498 outSort.handle = handle;
1500 if (handle == NOSORTHANDLE)
1502 if (sort_isNewEntry (outSort))
1504 outSort.handle = handle = sort_enterNew (outSort);
1508 outSort.handle = handle = sort_enterNewForce (outSort);
1513 if (sortTable[handle].kind != SRT_ENUM)
1515 sortError (opttagid, handle, outSort);
1518 smemberInfo_free (outSort.members);
1525 sort_updateEnum (sort enumSort, /*@only@*/ smemberInfo *info)
1528 ** Expect enumSort to be in sort table but not yet filled in.
1529 ** Return TRUE if it is "new"
1534 llassert (sortTable != NULL);
1536 sn = sort_lookup (enumSort);
1537 if (sn.members == (smemberInfo *) 0)
1539 sortTable[enumSort].members = info;
1540 genEnumOps (enumSort);
1545 smemberInfo_free (info);
1551 void genEnumOps (sort enumSort)
1554 ltokenList domain = ltokenList_new ();
1559 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (enumSort));
1560 signature = makesigNode (ltoken_undefined, domain, range);
1562 llassert (sortTable != NULL);
1564 for (ei = sortTable[enumSort].members;
1565 ei != (smemberInfo *) 0; ei = ei->next)
1567 mem = ltoken_createType (simpleId, SID_OP, ei->name);
1568 nn = makeNameNodeId (mem);
1569 symtable_enterOp (g_symtab, nn, sigNode_copy (signature));
1572 sigNode_free (signature);
1573 overloadSizeof (enumSort);
1577 genPtrOps (/*@unused@*/ sort baseSort, sort ptrSort, sort arraySort)
1579 /* Generate *__: xPtr -> x */
1581 /* overloadUnary (deRefNameNode, ptrSort, baseSort); */
1583 /* Generate maxIndex, minIndex: xPtr -> int */
1584 /* overloadUnaryTok (maxIndexNameNode, ptrSort, intToken); */
1585 /* overloadUnaryTok (minIndexNameNode, ptrSort, intToken); */
1587 /* Generate __[]: pointer -> array */
1588 overloadUnary (nameNode_copySafe (ptr2arrayNameNode), ptrSort, arraySort);
1590 /* Generate __+__, __-__: pointer, int -> pointer */
1591 overloadBinary (nameNode_copySafe (plusNameNode), ptrSort,
1592 ltoken_copy (intToken), ptrSort);
1594 overloadBinary (nameNode_copySafe (minusNameNode), ptrSort,
1595 ltoken_copy (intToken), ptrSort);
1597 /* Generate NIL: -> xPtr */
1598 /* Generate __+__: int, pointer -> pointer */
1599 /* Generate __-__: pointer, pointer -> int */
1600 overloadPtrFcns (ptrSort);
1604 genArrOps (sort baseSort, sort arraySort, int dim, /*@unused@*/ sort vecSort)
1606 /* Generate __[__]: nArr, int -> n */
1607 overloadBinary (nameNode_copySafe (arrayRefNameNode), arraySort,
1608 ltoken_copy (intToken), baseSort);
1610 /* Generate maxIndex, minIndex: sort -> int */
1611 /* overloadUnaryTok (maxIndexNameNode, arraySort, intToken); */
1612 /* overloadUnaryTok (minIndexNameNode, arraySort, intToken); */
1614 /* Generate isSub: arraySort, int, ... -> bool */
1615 overloadIsSub (arraySort, dim);
1617 /* Generate fresh, trashed, modifies, unchanged: array -> bool */
1618 /* Generate any, pre, post: array -> vector */
1620 /* overloadStateFcns (arraySort, vecSort); */
1621 /* overloadObjFcns (arraySort); */
1626 ** generate NIL: -> ptrSort
1627 ** __+__: int, ptrSort -> ptrSort
1628 ** __-__: ptrSort, ptrSort -> int
1631 overloadPtrFcns (sort ptrSort)
1633 ltokenList domain = ltokenList_new ();
1637 /* NIL: -> ptrSort */
1639 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (ptrSort));
1640 signature = makesigNode (ltoken_undefined, ltokenList_new (), ltoken_copy (range));
1641 symtable_enterOp (g_symtab, nameNode_copySafe (nilNameNode), signature);
1643 /* __+__: int, ptrSort -> ptrSort */
1645 ltokenList_addh (domain, ltoken_copy (intToken));
1646 ltokenList_addh (domain, ltoken_copy (range));
1648 signature = makesigNode (ltoken_undefined, domain, ltoken_copy (range));
1649 symtable_enterOp (g_symtab, nameNode_copySafe (plusNameNode), signature);
1651 /* __-__: ptrSort, ptrSort -> int */
1653 domain = ltokenList_new ();
1654 ltokenList_addh (domain, ltoken_copy (range));
1655 ltokenList_addh (domain, range);
1656 range = ltoken_copy (intToken);
1657 signature = makesigNode (ltoken_undefined, domain, range);
1658 symtable_enterOp (g_symtab, nameNode_copySafe (minusNameNode), signature);
1662 genVecOps (sort baseSort, sort vecSort, int dim)
1664 /* Generate __[__]: vecSort, int -> baseSort */
1666 overloadBinary (nameNode_copySafe (arrayRefNameNode), vecSort,
1667 ltoken_copy (intToken), baseSort);
1669 /* sizeof: vecSort -> int */
1670 /* Generate isSub: vecSort, int, ... -> bool */
1672 overloadIsSub (vecSort, dim);
1676 overloadIsSub (sort s, int dim)
1678 /* Generate isSub: s, int, ... -> bool */
1680 ltoken dom, nulltok = ltoken_undefined;
1684 for (j = 1; j <= dim; j++)
1686 nameNode isSubNameNode = (nameNode) dmalloc (sizeof (*isSubNameNode));
1688 isSubNameNode->isOpId = TRUE;
1689 isSubNameNode->content.opid = ltoken_createType (simpleId, SID_OP,
1690 lsymbol_fromChars ("isSub"));
1691 dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (s));
1693 domain = ltokenList_singleton (dom);
1695 for (i = 1; i <= j; i++)
1697 ltokenList_addh (domain, ltoken_copy (intToken));
1700 signature = makesigNode (nulltok, domain, ltoken_copy (ltoken_bool));
1701 symtable_enterOp (g_symtab, isSubNameNode, signature);
1706 overloadUnaryTok (/*@only@*/ nameNode nn, sort domainSort, /*@only@*/ ltoken range)
1708 /* Generate <nn>: domainSort -> rangeTok */
1713 dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (domainSort));
1714 domain = ltokenList_singleton (dom);
1715 signature = makesigNode (ltoken_undefined, domain, range);
1716 symtable_enterOp (g_symtab, nn, signature);
1720 overloadSizeof (sort domainSort)
1722 nameNode sizeofNameNode = (nameNode) dmalloc (sizeof (*sizeofNameNode));
1724 sizeofNameNode->isOpId = TRUE;
1725 sizeofNameNode->content.opid = ltoken_createType (simpleId, SID_OP,
1726 lsymbol_fromChars ("sizeof"));
1728 overloadUnaryTok (sizeofNameNode, domainSort, ltoken_copy (intToken));
1732 overloadUnary (/*@only@*/ nameNode nn, sort domainSort, sort rangeSort)
1734 ltoken range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rangeSort));
1736 overloadUnaryTok (nn, domainSort, range);
1740 overloadBinary (/*@only@*/ nameNode nn, sort s, /*@only@*/ ltoken dTok, sort rs)
1742 /* Generate <nn>: s, dTok -> rs */
1745 ltokenList domain = ltokenList_new ();
1747 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rs));
1748 dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (s));
1750 ltokenList_addh (domain, dom);
1751 ltokenList_addh (domain, dTok);
1753 signature = makesigNode (ltoken_undefined, domain, range);
1754 symtable_enterOp (g_symtab, nn, signature);
1757 static /*@only@*/ nameNode
1758 makeFieldOp (lsymbol field)
1760 /* operator: __.<field> */
1765 u.id = ltoken_createType (simpleId, SID_OP, field);
1766 opform = makeOpFormNode (ltoken_undefined, OPF_MSELECT, u, ltoken_undefined);
1767 nn = makeNameNodeForm (opform);
1771 static /*@only@*/ nameNode
1772 makeArrowFieldOp (lsymbol field)
1774 /* operator: __-><field> */
1779 u.id = ltoken_createType (simpleId, SID_OP, field);
1780 opform = makeOpFormNode (ltoken_undefined, OPF_MMAP, u, ltoken_undefined);
1781 nn = makeNameNodeForm (opform);
1787 /*@globals undef noSort,
1788 undef arrayRefNameNode,
1789 undef ptr2arrayNameNode,
1790 undef deRefNameNode,
1793 undef minusNameNode,
1799 /* on alpha, declaration does not allocate storage */
1802 underscoreSymbol = lsymbol_fromChars ("_");
1805 ** commonly used data for generating operators
1808 lsymbol_setbool (lsymbol_fromChars ("bool"));
1809 intToken = ltoken_createType (simpleId, SID_SORT, lsymbol_fromChars ("int"));
1812 ** __ \eq __: sort, sort -> bool
1815 u.anyop = ltoken_copy (ltoken_eq);
1816 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1817 eqNameNode = makeNameNodeForm (opform);
1820 ** __ \neq __: sort, sort -> bool
1823 u.anyop = ltoken_copy (ltoken_neq);
1824 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1825 neqNameNode = makeNameNodeForm (opform);
1828 **if __ then __ else __: bool, sort, sort -> sort
1831 opform = makeOpFormNode (ltoken_undefined, OPF_IF,
1832 opFormUnion_createMiddle (0), ltoken_undefined);
1833 condNameNode = makeNameNodeForm (opform);
1835 /* operator: __[__]: arraySort, int -> elementSort_Obj */
1837 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked), OPF_BMMIDDLE, u,
1838 ltoken_copy (ltoken_rbracket));
1839 arrayRefNameNode = makeNameNodeForm (opform);
1841 /* operator: __[]: ptrSort -> arraySort */
1843 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked),
1845 ltoken_copy (ltoken_rbracket));
1846 ptr2arrayNameNode = makeNameNodeForm (opform);
1849 u.anyop = ltoken_create (LLT_MULOP, lsymbol_fromChars ("*"));
1850 opform = makeOpFormNode (ltoken_undefined, OPF_ANYOPM, u, ltoken_undefined);
1851 deRefNameNode = makeNameNodeForm (opform);
1853 /* operator: __ + __ */
1854 u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("+"));
1855 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1856 plusNameNode = makeNameNodeForm (opform);
1858 /* operator: __ - __ */
1859 u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("-"));
1860 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1861 minusNameNode = makeNameNodeForm (opform);
1864 nilNameNode = (nameNode) dmalloc (sizeof (*nilNameNode));
1865 nilNameNode->isOpId = TRUE;
1866 nilNameNode->content.opid = ltoken_createType (simpleId, SID_OP,
1867 lsymbol_fromChars ("NIL"));
1869 noSort.kind = SRT_NONE;
1870 noSort.name = lsymbol_fromChars ("_unknown");;
1871 noSort.tag = lsymbol_undefined;
1872 noSort.baseSort = NOSORTHANDLE;
1873 noSort.objSort = NOSORTHANDLE;
1874 noSort.members = smemberInfo_undefined;
1875 noSort.export = FALSE;
1876 noSort.mutable = FALSE;
1877 noSort.abstract = FALSE;
1878 noSort.imported = FALSE;
1879 noSort.handle = NOSORTHANDLE;
1882 ** Store the null sort into table, and in the process initialize the sort table.
1883 ** Must be the first sort_enter so NOSORTHANDLE is truly = 0. Similarly,
1884 ** for HOFSORTHANDLE = 1.
1887 noSort.handle = sort_enterGlobal (noSort);
1888 (void) sort_enterGlobal (HOFSort);
1890 /* Other builtin sorts */
1892 sort_bool = sort_makeImmutable (ltoken_undefined, lsymbol_fromChars ("bool"));
1893 sort_capBool = sort_makeSortNoOps (ltoken_undefined, lsymbol_fromChars ("Bool"));
1895 llassert (sortTable != NULL);
1897 /* make sort_Bool a synonym for sort_bool */
1898 sortTable[sort_capBool].kind = SRT_SYN;
1899 sortTable[sort_capBool].baseSort = sort_bool;
1900 sortTable[sort_capBool].mutable = FALSE;
1901 sortTable[sort_capBool].abstract = TRUE;
1903 sort_int = sort_makeLiteralSort (ltoken_undefined,
1904 lsymbol_fromChars ("int"));
1905 sort_char = sort_makeLiteralSort (ltoken_undefined,
1906 lsymbol_fromChars ("char"));
1907 sort_void = sort_makeLiteralSort (ltoken_undefined,
1908 lsymbol_fromChars ("void"));
1910 /* sort_cstring is char__Vec, for C strings eg: "xyz" */
1911 char_obj_ptrSort = sort_makePtr (ltoken_undefined, sort_char);
1912 char_obj_ArrSort = sort_makeArr (ltoken_undefined, sort_char);
1914 sort_cstring = sort_makeVal (char_obj_ArrSort);
1915 sort_float = sort_makeLiteralSort (ltoken_undefined, lsymbol_fromChars ("float"));
1916 sort_double = sort_makeLiteralSort (ltoken_undefined, lsymbol_fromChars ("double"));
1920 sort_lookupName (lsymbol name)
1924 if (name == lsymbol_undefined)
1926 return NOSORTHANDLE;
1929 llassert (sortTable != NULL);
1931 for (i = 0; i < sortTableSize; i++)
1933 if (sortTable[i].name == name)
1939 return NOSORTHANDLE;
1943 sort_isNewEntry (sortNode s)
1947 for (i = 0; i < sortTableSize; i++)
1949 llassert (sortTable != NULL);
1951 if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
1960 sort_enterGlobal (sortNode s)
1962 /*@i@*/ return (sort_enterNew (s));
1966 sort_enterNew (sortNode s)
1968 /* This ensures that the argument sortNode is not entered into
1969 the sort table more than once. isNew flag will tell the
1970 caller this info, and the caller will decide whether to generate
1971 operators for this sort. */
1974 for (i = 0; i < sortTableSize; i++)
1976 llassert (sortTable != NULL);
1978 if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
1985 if (sortTableSize >= sortTableAlloc)
1987 sortNode *oldSortTable = sortTable;
1989 sortTableAlloc += DELTA;
1990 sortTable = (sortNode *) dmalloc (sortTableAlloc * sizeof (*sortTable));
1992 if (sortTableSize > 0)
1994 llassert (oldSortTable != NULL);
1995 for (i = 0; i < sortTableSize; i++)
1997 sortTable[i] = oldSortTable[i];
2001 sfree (oldSortTable);
2004 llassert (sortTable != NULL);
2006 s.handle = sortTableSize;
2007 sortTable[sortTableSize++] = s;
2014 static sort sort_enterNewForce (sortNode s)
2016 sort sor = sort_enterNew (s);
2019 llassert (sortTable != NULL);
2022 /*@-globstate@*/ return (sor); /*@=globstate@*/
2026 sort_printStats (void)
2028 /* only for debugging */
2029 printf ("sortTableSize = %d; sortTableAlloc = %d\n", sortTableSize,
2034 sort_lookup (sort sor)
2036 /* ymtan: can sor be 0 ? */
2037 /* evs --- yup...0 should return noSort ? */
2039 if (sor > 0U && sor < (unsigned) sortTableSize)
2041 llassert (sortTable != NULL);
2042 return sortTable[sor];
2045 llassert (sor == 0);
2050 sort_quietLookup (sort sor)
2052 /* ymtan: can sor be 0 ? */
2053 if (sor > 0U && sor < (unsigned) sortTableSize)
2055 llassert (sortTable != NULL);
2056 return (sortTable[sor]);
2065 printEnumMembers (/*@null@*/ smemberInfo *list)
2067 cstring out = cstring_undefined;
2070 for (m = list; m != (smemberInfo *) 0; m = m->next)
2072 out = cstring_concat (out, lsymbol_toString (m->name));
2074 if (m->next != (smemberInfo *) 0)
2076 out = cstring_concatChars (out, ", ");
2082 static /*@only@*/ cstring
2083 printStructMembers (/*@null@*/ smemberInfo *list)
2085 cstring ret = cstring_undefined;
2088 for (m = list; m != (smemberInfo *) 0; m = m->next)
2090 ret = message ("%q%q %s; ",
2091 ret, sort_unparse (m->sort),
2092 cstring_fromChars (lsymbol_toChars (m->name)));
2099 sort_unparse (sort s)
2101 /* printing routine for sorts */
2105 sn = sort_quietLookup (s);
2111 if (name == lsymbol_undefined)
2113 return cstring_makeLiteral ("_unknown");
2116 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2118 return cstring_makeLiteral ("procedural");
2120 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2122 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2125 return (message ("%q *", sort_unparse (sort_makeVal (sn.baseSort))));
2127 return (message ("obj %q", sort_unparse (sn.baseSort)));
2129 return (message ("array of %q", sort_unparse (sort_makeVal (sn.baseSort))));
2131 return (message ("vector of %q", sort_unparse (sn.baseSort)));
2133 if (sn.tag != lsymbol_undefined && sn.realtag)
2135 return (message ("struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2139 return (message ("struct {%q}", printStructMembers (sn.members)));
2142 if (sn.tag != lsymbol_undefined && sn.realtag)
2144 return (message ("union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2148 return (message ("union {%q}", printStructMembers (sn.members)));
2151 if (sn.tag != lsymbol_undefined && sn.realtag)
2153 return (message ("enum %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2157 return (message ("enum {%q}", printEnumMembers (sn.members)));
2160 if (sn.tag != lsymbol_undefined && sn.realtag)
2162 return (message ("obj struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2166 return (message ("obj struct {%q}", printStructMembers (sn.members)));
2169 if (sn.tag != lsymbol_undefined && sn.realtag)
2171 return (message ("obj union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2175 return (message ("obj union {%q}", printStructMembers (sn.members)));
2178 return (cstring_makeLiteral ("illegal"));
2183 sp (lsymbol s1, lsymbol s2)
2185 char buff[MAXBUFFLEN];
2190 name1Ptr = lsymbol_toCharsSafe (s1);
2191 name2Ptr = lsymbol_toCharsSafe (s2);
2193 if (strlen (name1Ptr) + strlen (name2Ptr) + 1 > MAXBUFFLEN)
2195 temp_length = strlen (name1Ptr) + strlen (name2Ptr) + 1;
2196 llfatalbug (message ("sp: name too long: %s%s",
2197 cstring_fromChars (name1Ptr),
2198 cstring_fromChars (name2Ptr)));
2201 strcpy (&buff[0], name1Ptr);
2202 strcat (&buff[0], name2Ptr);
2204 return lsymbol_fromChars (&buff[0]);
2208 sortTag_toSymbol (char *kind, ltoken tagid, /*@out@*/ bool *isNew)
2211 ** kind could be struct, union or enum. Create a unique sort
2212 ** name based on the given info. But first check that tagid
2213 ** has not been defined already. (ok if it is a forward decl)
2218 if (ltoken_isUndefined (tagid))
2221 return (cstring_toSymbol (message ("_anon_%s%d", cstring_fromChars (kind), sortUID++)));
2225 to = symtable_tagInfo (g_symtab, ltoken_getText (tagid));
2227 if (tagInfo_exists (to))
2236 return (cstring_toSymbol (message ("_%s_%s",
2237 ltoken_unparse (tagid),
2238 cstring_fromChars (kind))));
2242 /*@constant int MAX_SORT_DEPTH@*/
2243 # define MAX_SORT_DEPTH 10
2246 sort_getUnderlyingAux (sort s, int depth)
2248 sortNode sn = sort_quietLookup (s);
2250 if (sn.kind == SRT_SYN)
2252 if (depth > MAX_SORT_DEPTH)
2254 llcontbug (message ("sort_getUnderlying: depth charge: %d", depth));
2258 return sort_getUnderlyingAux (sn.baseSort, depth + 1);
2265 sort_getUnderlying (sort s)
2267 return sort_getUnderlyingAux (s, 0);
2271 underlyingSortName (sortNode sn)
2273 if (sn.kind == SRT_SYN)
2274 return underlyingSortName (sort_quietLookup (sn.baseSort));
2278 static /*@observer@*/ sortNode
2279 underlyingSortNode (sortNode sn)
2281 if (sn.kind == SRT_SYN)
2283 return underlyingSortNode (sort_quietLookup (sn.baseSort));
2290 sort_mutable (sort s)
2292 /* if s is not a valid sort, then returns false */
2293 sortNode sn = sort_quietLookup (s);
2300 sort_setExporting (bool flag)
2308 /*@observer@*/ static cstring
2309 sort_unparseKind (sortKind k)
2311 if (k > SRT_FIRST && k < SRT_LAST)
2312 return (cstring_fromChars (sortKindName[(int)k]));
2314 return (cstring_makeLiteralTemp ("<unknown sort kind>"));
2318 sort_isValidSort (sort s)
2320 sortNode sn = sort_quietLookup (s);
2321 sortKind k = sn.kind;
2322 if (k != SRT_NONE && k > SRT_FIRST && k < SRT_LAST)
2329 sort_dump (FILE *f, bool lco)
2335 fprintf (f, "%s\n", BEGINSORTTABLE);
2336 llassert (sortTable != NULL);
2338 for (i = 2; i < sortTableSize; i++)
2340 /* skips 0 and 1, noSort and HOFSort */
2343 /* if (lco && !s.export) continue; */
2344 /* Difficult to keep track of where each op and sort belong to
2345 which LCL type. Easiest to export them all (even private sorts and
2346 op's) but for checking imported modules, we only use LCL types and
2347 variables to check, i.e., we don't rely on sorts and op's for such
2350 if (s.kind == SRT_NONE)
2355 fprintf (f, "%%LCL");
2358 if (lsymbol_isDefined (s.name))
2360 fprintf (f, "sort %s ", lsymbol_toCharsSafe (s.name));
2364 llcontbug (message ("Invalid sort in sort_dump: sort %d; sortname: %s. This may result from using .lcs files produced by an old version of LCLint. Remove the .lcs files, and rerun LCLint.",
2365 i, lsymbol_toString (s.name)));
2366 fprintf (f, "sort _error_ ");
2369 if (!lco && !s.export)
2370 fprintf (f, "private ");
2372 /*@-loopswitchbreak@*/
2376 fprintf (f, "hof nil nil\n");
2380 fprintf (f, "immutable nil nil\n");
2382 fprintf (f, "primitive nil nil\n");
2386 fprintf (f, "mutable %s nil\n",
2387 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2389 fprintf (f, "obj %s nil\n",
2390 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2393 fprintf (f, "synonym %s nil\n",
2394 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2397 fprintf (f, "ptr %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2400 fprintf (f, "arr %s nil\n",
2401 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2404 fprintf (f, "vec %s %s\n",
2405 lsymbol_toCharsSafe (sortTable[s.baseSort].name),
2406 lsymbol_toCharsSafe (sortTable[s.objSort].name));
2409 if (s.tag == lsymbol_undefined)
2411 /* we need to make up a tag to prevent excessive
2412 growth of .lcs files when tags are overloaded
2414 llbuglit ("Struct has no tag");
2417 fprintf (f, "str %s nil\n", lsymbol_toCharsSafe (s.tag));
2419 for (mem = s.members;
2420 mem != smemberInfo_undefined; mem = mem->next)
2423 fprintf (f, "%%LCL");
2424 fprintf (f, "sort %s strMem %s nil\n", lsymbol_toCharsSafe (mem->name),
2425 lsymbol_toCharsSafe (sortTable[mem->sort].name));
2428 fprintf (f, "%%LCL");
2429 fprintf (f, "sort strEnd nil nil nil\n");
2432 if (s.tag == lsymbol_undefined)
2433 llbuglit ("Union has no tag");
2435 fprintf (f, "union %s nil\n", lsymbol_toCharsSafe (s.tag));
2436 for (mem = s.members;
2437 mem != smemberInfo_undefined; mem = mem->next)
2440 fprintf (f, "%%LCL");
2441 fprintf (f, "sort %s unionMem %s nil\n", lsymbol_toCharsSafe (mem->name),
2442 lsymbol_toCharsSafe (sortTable[mem->sort].name));
2445 fprintf (f, "%%LCL");
2446 fprintf (f, "sort unionEnd nil nil nil\n");
2449 if (s.tag == lsymbol_undefined)
2451 llbuglit ("Enum has no tag");
2454 fprintf (f, "enum %s nil\n", lsymbol_toCharsSafe (s.tag));
2456 for (mem = s.members;
2457 mem != smemberInfo_undefined; mem = mem->next)
2460 fprintf (f, "%%LCL");
2461 fprintf (f, "sort %s enumMem nil nil\n", lsymbol_toCharsSafe (mem->name));
2464 fprintf (f, "%%LCL");
2465 fprintf (f, "sort enumEnd nil nil nil\n");
2468 fprintf (f, "tup %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2471 fprintf (f, "unionval %s nil\n",
2472 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2475 fprintf (f, "sort_dump: unexpected sort: %d", (int)s.kind);
2477 /*@=loopswitchbreak@*/
2480 fprintf (f, "%s\n", SORTTABLEEND);
2484 sort_loadOther (char *kstr, lsymbol sname, sort bsort)
2486 if (strcmp (kstr, "synonym") == 0)
2488 (void) sort_construct (sname, SRT_SYN, bsort, lsymbol_undefined,
2489 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2491 else if (strcmp (kstr, "mutable") == 0)
2493 (void) sort_constructAbstract (sname, TRUE, bsort);
2495 else if (strcmp (kstr, "obj") == 0)
2497 (void) sort_construct (sname, SRT_OBJ, bsort, lsymbol_undefined,
2498 TRUE, NOSORTHANDLE, smemberInfo_undefined);
2500 else if (strcmp (kstr, "ptr") == 0)
2502 (void) sort_construct (sname, SRT_PTR, bsort, lsymbol_undefined,
2503 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2505 else if (strcmp (kstr, "arr") == 0)
2507 (void) sort_construct (sname, SRT_ARRAY, bsort, lsymbol_undefined,
2508 TRUE, NOSORTHANDLE, smemberInfo_undefined);
2510 else if (strcmp (kstr, "tup") == 0)
2512 (void) sort_construct (sname, SRT_TUPLE, bsort, lsymbol_undefined,
2513 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2515 else if (strcmp (kstr, "unionval") == 0)
2517 (void) sort_construct (sname, SRT_UNIONVAL, bsort, lsymbol_undefined,
2518 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2522 llbug (message ("Unhandled: %s", cstring_fromChars (kstr)));
2527 parseSortLine (char *line, ltoken t, tsource * s,
2528 mapping *map, lsymbolList slist)
2530 /* caller expects that map and slist are updated */
2531 /* t and importfle are only used for error messages */
2532 static lsymbol strName = lsymbol_undefined;
2533 static smemberInfo *strMemList = NULL;
2534 static lsymbol unionName = lsymbol_undefined;
2535 static smemberInfo *unionMemList = NULL;
2536 static lsymbol enumName = lsymbol_undefined;
2537 static smemberInfo *enumMemList = NULL;
2538 static lsymbol tagName = lsymbol_undefined;
2540 char *importfile = tsource_fileName (s);
2541 char sostr[MAXBUFFLEN], kstr[10], basedstr[MAXBUFFLEN], objstr[MAXBUFFLEN];
2544 lsymbol sname, bname, new_name, objName;
2547 int col; /* for keeping column number */
2550 if (sscanf (line, "sort %s %s %s %s", &(sostr[0]), &(kstr[0]),
2551 &(basedstr[0]), &(objstr[0])) != 4)
2553 /* if this fails, can have weird errors */
2554 /* strEnd, unionEnd, enumEnd won't return 4 args */
2556 (message ("%q: Imported file contains illegal sort declaration. "
2557 "Skipping this line: \n%s\n",
2558 fileloc_unparseRaw (cstring_fromChars (importfile),
2559 tsource_thisLineNumber (s)),
2560 cstring_fromChars (line)));
2564 sname = lsymbol_fromChars (sostr);
2565 if (sname == lsymbol_fromChars ("nil"))
2567 /* No given sort name. Use lsymbol_undefined and generate sort name
2568 in sort building routines. */
2569 sname = lsymbol_undefined;
2570 lclerror (t, message ("Illegal sort declaration in import file: %s:\n%s",
2571 cstring_fromChars (importfile),
2572 cstring_fromChars (line)));
2575 /* Assume that when we encounter a sort S1 that is based on sort
2576 S2, S2 is before S1 in the imported file. sort table is a
2577 linear list and we create base sorts before other sorts. */
2579 bname = lsymbol_fromChars (basedstr);
2580 if (strcmp (kstr, "primitive") == 0)
2582 new_name = lsymbol_translateSort (map, sname);
2583 (void) sort_construct (new_name, SRT_PRIM, NOSORTHANDLE,
2584 lsymbol_undefined, FALSE,
2585 NOSORTHANDLE, smemberInfo_undefined);
2587 else if (strcmp (kstr, "strMem") == 0)
2589 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2590 mem->next = strMemList;
2592 mem->sortname = bname;
2593 mem->sort = NOSORTHANDLE;
2596 else if (strcmp (sostr, "strEnd") == 0)
2597 { /* now process it */
2598 if (strName != lsymbol_undefined && strMemList != NULL)
2600 sort asort = sort_construct (strName, SRT_STRUCT, NOSORTHANDLE, tagName,
2601 TRUE, NOSORTHANDLE, strMemList);
2603 if (tagName != lsymbol_undefined)
2605 tagid = ltoken_create (simpleId, tagName);
2607 ti = (tagInfo) dmalloc (sizeof (*ti));
2609 ti->kind = TAG_STRUCT;
2611 ti->imported = FALSE;
2613 (void) symtable_enterTagForce (g_symtab, ti);
2618 if (strName == lsymbol_undefined)
2620 lclbug (message ("%q: Imported file contains unexpected null struct sort",
2621 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2626 ** no members -> its a forward struct
2629 if (tagName != lsymbol_undefined)
2631 tagid = ltoken_create (simpleId, tagName);
2632 (void) checkAndEnterTag (TAG_FWDSTRUCT, tagid);
2636 strName = lsymbol_undefined;
2638 tagName = lsymbol_undefined;
2640 else if (strcmp (kstr, "str") == 0)
2642 if (strName != lsymbol_undefined || strMemList != NULL)
2644 lclbug (message ("%q: unexpected non-null struct sort or "
2645 "non-empty member list",
2646 fileloc_unparseRaw (cstring_fromChars (importfile),
2647 tsource_thisLineNumber (s))));
2649 /* see if a tag is associated with this sort */
2650 if (strcmp (basedstr, "nil") == 0)
2652 llfatalerror (message ("%s: Struct missing tag. Obsolete .lcs file, remove and rerun lcl.",
2653 cstring_fromChars (importfile)));
2655 strName = sortTag_toSymbol ("Struct", nulltok, &tmp);
2656 tagName = lsymbol_undefined;
2657 mapping_bind (map, sname, strName);
2660 else /* a tag exists */
2661 { /* create tag in symbol table and add tagged sort in sort table */
2663 tagid = ltoken_create (simpleId, bname);
2665 strName = sortTag_toSymbol ("Struct", tagid, &tmp);
2666 ti = symtable_tagInfo (g_symtab, tagName);
2669 ** No error for redefining a tag in an import.
2672 /* to be processed later in sort_import */
2673 lsymbolList_addh (slist, strName);
2675 else if (strcmp (kstr, "enumMem") == 0)
2677 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2678 mem->next = enumMemList;
2679 mem->sortname = enumName;
2681 mem->sort = NOSORTHANDLE;
2684 else if (strcmp (sostr, "enumEnd") == 0)
2686 if (enumName != lsymbol_undefined && enumMemList != NULL)
2688 sort asort = sort_construct (enumName, SRT_ENUM, NOSORTHANDLE, tagName,
2689 FALSE, NOSORTHANDLE, enumMemList);
2691 if (tagName != lsymbol_undefined)
2693 tagid = ltoken_create (simpleId, tagName);
2695 ti = (tagInfo) dmalloc (sizeof (*ti));
2697 ti->kind = TAG_ENUM;
2699 ti->imported = FALSE;
2701 (void) symtable_enterTagForce (g_symtab, ti);
2706 lclbug (message ("%q: unexpected null enum sort or empty member list",
2707 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2709 enumName = lsymbol_undefined;
2711 tagName = lsymbol_undefined;
2713 else if (strcmp (kstr, "enum") == 0)
2715 if (enumName != lsymbol_undefined || enumMemList != NULL)
2717 lclbug (message ("%q: Unexpected non-null enum sort or "
2718 "non-empty member list",
2719 fileloc_unparseRaw (cstring_fromChars (importfile),
2720 tsource_thisLineNumber (s))));
2723 /* see if a tag is associated with this sort */
2724 if (strcmp (basedstr, "nil") == 0)
2726 llfatalerror (message ("%s: Enum missing tag. Obsolete .lcs file, "
2727 "remove and rerun lcl.",
2728 cstring_fromChars (importfile)));
2731 { /* a tag exists */
2733 tagid = ltoken_create (simpleId, bname);
2734 enumName = sortTag_toSymbol ("Enum", tagid, &tmp);
2735 ti = symtable_tagInfo (g_symtab, bname);
2738 else if (strcmp (kstr, "unionMem") == 0)
2740 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2741 mem->next = unionMemList;
2742 mem->sortname = bname;
2744 mem->sort = NOSORTHANDLE;
2747 else if (strcmp (sostr, "unionEnd") == 0)
2749 if (unionName != lsymbol_undefined && unionMemList != NULL)
2751 sort asort = sort_construct (unionName, SRT_UNION, NOSORTHANDLE, tagName,
2752 FALSE, NOSORTHANDLE, unionMemList);
2754 if (tagName != lsymbol_undefined)
2756 tagid = ltoken_create (simpleId, tagName);
2758 ti = (tagInfo) dmalloc (sizeof (*ti));
2760 ti->kind = TAG_UNION;
2762 ti->imported = FALSE;
2764 (void) symtable_enterTagForce (g_symtab, ti);
2769 if (unionName == lsymbol_undefined)
2772 (message ("%q: Imported file contains unexpected null union sort",
2773 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2778 ** no members -> its a forward struct
2781 if (tagName != lsymbol_undefined)
2783 tagid = ltoken_create (simpleId, tagName);
2785 (void) checkAndEnterTag (TAG_FWDUNION, tagid);
2790 unionName = lsymbol_undefined;
2791 unionMemList = NULL;
2792 tagName = lsymbol_undefined;
2794 else if (strcmp (kstr, "union") == 0)
2796 if (unionName != lsymbol_undefined || unionMemList != NULL)
2800 ("%q: Unexpected non-null union sort or non-empty "
2802 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2804 /* see if a tag is associated with this sort */
2805 if (strcmp (basedstr, "nil") == 0)
2808 (message ("%s: Union missing tag. Obsolete .lcs file, "
2809 "remove and rerun lcl.",
2810 cstring_fromChars (importfile)));
2813 { /* a tag exists */
2815 tagid = ltoken_create (simpleId, bname);
2817 unionName = sortTag_toSymbol ("Union", tagid, &tmp);
2818 ti = symtable_tagInfo (g_symtab, bname);
2820 lsymbolList_addh (slist, unionName);
2822 else if (strcmp (kstr, "immutable") == 0)
2824 (void) sort_constructAbstract (sname, FALSE, NOSORTHANDLE);
2826 else if (strcmp (kstr, "hof") == 0)
2828 (void) sort_construct (sname, SRT_HOF, NOSORTHANDLE, lsymbol_undefined,
2829 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2833 sort bsort = sort_lookupName (lsymbol_translateSort (map, bname));
2835 if (sort_isNoSort (bsort))
2837 lineptr = strchr (line, ' '); /* go past "sort" */
2838 llassert (lineptr != NULL);
2839 lineptr = strchr (lineptr + 1, ' '); /* go past sostr */
2840 llassert (lineptr != NULL);
2841 lineptr = strchr (lineptr + 1, ' '); /* go past kstr */
2842 llassert (lineptr != NULL);
2843 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
2846 (message ("%q: Imported file contains unknown base sort: %s",
2847 fileloc_unparseRawCol (cstring_fromChars (importfile),
2848 tsource_thisLineNumber (s), col),
2849 cstring_fromChars (lsymbol_toCharsSafe (bname))));
2852 if (strcmp (kstr, "vec") == 0)
2854 objName = lsymbol_fromChars (objstr);
2855 objSort = sort_lookupName (lsymbol_translateSort (map, objName));
2856 (void) sort_construct (sname, SRT_VECTOR, bsort, lsymbol_undefined,
2857 FALSE, objSort, smemberInfo_undefined);
2861 sort_loadOther (kstr, sname, bsort);
2867 sort_import (tsource *imported, ltoken tok, mapping * map)
2869 /* tok is only used for error message line number */
2870 char *buf, *importfile;
2873 lsymbolList slist = lsymbolList_new ();
2875 buf = tsource_nextLine (imported);
2877 llassert (buf != NULL);
2879 importfile = tsource_fileName (imported);
2881 if (!firstWord (buf, "%LCLSortTable"))
2883 lclsource = LCLScanSource ();
2885 lclfatalerror (tok, message ("Expecting \"%%LCLSortTable\" line "
2886 "in import file %s:\n%s",
2887 cstring_fromChars (importfile),
2888 cstring_fromChars (buf)));
2894 buf = tsource_nextLine (imported);
2896 llassert (buf != NULL);
2898 if (firstWord (buf, "%LCLSortTableEnd"))
2903 { /* a good line, remove %LCL from line first */
2904 if (firstWord (buf, "%LCL"))
2906 parseSortLine (buf + 4, tok, imported, map, slist);
2910 lclsource = LCLScanSource ();
2913 message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
2914 cstring_fromChars (importfile),
2915 cstring_fromChars (buf)));
2920 /* now process the smemberInfo in the sort List */
2921 lsymbolList_elements (slist, s)
2923 if (s != lsymbol_undefined)
2928 sor = sort_lookupName (s);
2929 sn = sort_quietLookup (sor);
2934 { /* update the symbol table with members of enum */
2936 smemberInfo *mlist = sn.members;
2937 for (; mlist != NULL; mlist = mlist->next)
2939 /* check that enumeration constants are unique */
2940 vi = symtable_varInfo (g_symtab, mlist->name);
2941 if (!varInfo_exists (vi))
2942 { /* put info into symbol table */
2943 vi = (varInfo) dmalloc (sizeof (*vi));
2944 vi->id = ltoken_create (NOTTOKEN, mlist->name);
2945 vi->kind = VRK_ENUM;
2949 (void) symtable_enterVar (g_symtab, vi);
2955 (message ("%s: enum member %s of %s has already been declared",
2956 cstring_fromChars (importfile),
2957 lsymbol_toString (mlist->name),
2958 lsymbol_toString (sn.name)));
2961 /*@switchbreak@*/ break;
2966 smemberInfo *mlist = sn.members;
2968 for (; mlist != NULL; mlist = mlist->next)
2970 bsort = sort_lookupName (lsymbol_translateSort (map, mlist->sortname));
2971 if (sort_isNoSort (bsort))
2973 lclbug (message ("%s: member %s of %s has unknown sort\n",
2974 cstring_fromChars (importfile),
2975 cstring_fromChars (lsymbol_toChars (mlist->name)),
2976 cstring_fromChars (lsymbol_toChars (sn.name))));
2980 mlist->sort = bsort;
2983 /*@switchbreak@*/ break;
2986 lclbug (message ("%s: %s has unexpected sort kind %s",
2987 cstring_fromChars (importfile),
2988 cstring_fromChars (lsymbol_toChars (sn.name)),
2989 sort_unparseKind (sn.kind)));
2992 } end_lsymbolList_elements;
2994 /* list and sorts in it are not used anymore */
2995 lsymbolList_free (slist);
2999 sort_equal (sort *s1, sort *s2)
3002 if ((s1 != 0) && (s2 != 0))
3006 /* handle synonym sorts */
3007 syn1 = sort_getUnderlying (*s1);
3008 syn2 = sort_getUnderlying (*s2);
3011 /* makes bool and Bool equal */
3017 sort_compatible (sort s1, sort s2)
3020 /* later: might consider "char" and enum types the same as "int" */
3023 /* handle synonym sorts */
3024 syn1 = sort_getUnderlying (s1);
3025 syn2 = sort_getUnderlying (s2);
3028 /* makes bool and Bool equal */
3033 sort_compatible_modulo_cstring (sort s1, sort s2)
3035 /* like sort_compatible but also handles special cstring inits,
3036 allows the following 2 cases:
3037 char c[] = "abc"; (LHS: char_Obj_Arr, RHS = char_Vec)
3038 (c as implicitly coerced into c^)
3039 char *d = "abc"; (LHS: char_Obj_Ptr, RHS = char_Vec)
3040 (d as implicitly coerced into d[]^)
3043 if (sort_compatible (s1, s2))
3045 syn1 = sort_getUnderlying (s1);
3046 syn2 = sort_getUnderlying (s2);
3047 if (sort_cstring == syn2 &&
3048 (syn1 == char_obj_ptrSort || syn1 == char_obj_ArrSort))
3054 sort_getLsymbol (sort sor)
3056 /* sortNode sn = sort_lookup (sor); */
3057 sortNode sn = sort_quietLookup (sor);
3061 /* a few handy routines for debugging */
3063 char *sort_getName (sort s)
3065 return (lsymbol_toCharsSafe (sort_getLsymbol (s)));
3068 /*@exposed@*/ cstring
3069 sort_unparseName (sort s)
3071 return (cstring_fromChars (sort_getName (s)));
3075 sortError (ltoken t, sort oldsort, sortNode newnode)
3077 sortNode old = sort_quietLookup (oldsort);
3079 if ((old.kind <= SRT_FIRST || old.kind >= SRT_LAST) ||
3080 (newnode.kind <= SRT_FIRST || newnode.kind >= SRT_LAST))
3082 llbuglit ("sortError: illegal sort kind");
3085 llassert (sortTable != NULL);
3087 lclerror (t, message ("Sort %s defined as %s cannot be redefined as %s",
3088 cstring_fromChars (lsymbol_toChars (newnode.name)),
3089 sort_unparseKindName (sortTable[oldsort]),
3090 sort_unparseKindName (newnode)));
3093 static /*@observer@*/ cstring
3094 sort_unparseKindName (sortNode s)
3099 return cstring_fromChars (sortKindName[(int)s.kind]);
3105 return cstring_makeLiteralTemp ("MUTABLE");
3109 return cstring_makeLiteralTemp ("IMMUTABLE");
3113 return cstring_fromChars (sortKindName[(int)s.kind]);
3120 sort_fromLsymbol (lsymbol sortid)
3122 /* like sort_lookupName but creates sort if not already present */
3123 sort sort = sort_lookupName (sortid);
3124 if (sort == NOSORTHANDLE)
3125 sort = sort_makeSort (ltoken_undefined, sortid);
3130 sort_isHOFSortKind (sort s)
3132 sortNode sn = sort_quietLookup (s);
3133 if (sn.kind == SRT_HOF)
3139 ** returns TRUE iff s has State operators (', ~, ^)
3143 sort_hasStateFcns (sort s)
3145 sortNode sn = sort_quietLookup (s);
3146 sortKind kind = sn.kind;
3148 if (kind == SRT_SYN)
3150 return (sort_hasStateFcns (sn.baseSort));
3153 return ((kind == SRT_PTR) ||
3154 (kind == SRT_OBJ) ||
3155 (kind == SRT_ARRAY) ||
3156 (kind == SRT_STRUCT) ||
3157 (kind == SRT_UNION));