]> andersk Git - splint.git/blame - src/sort.c
Initial revision
[splint.git] / src / sort.c
CommitLineData
885824d3 1/*
2** LCLint - annotation-assisted static program checker
3** Copyright (C) 1994-2000 University of Virginia,
4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** sort.c
26**
27** sort abstraction
28**
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.
32**
33** AUTHOR:
34** Yang Meng Tan,
35** Massachusetts Institute of Technology
36*/
37
38# include "lclintMacros.nf"
39# include "llbasic.h"
40# include "llgrammar.h"
41# include "lclscan.h"
42
43/*@+ignorequals@*/
44
45static lsymbol newStructTag (void) /*@*/ ;
46static lsymbol newEnumTag (void) /*@*/ ;
47static lsymbol newUnionTag (void) /*@*/ ;
48
49/*@constant static int MAXBUFFLEN; @*/
50# define MAXBUFFLEN 1024
51
52/*@constant static int DELTA; @*/
53# define DELTA 100
54
55/*@constant static int NOSORTHANDLE; @*/
56# define NOSORTHANDLE 0
57
58/*@constant static int HOFSORTHANDLE; @*/
59# define HOFSORTHANDLE 1
60
61/* local routines */
62
63static void sort_addTupleMembers (sort p_tupleSort, sort p_strSort)
64 /*@modifies internalState@*/ ;
65
66static bool sort_isNewEntry (sortNode p_s) /*@*/ ;
67
68static 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@*/ ;
72
73static sort sort_enterGlobal (sortNode p_s) /*@modifies internalState@*/ ;
74
75static 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@*/ ;
79
80static void genPtrOps (sort p_baseSort, sort p_ptrSort, sort p_arraySort);
81static void genArrOps (sort p_baseSort, sort p_arraySort, int p_dim,
82 sort p_vecSort);
83static void genVecOps (sort p_baseSort, sort p_vecSort, int p_dim);
84static void genTupleOps (sort p_tupleSort);
85static void genUnionOps (sort p_tupleSort);
86static void genStrOps (sort p_strSort, sort p_tupleSort);
87static void genEnumOps (sort p_enumSort);
88
89static void overloadPtrFcns (sort p_ptrSort);
90static void overloadIsSub (sort p_s, int p_dim);
91static void overloadSizeof (sort p_domainSort);
92
93/*@observer@*/ static cstring sort_unparseKind (sortKind p_k) /*@*/ ;
94
95static /*@observer@*/ cstring
96 sort_unparseKindName (sortNode p_s) /*@*/ ;
97
98static lsymbol
99 sortTag_toSymbol (char *p_kind, ltoken p_tagid, /*@out@*/ bool *p_isNew);
100
101static void
102 overloadUnaryTok (/*@only@*/ nameNode p_nn,
103 sort p_domainSort, /*@only@*/ ltoken p_range);
104static void
105 overloadUnary (/*@only@*/ nameNode p_nn,
106 sort p_domainSort, sort p_rangeSort);
107static void
108 overloadBinary (/*@only@*/ nameNode p_nn,
109 sort p_s, /*@only@*/ ltoken p_dTok, sort p_rs);
110static /*@only@*/ nameNode makeFieldOp (lsymbol p_field);
111static /*@only@*/ nameNode makeArrowFieldOp (lsymbol p_field);
112
113# undef sp
114static lsymbol sp (lsymbol p_s1, lsymbol p_s2);
115static void sortError (ltoken p_t, sort p_oldsort, sortNode p_newnode);
116
117/*@-namechecks@*/
118sort sort_bool;
119sort sort_capBool;
120sort sort_int;
121sort sort_char;
122sort sort_float;
123sort sort_double;
124sort sort_cstring;
125/*@=namechecks@*/
126
127static sort sort_void;
128static sort char_obj_ptrSort;
129static sort char_obj_ArrSort;
130
131/* This is used to uniqueize sort names, for anonymous C types */
132static int sortUID = 1;
133
134static /*@only@*/ /*@null@*/ sortNode *sortTable = (sortNode *) 0;
135static int sortTableSize = 0;
136static int sortTableAlloc = 0;
137
138/* Important to keep sorts in some order because importing routines
139for sorts rely on this order to ensure that when we encounter a sort
140S1 that is based on sort S2, S2 is before S1 in the imported file. */
141
142static bool exporting = TRUE;
143
144static lsymbol underscoreSymbol;
145static /*@only@*/ ltoken intToken;
146
147static /*@owned@*/ nameNode arrayRefNameNode;
148static /*@owned@*/ nameNode ptr2arrayNameNode;
149static /*@owned@*/ nameNode deRefNameNode;
150static /*@owned@*/ nameNode nilNameNode;
151static /*@owned@*/ nameNode plusNameNode;
152static /*@owned@*/ nameNode minusNameNode;
153static /*@owned@*/ nameNode condNameNode;
154static /*@owned@*/ nameNode eqNameNode;
155static /*@owned@*/ nameNode neqNameNode;
156
157static sortNode noSort;
158
159static sortNode HOFSort =
160{
161 SRT_HOF,
162 HOFSORTHANDLE,
163 lsymbol_undefined,
164 lsymbol_undefined,
165 FALSE, /* was lsymbolNULL */
166 NOSORTHANDLE,
167 NOSORTHANDLE,
168 smemberInfo_undefined,
169 FALSE,
170 FALSE,
171 FALSE,
172 FALSE
173};
174
175static ob_mstring sortKindName[] =
176{
177 "FIRSTSORT", "NOSORT", "HOFSORT",
178 "PRIMITIVE", "SYNONYM", "POINTER", "OBJ", "ARRAY", "VECTOR",
179 "STRUCT", "TUPLE", "UNION", "UNIONVAL", "ENUM", "LASTSORT"
180} ;
181
182static void smemberInfo_free (/*@null@*/ /*@only@*/ smemberInfo *mem)
183{
184 sfree (mem);
185}
186
187static void sortNode_free (/*@special@*/ sortNode sn)
188 /*@uses sn.members@*/
189 /*@releases sn.members@*/
190{
191 smemberInfo_free (sn.members);
192}
193
194void
195sort_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 @*/
201{
202 if (sortTable != NULL)
203 {
204 int i;
205
206 for (i = 0; i < sortTableSize; i++)
207 {
208 sortNode_free (sortTable[i]);
209 }
210
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);
220
221 sfree (sortTable);
222 /*@-branchstate@*/
223 }
224} /*@=branchstate@*/
225
226sort
227sort_makeNoSort (void)
228{
229 return NOSORTHANDLE;
230}
231
232sort
233sort_makeHOFSort (sort base)
234{
235 sortNode outSort;
236 sort handle;
237
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;
248
249 llassert (sortTable != NULL);
250
251 outSort.handle = handle = sortTableSize;
252 sortTable[handle] = outSort;
253
254 sortTableSize++;
255 return handle;
256}
257
258static sort
259sort_construct (lsymbol name, sortKind kind, sort baseSort,
260 lsymbol tagName,
261 bool mut, sort objSort, /*@null@*/ smemberInfo *members)
262{
263 sortNode outSort;
264 sort handle;
265
266 handle = sort_lookupName (name);
267
268 outSort.kind = kind;
269 outSort.name = 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;
280
281 if (handle == NOSORTHANDLE)
282 {
283 outSort.handle = handle = sort_enterNew (outSort);
284 return handle;
285 }
286 else
287 {
288 llassert (sortTable != NULL);
289
290 if (sortTable[handle].kind != kind)
291 {
292 sortError (ltoken_undefined, handle, outSort);
293 smemberInfo_free (outSort.members);
294
295 return handle;
296 }
297 else
298 {
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.
302 */
303
304 sortTable[handle] = outSort;
305 return handle;
306 }
307 }
308}
309
310static sort
311 sort_constructAbstract (lsymbol name, bool mut, sort baseSort)
312{
313 sortNode outSort;
314 sortKind kind;
315 sort handle;
316
317 if (mut)
318 kind = SRT_OBJ;
319 else
320 kind = SRT_PRIM;
321
322 handle = sort_lookupName (name);
323 outSort.kind = kind;
324 outSort.name = 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;
334
335 if (handle == NOSORTHANDLE)
336 {
337 outSort.handle = handle = sort_enterNew (outSort);
338 /* do not make sort operators. */
339 }
340 else
341 {
342 llassert (sortTable != NULL);
343
344 if (sortTable[handle].kind != kind)
345 {
346 sortError (ltoken_undefined, handle, outSort);
347 }
348
349 smemberInfo_free (outSort.members);
350 }
351
352 return handle;
353}
354
355sort
356sort_makeSort (/*@unused@*/ ltoken t, lsymbol n)
357{
358 /*
359 ** Expects n to be a new sort.
360 ** Generate a sort with the given name. Useful for LSL sorts.
361 */
362
363 sort handle = sort_lookupName (n);
364
365 if (handle == NOSORTHANDLE)
366 {
367 sortNode outSort;
368
369 outSort.handle = handle;
370 outSort.kind = SRT_PRIM;
371 outSort.name = n;
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;
380
381 /* Put into sort table, sort_enter checks for duplicates. */
382 outSort.handle = handle = sort_enterNew (outSort);
383 }
384 else
385 {
386 /* don't override old info */
387 ;
388 }
389
390 return handle;
391}
392
393static sort
394sort_makeSortNoOps (/*@unused@*/ ltoken t, lsymbol n) /*@modifies internalState@*/
395{
396 sort handle;
397
398 handle = sort_lookupName (n);
399
400 if (handle == NOSORTHANDLE)
401 {
402 sortNode outSort;
403
404 outSort.handle = handle;
405 outSort.kind = SRT_PRIM;
406 outSort.name = n;
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 */
418
419 return handle;
420}
421
422static sort
423sort_makeLiteralSort (ltoken t, lsymbol n)
424 /*@modifies internalState@*/
425{
426 /*
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.
430 */
431
432 sort handle = sort_makeSort (t, n);
433
434 overloadSizeof (handle);
435 return handle;
436}
437
438sort
439sort_makeSyn (ltoken t, sort s, lsymbol n)
440{
441 /* make a synonym sort with name n that is == to sort s */
442 /* expect n to be a new sort name */
443 sortNode outSort;
444 sort handle;
445 /* must not clash with any LSL sorts */
446 lsymbol newname = sp (underscoreSymbol, n);
447
448 if (n == lsymbol_undefined)
449 {
450 llbuglit ("sort_makeSyn: synonym must have name");
451 }
452
453 handle = sort_lookupName (newname);
454
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;
467
468 if (handle == NOSORTHANDLE)
469 {
470 outSort.handle = handle = sort_enterNew (outSort);
471 /* No operators to generate for synonyms */
472 }
473 else
474 {
475 llassert (sortTable != NULL);
476
477 if (sortTable[handle].kind != SRT_SYN)
478 {
479 sortError (t, handle, outSort);
480 }
481
482 smemberInfo_free (outSort.members);
483 }
484
485 return handle;
486}
487
488sort
489sort_makeFormal (sort insort)
490{
491 sortNode s;
492 sort sor, handle;
493
494 sor = sort_getUnderlying (insort);
495 handle = sor;
496 s = sort_lookup (sor);
497
498 switch (s.kind)
499 {
500 case SRT_STRUCT:
501 handle = sort_makeTuple (ltoken_undefined, sor);
502 break;
503 case SRT_UNION:
504 handle = sort_makeUnionVal (ltoken_undefined, sor);
505 break;
506 default:
507 break;
508 }
509
510 return handle;
511}
512
513sort
514sort_makeGlobal (sort insort)
515{
516 /* Make a Obj if not an array or a struct */
517 sortNode s;
518 sort sor, handle;
519 sor = sort_getUnderlying (insort);
520 handle = sor;
521 s = sort_lookup (sor);
522
523 switch (s.kind)
524 {
525 case SRT_ARRAY:
526 case SRT_STRUCT:
527 case SRT_UNION:
528 case SRT_HOF:
529 case SRT_NONE:
530 break;
531 case SRT_VECTOR:
532 case SRT_TUPLE:
533 case SRT_UNIONVAL:
534 llcontbuglit ("sort_makeGlobal: can't make vectors, tuples, or unionvals global");
535 break;
536 default:
537 handle = sort_makeObj (sor);
538 break;
539 }
540 return handle;
541}
542
543sort
544sort_makeObj (sort sor)
545{
546 sortNode baseSortNode, outSort;
547 sort baseSort, handle;
548 lsymbol name;
549
550 /* skip the synonym sort */
551 baseSort = sort_getUnderlying (sor);
552 baseSortNode = sort_quietLookup (baseSort);
553 switch (baseSortNode.kind)
554 {
555 case SRT_HOF:
556 case SRT_NONE:
557 return baseSort;
558 case SRT_VECTOR:
559 if (baseSortNode.objSort != 0)
560 return baseSortNode.objSort;
561 else /* must have well-defined objSort field */
562 {
563 llcontbuglit ("sort_makeObj: Inconsistent vector reps:invalid objSort field");
564 return baseSort;
565 }
566 case SRT_TUPLE:
567 case SRT_UNIONVAL:
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 */
575 {
576 llcontbuglit ("sort_makeObj: Inconsistent tuples or unionvals reps: invalid baseSort field");
577 return baseSort;
578 }
579 default:
580 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
581 lsymbol_fromChars ("_Obj"));
582 handle = sort_lookupName (name);
583
584 outSort.kind = SRT_OBJ;
585 /* must not clash with any LSL sorts */
586 outSort.name = name;
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;
596
597 if (handle == NOSORTHANDLE)
598 {
599 if (sort_isNewEntry (outSort))
600 {
601 outSort.handle = handle = sort_enterNew (outSort);
602 }
603 else
604 {
605 outSort.handle = handle = sort_enterNew (outSort);
606 }
607 }
608 else
609 {
610 llassert (sortTable != NULL);
611
612 if (sortTable[handle].kind != SRT_OBJ)
613 {
614 sortError (ltoken_undefined, handle, outSort);
615 }
616
617 smemberInfo_free (outSort.members);
618 }
619
620 return handle;
621 }
622}
623
624sort
625sort_makePtr (ltoken t, sort baseSort)
626{
627 sortNode s, outSort;
628 sort handle, arrayHandle;
629 lsymbol name;
630
631 s = sort_lookup (baseSort);
632
633 if (s.kind == SRT_HOF)
634 {
635 return baseSort;
636 }
637 if (s.kind == SRT_NONE)
638 {
639 return baseSort;
640 }
641
642 if (s.kind != SRT_ARRAY && s.kind != SRT_STRUCT &&
643 s.kind != SRT_UNION)
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);
647
648 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
649 lsymbol_fromChars ("_Ptr"));
650 handle = sort_lookupName (name);
651
652 outSort.kind = SRT_PTR;
653 outSort.name = name;
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;
663
664 if (handle == NOSORTHANDLE)
665 {
666 if (sort_isNewEntry (outSort))
667 {
668 outSort.handle = handle = sort_enterNew (outSort);
669 arrayHandle = sort_makeArr (t, baseSort);
670 genPtrOps (baseSort, handle, arrayHandle);
671 }
672 else
673 {
674 outSort.handle = handle = sort_enterNew (outSort);
675 }
676 }
677 else
678 {
679 llassert (sortTable != NULL);
680
681 if (sortTable[handle].kind != SRT_PTR)
682 {
683 sortError (t, handle, outSort);
684 }
685 smemberInfo_free (outSort.members);
686 }
687 return handle;
688}
689
690sort
691sort_makePtrN (sort s, int pointers)
692{
693 llassert (pointers >= 0);
694
695 if (pointers == 0)
696 {
697 return s;
698 }
699 else
700 {
701 return sort_makePtrN (sort_makePtr (ltoken_undefined, s),
702 pointers - 1);
703 }
704}
705
706sort
707sort_makeArr (ltoken t, sort baseSort)
708{
709 sortNode s, outSort, old;
710 sort handle, vecHandle;
711 int dim;
712 lsymbol name;
713
714 s = sort_lookup (baseSort);
715
716 if (s.kind == SRT_HOF)
717 return baseSort;
718 if (s.kind == SRT_NONE)
719 return baseSort;
720
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);
725
726 name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
727 lsymbol_fromChars ("_Arr"));
728 handle = sort_lookupName (name);
729
730 /* must not clash with any LSL sorts */
731 outSort.name = name;
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;
741
742 if (handle == NOSORTHANDLE)
743 {
744 if (sort_isNewEntry (outSort))
745 {
746 outSort.handle = handle = sort_enterNew (outSort);
747
748 for (old = outSort, dim = 0;
749 old.kind == SRT_ARRAY;
750 dim++, old = sort_lookup (old.baseSort))
751 {
752 ;
753 }
754
755 vecHandle = sort_makeVec (t, handle);
756 genArrOps (baseSort, handle, dim, vecHandle);
757 }
758 else
759 {
760 outSort.handle = handle = sort_enterNew (outSort);
761 }
762 }
763 else
764 {
765 llassert (sortTable != NULL);
766
767 if (sortTable[handle].kind != SRT_ARRAY)
768 {
769 sortError (t, handle, outSort);
770 }
771
772 smemberInfo_free (outSort.members);
773 }
774
775 return handle;
776}
777
778sort
779sort_makeVec (ltoken t, sort arraySort)
780{
781 sortNode s, outSort, old;
782 sort baseSort, handle, elementSort;
783 int dim; /* array dimension count. */
784 lsymbol name;
785
786 s = sort_lookup (arraySort);
787
788 if (s.kind == SRT_HOF)
789 return arraySort;
790 if (s.kind == SRT_NONE)
791 return arraySort;
792
793 if (s.kind != SRT_ARRAY)
794 {
795 llbug (message ("sort_makeVec: only arrays can become vectors: given sort is %s",
796 sort_unparseKind (s.kind)));
797 }
798
799 if (s.baseSort == NOSORTHANDLE)
800 llbuglit ("sort_makeVec: arrays must have base (element) sort");
801
802 /* Vectors return "values", so make array elements values. */
803
804 baseSort = s.baseSort;
805 elementSort = sort_makeVal (baseSort);
806
807 name = sp (sp (underscoreSymbol, sort_getLsymbol (elementSort)),
808 lsymbol_fromChars ("_Vec"));
809 handle = sort_lookupName (name);
810
811 outSort.baseSort = elementSort;
812 outSort.name = name;
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;
821
822 if (handle == NOSORTHANDLE)
823 {
824 if (sort_isNewEntry (outSort))
825 {
826 outSort.handle = handle = sort_enterNew (outSort);
827
828 for (old = outSort, dim = 0;
829 old.kind == SRT_VECTOR;
830 dim++, old = sort_lookup (old.baseSort))
831 {
832 ;
833 }
834
835 genVecOps (elementSort, handle, dim);
836 }
837 else
838 {
839 outSort.handle = handle = sort_enterNew (outSort);
840 }
841 }
842 else
843 {
844 llassert (sortTable != NULL);
845
846 if (sortTable[handle].kind != SRT_VECTOR)
847 {
848 sortError (t, handle, outSort);
849 }
850
851 smemberInfo_free (outSort.members);
852 }
853
854 return handle;
855}
856
857sort
858sort_makeVal (sort sor)
859{
860 sort retSort = sor;
861 sortNode rsn, s;
862
863 llassert (sortTable != NULL);
864 s = sort_quietLookup (sor);
865
866 switch (s.kind)
867 {
868 case SRT_PRIM:
869 case SRT_ENUM:
870 case SRT_PTR:
871 case SRT_TUPLE:
872 case SRT_UNIONVAL:
873 case SRT_VECTOR:
874 case SRT_HOF:
875 case SRT_NONE:
876 /* Do nothing for basic types and pointers. */
877 retSort = sor;
878 break;
879 case SRT_SYN:
880 return sort_makeVal (sortTable[sor].baseSort);
881 case SRT_OBJ:
882 /* Strip out the last Obj's */
883 if (s.baseSort == NOSORTHANDLE)
884 {
885 llbuglit ("sort_makeVal: expecting a base sort for Obj");
886 }
887 retSort = s.baseSort;
888 break;
889 case SRT_ARRAY:
890 retSort = sort_makeVec (ltoken_undefined, sor);
891 break;
892 case SRT_STRUCT:
893 retSort = sort_makeTuple (ltoken_undefined, sor);
894 break;
895 case SRT_UNION:
896 retSort = sort_makeUnionVal (ltoken_undefined, sor);
897 break;
898 default:
899 llbuglit ("sort_makeVal: invalid sort kind");
900 }
901 rsn = sort_quietLookup (retSort);
902 if (rsn.kind == SRT_NONE)
903 {
904 llfatalbug (message ("sort_makeVal: invalid return sort kind: %d", (int)rsn.kind));
905 }
906 return retSort;
907}
908
909sort
910sort_makeImmutable (ltoken t, lsymbol name)
911{
912 sortNode outSort;
913 sort handle;
914
915 handle = sort_lookupName (name);
916
917 outSort.kind = SRT_PRIM;
918 outSort.name = name;
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;
927
928 if (handle == NOSORTHANDLE)
929 {
930 outSort.handle = handle = sort_enterNew (outSort);
931 overloadSizeof (handle);
932 }
933 else
934 { /* complain */
935 llassert (sortTable != NULL);
936
937 if ((sortTable[handle].kind != SRT_PRIM) &&
938 (sortTable[handle].abstract) &&
939 (!sortTable[handle].mutable))
940 {
941 sortError (t, handle, outSort);
942 }
943
944 smemberInfo_free (outSort.members);
945 }
946
947 return handle;
948}
949
950sort
951sort_makeMutable (ltoken t, lsymbol name)
952{
953 sort immutable_old, handle, baseSort;
954 lsymbol objName;
955
956 immutable_old = sort_lookupName (name);
957
958 /* First generate the value sort */
959 baseSort = sort_makeImmutable (t, name);
960
961 llassert (sortTable != NULL);
962
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))
968 {
969 /* already complained */
970 handle = NOSORTHANDLE;
971 }
972 else
973 { /* sort_makeImmutable must have succeeded */
974 sortNode outSort;
975
976 /* must not clash with any LSL sorts */
977 objName = sp (sp (underscoreSymbol, name),
978 lsymbol_fromChars ("_Obj"));
979 handle = sort_lookupName (objName);
980
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;
992
993 if (handle == NOSORTHANDLE)
994 {
995 if (sort_isNewEntry (outSort))
996 {
997 outSort.handle = handle = sort_enterNew (outSort);
998 }
999 else
1000 {
1001 handle = sort_enterNew (outSort);
1002 }
1003 }
1004 else
1005 {
1006 llassert (sortTable != NULL);
1007
1008 if ((sortTable[handle].kind != SRT_OBJ)
1009 && sortTable[handle].abstract
1010 && sortTable[handle].mutable)
1011 {
1012 sortError (t, handle, outSort);
1013 }
1014
1015 smemberInfo_free (outSort.members);
1016 }
1017 }
1018 return handle;
1019}
1020
1021sort
1022sort_makeStr (ltoken opttagid)
1023{
1024 sortNode outSort;
1025 sort handle;
1026 bool isNewTag;
1027 lsymbol name;
1028
1029 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1030 /* isNewTag true means that the name generated is new */
1031
1032 if (ltoken_isUndefined (opttagid))
1033 {
1034 opttagid = ltoken_create (simpleId, newStructTag ());
1035
1036 outSort.realtag = FALSE;
1037 }
1038 else
1039 {
1040 outSort.realtag = TRUE;
1041 }
1042
1043 name = sortTag_toSymbol ("Struct", opttagid, &isNewTag);
1044
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;
1058
1059 if (handle == NOSORTHANDLE)
1060 {
1061 if (sort_isNewEntry (outSort))
1062 {
1063 outSort.handle = handle = sort_enterNew (outSort);
1064 }
1065 else
1066 {
1067 outSort.handle = handle = sort_enterNewForce (outSort);
1068 }
1069 }
1070 else
1071 {
1072 if (sortTable[handle].kind != SRT_STRUCT)
1073 {
1074 sortError (opttagid, handle, outSort);
1075 }
1076
1077 smemberInfo_free (outSort.members);
1078 }
1079
1080 return handle;
1081}
1082
1083bool
1084sort_updateStr (sort strSort, /*@only@*/ smemberInfo *info)
1085{
1086 /* expect strSort to be in sort table but not yet filled in */
1087 /* return TRUE if it is "new" */
1088 sort tupleSort;
1089 sortNode sn;
1090
1091 llassert (sortTable != NULL);
1092 sn = sort_lookup (strSort);
1093
1094 if (sn.members == (smemberInfo *) 0)
1095 {
1096 sortTable[strSort].members = info;
1097 tupleSort = sort_makeTuple (ltoken_undefined, strSort);
1098 genStrOps (strSort, tupleSort);
1099 return TRUE;
1100 }
1101 else
1102 {
1103 smemberInfo_free (info);
1104 return FALSE;
1105 }
1106}
1107
1108sort
1109sort_makeTuple (ltoken t, sort strSort)
1110{
1111 sort handle;
1112 sortNode outSort, s = sort_lookup (strSort);
1113 lsymbol name;
1114
1115 if (s.kind != SRT_STRUCT)
1116 {
1117 llfatalbug (message ("sort_makeTuple: Only structs can become tuples: given sort is %s",
1118 sort_unparseKind (s.kind)));
1119 }
1120
1121 name = sp (s.name, lsymbol_fromChars ("_Tuple"));
1122 llassert (sortTable != NULL);
1123 handle = sort_lookupName (name);
1124
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;
1137
1138 if (handle == NOSORTHANDLE)
1139 {
1140 if (sort_isNewEntry (outSort))
1141 {
1142 outSort.handle = handle = sort_enterNew (outSort);
1143
1144 sort_addTupleMembers (handle, strSort);
1145 genTupleOps (handle);
1146 }
1147 else
1148 {
1149 outSort.handle = handle = sort_enterNew (outSort);
1150 }
1151 }
1152 else
1153 {
1154 if (sortTable[handle].kind != SRT_TUPLE)
1155 {
1156 sortError (t, handle, outSort);
1157 }
1158
1159 smemberInfo_free (outSort.members);
1160 }
1161
1162 return handle;
1163}
1164
1165static void
1166sort_addTupleMembers (sort tupleSort, sort strSort)
1167{
1168 smemberInfo *mem, *tail = smemberInfo_undefined;
1169 smemberInfo *top = smemberInfo_undefined;
1170 smemberInfo *newinfo;
1171
1172 /* make sure it works for empty smemberInfo */
1173
1174 llassert (sortTable != NULL);
1175
1176 for (mem = sortTable[strSort].members;
1177 mem != smemberInfo_undefined; mem = mem->next)
1178 {
1179 newinfo = (smemberInfo *) dmalloc (sizeof (*newinfo));
1180 newinfo->name = mem->name;
1181 newinfo->sort = sort_makeVal (mem->sort);
1182 newinfo->next = smemberInfo_undefined;
1183
1184 if (top == smemberInfo_undefined)
1185 { /* start of iteration */
1186 top = newinfo;
1187 tail = newinfo;
1188 }
1189 else
1190 {
1191 llassert (tail != smemberInfo_undefined);
1192
1193 tail->next = newinfo;
1194 tail = newinfo;
1195 /*@-branchstate@*/ /* tail is dependent */
1196 }
1197 /*@=branchstate@*/
1198 }
1199
1200 sortTable[tupleSort].members = top;
1201}
1202
1203static
1204void genTupleOps (sort tupleSort)
1205{
1206 ltoken range, dom;
1207 sort fieldsort;
1208 smemberInfo *m;
1209 unsigned int memCount;
1210 ltokenList domain = ltokenList_new ();
1211 sigNode signature;
1212 opFormUnion u;
1213 opFormNode opform;
1214 nameNode nn;
1215
1216 memCount = 0;
1217 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (tupleSort));
1218
1219 llassert (sortTable != NULL);
1220 for (m = sortTable[tupleSort].members;
1221 m != smemberInfo_undefined; m = m->next)
1222 {
1223 fieldsort = sort_makeVal (m->sort);
1224 overloadUnary (makeFieldOp (m->name), tupleSort, fieldsort);
1225
1226 dom = ltoken_createType (simpleId, SID_SORT,
1227 sort_getLsymbol (fieldsort));
1228 ltokenList_addh (domain, dom);
1229 memCount++;
1230 }
1231
1232 /* For tuples only: [__, ...]: memSorts, ... -> tupleSort */
1233 signature = makesigNode (ltoken_undefined, domain, range);
1234 u.middle = memCount;
1235
1236 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked),
1237 OPF_BMIDDLE, u, ltoken_copy (ltoken_rbracket));
1238
1239 nn = makeNameNodeForm (opform);
1240 symtable_enterOp (g_symtab, nn, signature);
1241
1242 /*
1243 ** should not be able to take sizeof (struct^) ...
1244 */
1245}
1246
1247static
1248void genUnionOps (sort tupleSort)
1249{
1250 /* like genTupleOps but no constructor [ ...]: -> unionSort */
1251 smemberInfo *m;
1252 sort sort;
1253
1254 llassert (sortTable != NULL);
1255 for (m = sortTable[tupleSort].members;
1256 m != smemberInfo_undefined; m = m->next)
1257 {
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)); */
1267 }
1268}
1269
1270static
1271void genStrOps (sort strSort, /*@unused@*/ sort tupleSort)
1272{
1273 smemberInfo *m;
1274 sort sort;
1275
1276 llassert (sortTable != NULL);
1277 for (m = sortTable[strSort].members;
1278 m != smemberInfo_undefined; m = m->next)
1279 {
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)); */
1289 }
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); */
1294}
1295
1296sort
1297sort_makeUnion (ltoken opttagid)
1298{
1299 sortNode outSort;
1300 sort handle;
1301 bool isNewTag;
1302 lsymbol name;
1303
1304 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1305 /* isNewTag true means that the name generated is new */
1306
1307 if (ltoken_isUndefined (opttagid))
1308 {
1309 opttagid = ltoken_create (simpleId, newUnionTag ());
1310 outSort.realtag = FALSE;
1311 }
1312 else
1313 outSort.realtag = TRUE;
1314
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;
1329
1330 if (handle == NOSORTHANDLE)
1331 {
1332 if (sort_isNewEntry (outSort))
1333 {
1334 outSort.handle = handle = sort_enterNew (outSort);
1335 }
1336 else
1337 {
1338 outSort.handle = handle = sort_enterNewForce (outSort);
1339 }
1340 }
1341 else
1342 {
1343 if (sortTable[handle].kind != SRT_UNION)
1344 {
1345 sortError (opttagid, handle, outSort);
1346 }
1347
1348 smemberInfo_free (outSort.members);
1349 }
1350
1351 return handle;
1352}
1353
1354bool
1355sort_updateUnion (sort unionSort, /*@only@*/ smemberInfo *info)
1356{
1357 /* expect unionSort to be in sort table but not yet filled in */
1358 /* return TRUE if it is "new" */
1359 sort uValSort;
1360 sortNode sn;
1361
1362 llassert (sortTable != NULL);
1363
1364 sn = sort_lookup (unionSort);
1365
1366 if (sn.members == (smemberInfo *) 0)
1367 {
1368 sortTable[unionSort].members = info;
1369 uValSort = sort_makeUnionVal (ltoken_undefined, unionSort);
1370 /* same as struct operations */
1371 genStrOps (unionSort, uValSort);
1372 return TRUE;
1373 }
1374 else
1375 {
1376 smemberInfo_free (info);
1377 return FALSE;
1378 }
1379}
1380
1381sort
1382sort_makeUnionVal (ltoken t, sort unionSort)
1383{
1384 sort handle;
1385 sortNode outSort, s = sort_lookup (unionSort);
1386 lsymbol name;
1387
1388 if (s.kind != SRT_UNION)
1389 {
1390 llfatalbug (message ("sort_makeUnion: only unions can become unionVals: given sort is: %s",
1391 sort_unparseKind (s.kind)));
1392 }
1393
1394 llassert (sortTable != NULL);
1395
1396 name = sp (s.name, lsymbol_fromChars ("_UnionVal"));
1397 handle = sort_lookupName (name);
1398
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;
1411
1412 if (handle == NOSORTHANDLE)
1413 {
1414 if (sort_isNewEntry (outSort))
1415 {
1416 outSort.handle = handle = sort_enterNew (outSort);
1417
1418 /* Add members to the unionVal's. */
1419 /* same as structs and tuples */
1420
1421 sort_addTupleMembers (handle, unionSort);
1422 genUnionOps (handle);
1423 }
1424 else
1425 {
1426 outSort.handle = handle = sort_enterNew (outSort);
1427 }
1428 }
1429 else
1430 {
1431 if (sortTable[handle].kind != SRT_UNIONVAL)
1432 {
1433 sortError (t, handle, outSort);
1434 }
1435
1436 smemberInfo_free (outSort.members);
1437 }
1438
1439 return handle;
1440}
1441
1442static lsymbol
1443newEnumTag ()
1444{
1445 static int ecount = 0;
1446
1447 return (cstring_toSymbol (message ("e%s%de", context_moduleName (), ecount++)));
1448}
1449
1450static lsymbol
1451newStructTag ()
1452{
1453 static int ecount = 0;
1454
1455 return (cstring_toSymbol (message ("s%s%ds", context_moduleName (), ecount++)));
1456}
1457
1458static lsymbol
1459newUnionTag ()
1460{
1461 static int ecount = 0;
1462
1463 return (cstring_toSymbol (message ("u%s%du", context_moduleName (), ecount++)));
1464}
1465
1466sort
1467sort_makeEnum (ltoken opttagid)
1468{
1469 sortNode outSort;
1470 sort handle;
1471 bool isNew;
1472 lsymbol name;
1473
1474 llassert (sortTable != NULL);
1475
1476 if (ltoken_isUndefined (opttagid))
1477 {
1478 opttagid = ltoken_create (simpleId, newEnumTag ());
1479 outSort.realtag = FALSE;
1480 }
1481 else
1482 outSort.realtag = TRUE;
1483
1484 /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
1485
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;
1499
1500 if (handle == NOSORTHANDLE)
1501 {
1502 if (sort_isNewEntry (outSort))
1503 {
1504 outSort.handle = handle = sort_enterNew (outSort);
1505 }
1506 else
1507 {
1508 outSort.handle = handle = sort_enterNewForce (outSort);
1509 }
1510 }
1511 else
1512 {
1513 if (sortTable[handle].kind != SRT_ENUM)
1514 {
1515 sortError (opttagid, handle, outSort);
1516 }
1517
1518 smemberInfo_free (outSort.members);
1519 }
1520
1521 return handle;
1522}
1523
1524bool
1525sort_updateEnum (sort enumSort, /*@only@*/ smemberInfo *info)
1526{
1527 /*
1528 ** Expect enumSort to be in sort table but not yet filled in.
1529 ** Return TRUE if it is "new"
1530 */
1531
1532 sortNode sn;
1533
1534 llassert (sortTable != NULL);
1535
1536 sn = sort_lookup (enumSort);
1537 if (sn.members == (smemberInfo *) 0)
1538 {
1539 sortTable[enumSort].members = info;
1540 genEnumOps (enumSort);
1541 return TRUE;
1542 }
1543 else
1544 {
1545 smemberInfo_free (info);
1546 return FALSE;
1547 }
1548}
1549
1550static
1551void genEnumOps (sort enumSort)
1552{
1553 smemberInfo *ei;
1554 ltokenList domain = ltokenList_new ();
1555 ltoken range, mem;
1556 nameNode nn;
1557 sigNode signature;
1558
1559 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (enumSort));
1560 signature = makesigNode (ltoken_undefined, domain, range);
1561
1562 llassert (sortTable != NULL);
1563
1564 for (ei = sortTable[enumSort].members;
1565 ei != (smemberInfo *) 0; ei = ei->next)
1566 {
1567 mem = ltoken_createType (simpleId, SID_OP, ei->name);
1568 nn = makeNameNodeId (mem);
1569 symtable_enterOp (g_symtab, nn, sigNode_copy (signature));
1570 }
1571
1572 sigNode_free (signature);
1573 overloadSizeof (enumSort);
1574}
1575
1576static void
1577genPtrOps (/*@unused@*/ sort baseSort, sort ptrSort, sort arraySort)
1578{
1579 /* Generate *__: xPtr -> x */
1580
1581 /* overloadUnary (deRefNameNode, ptrSort, baseSort); */
1582
1583 /* Generate maxIndex, minIndex: xPtr -> int */
1584 /* overloadUnaryTok (maxIndexNameNode, ptrSort, intToken); */
1585 /* overloadUnaryTok (minIndexNameNode, ptrSort, intToken); */
1586
1587 /* Generate __[]: pointer -> array */
1588 overloadUnary (nameNode_copySafe (ptr2arrayNameNode), ptrSort, arraySort);
1589
1590 /* Generate __+__, __-__: pointer, int -> pointer */
1591 overloadBinary (nameNode_copySafe (plusNameNode), ptrSort,
1592 ltoken_copy (intToken), ptrSort);
1593
1594 overloadBinary (nameNode_copySafe (minusNameNode), ptrSort,
1595 ltoken_copy (intToken), ptrSort);
1596
1597 /* Generate NIL: -> xPtr */
1598 /* Generate __+__: int, pointer -> pointer */
1599 /* Generate __-__: pointer, pointer -> int */
1600 overloadPtrFcns (ptrSort);
1601}
1602
1603static void
1604genArrOps (sort baseSort, sort arraySort, int dim, /*@unused@*/ sort vecSort)
1605{
1606 /* Generate __[__]: nArr, int -> n */
1607 overloadBinary (nameNode_copySafe (arrayRefNameNode), arraySort,
1608 ltoken_copy (intToken), baseSort);
1609
1610 /* Generate maxIndex, minIndex: sort -> int */
1611 /* overloadUnaryTok (maxIndexNameNode, arraySort, intToken); */
1612 /* overloadUnaryTok (minIndexNameNode, arraySort, intToken); */
1613
1614 /* Generate isSub: arraySort, int, ... -> bool */
1615 overloadIsSub (arraySort, dim);
1616
1617 /* Generate fresh, trashed, modifies, unchanged: array -> bool */
1618 /* Generate any, pre, post: array -> vector */
1619
1620 /* overloadStateFcns (arraySort, vecSort); */
1621 /* overloadObjFcns (arraySort); */
1622}
1623
1624/*
1625** overloadPtrFcns:
1626** generate NIL: -> ptrSort
1627** __+__: int, ptrSort -> ptrSort
1628** __-__: ptrSort, ptrSort -> int
1629*/
1630static void
1631overloadPtrFcns (sort ptrSort)
1632{
1633 ltokenList domain = ltokenList_new ();
1634 ltoken range;
1635 sigNode signature;
1636
1637 /* NIL: -> ptrSort */
1638
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);
1642
1643 /* __+__: int, ptrSort -> ptrSort */
1644
1645 ltokenList_addh (domain, ltoken_copy (intToken));
1646 ltokenList_addh (domain, ltoken_copy (range));
1647
1648 signature = makesigNode (ltoken_undefined, domain, ltoken_copy (range));
1649 symtable_enterOp (g_symtab, nameNode_copySafe (plusNameNode), signature);
1650
1651 /* __-__: ptrSort, ptrSort -> int */
1652
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);
1659}
1660
1661static void
1662genVecOps (sort baseSort, sort vecSort, int dim)
1663{
1664 /* Generate __[__]: vecSort, int -> baseSort */
1665
1666 overloadBinary (nameNode_copySafe (arrayRefNameNode), vecSort,
1667 ltoken_copy (intToken), baseSort);
1668
1669 /* sizeof: vecSort -> int */
1670 /* Generate isSub: vecSort, int, ... -> bool */
1671
1672 overloadIsSub (vecSort, dim);
1673}
1674
1675static void
1676overloadIsSub (sort s, int dim)
1677{
1678 /* Generate isSub: s, int, ... -> bool */
1679 int j, i;
1680 ltoken dom, nulltok = ltoken_undefined;
1681 ltokenList domain;
1682 sigNode signature;
1683
1684 for (j = 1; j <= dim; j++)
1685 {
1686 nameNode isSubNameNode = (nameNode) dmalloc (sizeof (*isSubNameNode));
1687
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));
1692
1693 domain = ltokenList_singleton (dom);
1694
1695 for (i = 1; i <= j; i++)
1696 {
1697 ltokenList_addh (domain, ltoken_copy (intToken));
1698 }
1699
1700 signature = makesigNode (nulltok, domain, ltoken_copy (ltoken_bool));
1701 symtable_enterOp (g_symtab, isSubNameNode, signature);
1702 }
1703}
1704
1705static void
1706overloadUnaryTok (/*@only@*/ nameNode nn, sort domainSort, /*@only@*/ ltoken range)
1707{
1708 /* Generate <nn>: domainSort -> rangeTok */
1709 sigNode signature;
1710 ltoken dom;
1711 ltokenList domain;
1712
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);
1717}
1718
1719static void
1720overloadSizeof (sort domainSort)
1721{
1722 nameNode sizeofNameNode = (nameNode) dmalloc (sizeof (*sizeofNameNode));
1723
1724 sizeofNameNode->isOpId = TRUE;
1725 sizeofNameNode->content.opid = ltoken_createType (simpleId, SID_OP,
1726 lsymbol_fromChars ("sizeof"));
1727
1728 overloadUnaryTok (sizeofNameNode, domainSort, ltoken_copy (intToken));
1729}
1730
1731static void
1732overloadUnary (/*@only@*/ nameNode nn, sort domainSort, sort rangeSort)
1733{
1734 ltoken range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rangeSort));
1735
1736 overloadUnaryTok (nn, domainSort, range);
1737}
1738
1739static void
1740overloadBinary (/*@only@*/ nameNode nn, sort s, /*@only@*/ ltoken dTok, sort rs)
1741{
1742 /* Generate <nn>: s, dTok -> rs */
1743 sigNode signature;
1744 ltoken range, dom;
1745 ltokenList domain = ltokenList_new ();
1746
1747 range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rs));
1748 dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (s));
1749
1750 ltokenList_addh (domain, dom);
1751 ltokenList_addh (domain, dTok);
1752
1753 signature = makesigNode (ltoken_undefined, domain, range);
1754 symtable_enterOp (g_symtab, nn, signature);
1755}
1756
1757static /*@only@*/ nameNode
1758makeFieldOp (lsymbol field)
1759{
1760 /* operator: __.<field> */
1761 nameNode nn;
1762 opFormUnion u;
1763 opFormNode opform;
1764
1765 u.id = ltoken_createType (simpleId, SID_OP, field);
1766 opform = makeOpFormNode (ltoken_undefined, OPF_MSELECT, u, ltoken_undefined);
1767 nn = makeNameNodeForm (opform);
1768 return nn;
1769}
1770
1771static /*@only@*/ nameNode
1772makeArrowFieldOp (lsymbol field)
1773{
1774 /* operator: __-><field> */
1775 nameNode nn;
1776 opFormUnion u;
1777 opFormNode opform;
1778
1779 u.id = ltoken_createType (simpleId, SID_OP, field);
1780 opform = makeOpFormNode (ltoken_undefined, OPF_MMAP, u, ltoken_undefined);
1781 nn = makeNameNodeForm (opform);
1782 return nn;
1783}
1784
1785void
1786sort_init (void)
1787 /*@globals undef noSort,
1788 undef arrayRefNameNode,
1789 undef ptr2arrayNameNode,
1790 undef deRefNameNode,
1791 undef nilNameNode,
1792 undef plusNameNode,
1793 undef minusNameNode,
1794 undef condNameNode,
1795 undef eqNameNode,
1796 undef neqNameNode,
1797 undef intToken; @*/
1798{
1799 /* on alpha, declaration does not allocate storage */
1800 opFormNode opform;
1801 opFormUnion u;
1802 underscoreSymbol = lsymbol_fromChars ("_");
1803
1804 /*
1805 ** commonly used data for generating operators
1806 */
1807
1808 lsymbol_setbool (lsymbol_fromChars ("bool"));
1809 intToken = ltoken_createType (simpleId, SID_SORT, lsymbol_fromChars ("int"));
1810
1811 /*
1812 ** __ \eq __: sort, sort -> bool
1813 */
1814
1815 u.anyop = ltoken_copy (ltoken_eq);
1816 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1817 eqNameNode = makeNameNodeForm (opform);
1818
1819 /*
1820 ** __ \neq __: sort, sort -> bool
1821 */
1822
1823 u.anyop = ltoken_copy (ltoken_neq);
1824 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1825 neqNameNode = makeNameNodeForm (opform);
1826
1827 /*
1828 **if __ then __ else __: bool, sort, sort -> sort
1829 */
1830
1831 opform = makeOpFormNode (ltoken_undefined, OPF_IF,
1832 opFormUnion_createMiddle (0), ltoken_undefined);
1833 condNameNode = makeNameNodeForm (opform);
1834
1835 /* operator: __[__]: arraySort, int -> elementSort_Obj */
1836 u.middle = 1;
1837 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked), OPF_BMMIDDLE, u,
1838 ltoken_copy (ltoken_rbracket));
1839 arrayRefNameNode = makeNameNodeForm (opform);
1840
1841 /* operator: __[]: ptrSort -> arraySort */
1842 u.middle = 0;
1843 opform = makeOpFormNode (ltoken_copy (ltoken_lbracked),
1844 OPF_BMMIDDLE, u,
1845 ltoken_copy (ltoken_rbracket));
1846 ptr2arrayNameNode = makeNameNodeForm (opform);
1847
1848 /* operator: *__ */
1849 u.anyop = ltoken_create (LLT_MULOP, lsymbol_fromChars ("*"));
1850 opform = makeOpFormNode (ltoken_undefined, OPF_ANYOPM, u, ltoken_undefined);
1851 deRefNameNode = makeNameNodeForm (opform);
1852
1853 /* operator: __ + __ */
1854 u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("+"));
1855 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1856 plusNameNode = makeNameNodeForm (opform);
1857
1858 /* operator: __ - __ */
1859 u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("-"));
1860 opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
1861 minusNameNode = makeNameNodeForm (opform);
1862
1863 /* operator: NIL */
1864 nilNameNode = (nameNode) dmalloc (sizeof (*nilNameNode));
1865 nilNameNode->isOpId = TRUE;
1866 nilNameNode->content.opid = ltoken_createType (simpleId, SID_OP,
1867 lsymbol_fromChars ("NIL"));
1868
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;
1880
1881 /*
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.
1885 */
1886
1887 noSort.handle = sort_enterGlobal (noSort);
1888 (void) sort_enterGlobal (HOFSort);
1889
1890 /* Other builtin sorts */
1891
1892 sort_bool = sort_makeImmutable (ltoken_undefined, lsymbol_fromChars ("bool"));
1893 sort_capBool = sort_makeSortNoOps (ltoken_undefined, lsymbol_fromChars ("Bool"));
1894
1895 llassert (sortTable != NULL);
1896
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;
1902
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"));
1909
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);
1913
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"));
1917}
1918
1919sort
1920sort_lookupName (lsymbol name)
1921{
1922 long int i;
1923
1924 if (name == lsymbol_undefined)
1925 {
1926 return NOSORTHANDLE;
1927 }
1928
1929 llassert (sortTable != NULL);
1930
1931 for (i = 0; i < sortTableSize; i++)
1932 {
1933 if (sortTable[i].name == name)
1934 {
1935 return i;
1936 }
1937 }
1938
1939 return NOSORTHANDLE;
1940}
1941
1942static bool
1943sort_isNewEntry (sortNode s)
1944{
1945 int i;
1946
1947 for (i = 0; i < sortTableSize; i++)
1948 {
1949 llassert (sortTable != NULL);
1950
1951 if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
1952 {
1953 return FALSE;
1954 }
1955 }
1956 return TRUE;
1957}
1958
1959static sort
1960sort_enterGlobal (sortNode s)
1961{
1962 /*@i@*/ return (sort_enterNew (s));
1963}
1964
1965static sort
1966sort_enterNew (sortNode s)
1967{
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. */
1972 long int i;
1973
1974 for (i = 0; i < sortTableSize; i++)
1975 {
1976 llassert (sortTable != NULL);
1977
1978 if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
1979 {
1980 sortNode_free (s);
1981 return i;
1982 }
1983 }
1984
1985 if (sortTableSize >= sortTableAlloc)
1986 {
1987 sortNode *oldSortTable = sortTable;
1988
1989 sortTableAlloc += DELTA;
1990 sortTable = (sortNode *) dmalloc (sortTableAlloc * sizeof (*sortTable));
1991
1992 if (sortTableSize > 0)
1993 {
1994 llassert (oldSortTable != NULL);
1995 for (i = 0; i < sortTableSize; i++)
1996 {
1997 sortTable[i] = oldSortTable[i];
1998 }
1999 }
2000
2001 sfree (oldSortTable);
2002 }
2003
2004 llassert (sortTable != NULL);
2005
2006 s.handle = sortTableSize;
2007 sortTable[sortTableSize++] = s;
2008
2009 /*@-compdef@*/
2010
2011 return s.handle;
2012} /*=compdef@*/
2013
2014static sort sort_enterNewForce (sortNode s)
2015{
2016 sort sor = sort_enterNew (s);
2017
2018 s.handle = sor;
2019 llassert (sortTable != NULL);
2020 sortTable[sor] = s;
2021
2022 /*@-globstate@*/ return (sor); /*@=globstate@*/
2023}
2024
2025void
2026sort_printStats (void)
2027{
2028 /* only for debugging */
2029 printf ("sortTableSize = %d; sortTableAlloc = %d\n", sortTableSize,
2030 sortTableAlloc);
2031}
2032
2033sortNode
2034sort_lookup (sort sor)
2035{
2036 /* ymtan: can sor be 0 ? */
2037 /* evs --- yup...0 should return noSort ? */
2038
2039 if (sor > 0U && sor < (unsigned) sortTableSize)
2040 {
2041 llassert (sortTable != NULL);
2042 return sortTable[sor];
2043 }
2044
2045 llassert (sor == 0);
2046 return noSort;
2047}
2048
2049sortNode
2050sort_quietLookup (sort sor)
2051{
2052 /* ymtan: can sor be 0 ? */
2053 if (sor > 0U && sor < (unsigned) sortTableSize)
2054 {
2055 llassert (sortTable != NULL);
2056 return (sortTable[sor]);
2057 }
2058 else
2059 {
2060 return noSort;
2061 }
2062}
2063
2064static cstring
2065printEnumMembers (/*@null@*/ smemberInfo *list)
2066{
2067 cstring out = cstring_undefined;
2068 smemberInfo *m;
2069
2070 for (m = list; m != (smemberInfo *) 0; m = m->next)
2071 {
2072 out = cstring_concat (out, lsymbol_toString (m->name));
2073
2074 if (m->next != (smemberInfo *) 0)
2075 {
2076 out = cstring_concatChars (out, ", ");
2077 }
2078 }
2079 return out;
2080}
2081
2082static /*@only@*/ cstring
2083printStructMembers (/*@null@*/ smemberInfo *list)
2084{
2085 cstring ret = cstring_undefined;
2086 smemberInfo *m;
2087
2088 for (m = list; m != (smemberInfo *) 0; m = m->next)
2089 {
2090 ret = message ("%q%q %s; ",
2091 ret, sort_unparse (m->sort),
2092 cstring_fromChars (lsymbol_toChars (m->name)));
2093 }
2094
2095 return ret;
2096}
2097
2098/*@only@*/ cstring
2099sort_unparse (sort s)
2100{
2101 /* printing routine for sorts */
2102 sortNode sn;
2103 lsymbol name;
2104
2105 sn = sort_quietLookup (s);
2106 name = sn.name;
2107
2108 switch (sn.kind)
2109 {
2110 case SRT_NONE:
2111 if (name == lsymbol_undefined)
2112 {
2113 return cstring_makeLiteral ("_unknown");
2114 }
2115
2116 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2117 case SRT_HOF:
2118 return cstring_makeLiteral ("procedural");
2119 case SRT_PRIM:
2120 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2121 case SRT_SYN:
2122 return (cstring_fromCharsNew (lsymbol_toChars (name)));
2123
2124 case SRT_PTR:
2125 return (message ("%q *", sort_unparse (sort_makeVal (sn.baseSort))));
2126 case SRT_OBJ:
2127 return (message ("obj %q", sort_unparse (sn.baseSort)));
2128 case SRT_ARRAY:
2129 return (message ("array of %q", sort_unparse (sort_makeVal (sn.baseSort))));
2130 case SRT_VECTOR:
2131 return (message ("vector of %q", sort_unparse (sn.baseSort)));
2132 case SRT_TUPLE:
2133 if (sn.tag != lsymbol_undefined && sn.realtag)
2134 {
2135 return (message ("struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2136 }
2137 else
2138 {
2139 return (message ("struct {%q}", printStructMembers (sn.members)));
2140 }
2141 case SRT_UNIONVAL:
2142 if (sn.tag != lsymbol_undefined && sn.realtag)
2143 {
2144 return (message ("union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2145 }
2146 else
2147 {
2148 return (message ("union {%q}", printStructMembers (sn.members)));
2149 }
2150 case SRT_ENUM:
2151 if (sn.tag != lsymbol_undefined && sn.realtag)
2152 {
2153 return (message ("enum %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2154 }
2155 else
2156 {
2157 return (message ("enum {%q}", printEnumMembers (sn.members)));
2158 }
2159 case SRT_STRUCT:
2160 if (sn.tag != lsymbol_undefined && sn.realtag)
2161 {
2162 return (message ("obj struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2163 }
2164 else
2165 {
2166 return (message ("obj struct {%q}", printStructMembers (sn.members)));
2167 }
2168 case SRT_UNION:
2169 if (sn.tag != lsymbol_undefined && sn.realtag)
2170 {
2171 return (message ("obj union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
2172 }
2173 else
2174 {
2175 return (message ("obj union {%q}", printStructMembers (sn.members)));
2176 }
2177 default:
2178 return (cstring_makeLiteral ("illegal"));
2179 }
2180}
2181
2182static lsymbol
2183sp (lsymbol s1, lsymbol s2)
2184{
2185 char buff[MAXBUFFLEN];
2186 char *name1Ptr;
2187 char *name2Ptr;
2188 int temp_length;
2189
2190 name1Ptr = lsymbol_toCharsSafe (s1);
2191 name2Ptr = lsymbol_toCharsSafe (s2);
2192
2193 if (strlen (name1Ptr) + strlen (name2Ptr) + 1 > MAXBUFFLEN)
2194 {
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)));
2199 }
2200
2201 strcpy (&buff[0], name1Ptr);
2202 strcat (&buff[0], name2Ptr);
2203
2204 return lsymbol_fromChars (&buff[0]);
2205}
2206
2207static lsymbol
2208sortTag_toSymbol (char *kind, ltoken tagid, /*@out@*/ bool *isNew)
2209{
2210 /*
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)
2214 **/
2215
2216 tagInfo to;
2217
2218 if (ltoken_isUndefined (tagid))
2219 {
2220 *isNew = TRUE;
2221 return (cstring_toSymbol (message ("_anon_%s%d", cstring_fromChars (kind), sortUID++)));
2222 }
2223 else
2224 {
2225 to = symtable_tagInfo (g_symtab, ltoken_getText (tagid));
2226
2227 if (tagInfo_exists (to))
2228 {
2229 *isNew = FALSE;
2230 }
2231 else
2232 {
2233 *isNew = TRUE;
2234 }
2235
2236 return (cstring_toSymbol (message ("_%s_%s",
2237 ltoken_unparse (tagid),
2238 cstring_fromChars (kind))));
2239 }
2240}
2241
2242# define MAX_SORT_DEPTH 10
2243
2244static sort
2245sort_getUnderlyingAux (sort s, int depth)
2246{
2247 sortNode sn = sort_quietLookup (s);
2248
2249 if (sn.kind == SRT_SYN)
2250 {
2251 if (depth > MAX_SORT_DEPTH)
2252 {
2253 llcontbug (message ("sort_getUnderlying: depth charge: %d", depth));
2254 return s;
2255 }
2256
2257 return sort_getUnderlyingAux (sn.baseSort, depth + 1);
2258 }
2259
2260 return s;
2261}
2262
2263sort
2264sort_getUnderlying (sort s)
2265{
2266 return sort_getUnderlyingAux (s, 0);
2267}
2268
2269static lsymbol
2270underlyingSortName (sortNode sn)
2271{
2272 if (sn.kind == SRT_SYN)
2273 return underlyingSortName (sort_quietLookup (sn.baseSort));
2274 return sn.name;
2275}
2276
2277static /*@observer@*/ sortNode
2278underlyingSortNode (sortNode sn)
2279{
2280 if (sn.kind == SRT_SYN)
2281 {
2282 return underlyingSortNode (sort_quietLookup (sn.baseSort));
2283 }
2284
2285 return sn;
2286}
2287
2288bool
2289sort_mutable (sort s)
2290{
2291 /* if s is not a valid sort, then returns false */
2292 sortNode sn = sort_quietLookup (s);
2293 if (sn.mutable)
2294 return TRUE;
2295 return FALSE;
2296}
2297
2298bool
2299sort_setExporting (bool flag)
2300{
2301 bool old;
2302 old = exporting;
2303 exporting = flag;
2304 return old;
2305}
2306
2307/*@observer@*/ static cstring
2308sort_unparseKind (sortKind k)
2309{
2310 if (k > SRT_FIRST && k < SRT_LAST)
2311 return (cstring_fromChars (sortKindName[(int)k]));
2312 else
2313 return (cstring_makeLiteralTemp ("<unknown sort kind>"));
2314}
2315
2316bool
2317sort_isValidSort (sort s)
2318{
2319 sortNode sn = sort_quietLookup (s);
2320 sortKind k = sn.kind;
2321 if (k != SRT_NONE && k > SRT_FIRST && k < SRT_LAST)
2322 return TRUE;
2323 else
2324 return FALSE;
2325}
2326
2327void
2328sort_dump (FILE *f, bool lco)
2329{
2330 int i;
2331 sortNode s;
2332 smemberInfo *mem;
2333
2334 fprintf (f, "%s\n", BEGINSORTTABLE);
2335 llassert (sortTable != NULL);
2336
2337 for (i = 2; i < sortTableSize; i++)
2338 {
2339 /* skips 0 and 1, noSort and HOFSort */
2340 s = sortTable[i];
2341
2342 /* if (lco && !s.export) continue; */
2343 /* Difficult to keep track of where each op and sort belong to
2344 which LCL type. Easiest to export them all (even private sorts and
2345 op's) but for checking imported modules, we only use LCL types and
2346 variables to check, i.e., we don't rely on sorts and op's for such
2347 checking. */
2348
2349 if (s.kind == SRT_NONE)
2350 continue;
2351
2352 if (lco)
2353 {
2354 fprintf (f, "%%LCL");
2355 }
2356
2357 if (lsymbol_isDefined (s.name))
2358 {
2359 fprintf (f, "sort %s ", lsymbol_toCharsSafe (s.name));
2360 }
2361 else
2362 {
2363 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.",
2364 i, lsymbol_toString (s.name)));
2365 fprintf (f, "sort _error_ ");
2366 }
2367
2368 if (!lco && !s.export)
2369 fprintf (f, "private ");
2370
2371 /*@-loopswitchbreak@*/
2372 switch (s.kind)
2373 {
2374 case SRT_HOF:
2375 fprintf (f, "hof nil nil\n");
2376 break;
2377 case SRT_PRIM:
2378 if (s.abstract)
2379 fprintf (f, "immutable nil nil\n");
2380 else
2381 fprintf (f, "primitive nil nil\n");
2382 break;
2383 case SRT_OBJ:
2384 if (s.abstract)
2385 fprintf (f, "mutable %s nil\n",
2386 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2387 else
2388 fprintf (f, "obj %s nil\n",
2389 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2390 break;
2391 case SRT_SYN:
2392 fprintf (f, "synonym %s nil\n",
2393 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2394 break;
2395 case SRT_PTR:
2396 fprintf (f, "ptr %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2397 break;
2398 case SRT_ARRAY:
2399 fprintf (f, "arr %s nil\n",
2400 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2401 break;
2402 case SRT_VECTOR:
2403 fprintf (f, "vec %s %s\n",
2404 lsymbol_toCharsSafe (sortTable[s.baseSort].name),
2405 lsymbol_toCharsSafe (sortTable[s.objSort].name));
2406 break;
2407 case SRT_STRUCT:
2408 if (s.tag == lsymbol_undefined)
2409 {
2410 /* we need to make up a tag to prevent excessive
2411 growth of .lcs files when tags are overloaded
2412 */
2413 llbuglit ("Struct has no tag");
2414 }
2415 else
2416 fprintf (f, "str %s nil\n", lsymbol_toCharsSafe (s.tag));
2417
2418 for (mem = s.members;
2419 mem != smemberInfo_undefined; mem = mem->next)
2420 {
2421 if (lco)
2422 fprintf (f, "%%LCL");
2423 fprintf (f, "sort %s strMem %s nil\n", lsymbol_toCharsSafe (mem->name),
2424 lsymbol_toCharsSafe (sortTable[mem->sort].name));
2425 }
2426 if (lco)
2427 fprintf (f, "%%LCL");
2428 fprintf (f, "sort strEnd nil nil nil\n");
2429 break;
2430 case SRT_UNION:
2431 if (s.tag == lsymbol_undefined)
2432 llbuglit ("Union has no tag");
2433 else
2434 fprintf (f, "union %s nil\n", lsymbol_toCharsSafe (s.tag));
2435 for (mem = s.members;
2436 mem != smemberInfo_undefined; mem = mem->next)
2437 {
2438 if (lco)
2439 fprintf (f, "%%LCL");
2440 fprintf (f, "sort %s unionMem %s nil\n", lsymbol_toCharsSafe (mem->name),
2441 lsymbol_toCharsSafe (sortTable[mem->sort].name));
2442 }
2443 if (lco)
2444 fprintf (f, "%%LCL");
2445 fprintf (f, "sort unionEnd nil nil nil\n");
2446 break;
2447 case SRT_ENUM:
2448 if (s.tag == lsymbol_undefined)
2449 {
2450 llbuglit ("Enum has no tag");
2451 }
2452
2453 fprintf (f, "enum %s nil\n", lsymbol_toCharsSafe (s.tag));
2454
2455 for (mem = s.members;
2456 mem != smemberInfo_undefined; mem = mem->next)
2457 {
2458 if (lco)
2459 fprintf (f, "%%LCL");
2460 fprintf (f, "sort %s enumMem nil nil\n", lsymbol_toCharsSafe (mem->name));
2461 }
2462 if (lco)
2463 fprintf (f, "%%LCL");
2464 fprintf (f, "sort enumEnd nil nil nil\n");
2465 break;
2466 case SRT_TUPLE:
2467 fprintf (f, "tup %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2468 break;
2469 case SRT_UNIONVAL:
2470 fprintf (f, "unionval %s nil\n",
2471 lsymbol_toCharsSafe (sortTable[s.baseSort].name));
2472 break;
2473 default:
2474 fprintf (f, "sort_dump: unexpected sort: %d", (int)s.kind);
2475 } /* switch */
2476 /*@=loopswitchbreak@*/
2477 }
2478
2479 fprintf (f, "%s\n", SORTTABLEEND);
2480}
2481
2482static void
2483sort_loadOther (char *kstr, lsymbol sname, sort bsort)
2484{
2485 if (strcmp (kstr, "synonym") == 0)
2486 {
2487 (void) sort_construct (sname, SRT_SYN, bsort, lsymbol_undefined,
2488 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2489 }
2490 else if (strcmp (kstr, "mutable") == 0)
2491 {
2492 (void) sort_constructAbstract (sname, TRUE, bsort);
2493 }
2494 else if (strcmp (kstr, "obj") == 0)
2495 {
2496 (void) sort_construct (sname, SRT_OBJ, bsort, lsymbol_undefined,
2497 TRUE, NOSORTHANDLE, smemberInfo_undefined);
2498 }
2499 else if (strcmp (kstr, "ptr") == 0)
2500 {
2501 (void) sort_construct (sname, SRT_PTR, bsort, lsymbol_undefined,
2502 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2503 }
2504 else if (strcmp (kstr, "arr") == 0)
2505 {
2506 (void) sort_construct (sname, SRT_ARRAY, bsort, lsymbol_undefined,
2507 TRUE, NOSORTHANDLE, smemberInfo_undefined);
2508 }
2509 else if (strcmp (kstr, "tup") == 0)
2510 {
2511 (void) sort_construct (sname, SRT_TUPLE, bsort, lsymbol_undefined,
2512 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2513 }
2514 else if (strcmp (kstr, "unionval") == 0)
2515 {
2516 (void) sort_construct (sname, SRT_UNIONVAL, bsort, lsymbol_undefined,
2517 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2518 }
2519 else
2520 {
2521 llbug (message ("Unhandled: %s", cstring_fromChars (kstr)));
2522 }
2523}
2524
2525static void
2526parseSortLine (char *line, ltoken t, tsource * s,
2527 mapping *map, lsymbolList slist)
2528{
2529 /* caller expects that map and slist are updated */
2530 /* t and importfle are only used for error messages */
2531 static lsymbol strName = lsymbol_undefined;
2532 static smemberInfo *strMemList = NULL;
2533 static lsymbol unionName = lsymbol_undefined;
2534 static smemberInfo *unionMemList = NULL;
2535 static lsymbol enumName = lsymbol_undefined;
2536 static smemberInfo *enumMemList = NULL;
2537 static lsymbol tagName = lsymbol_undefined;
2538
2539 char *importfile = tsource_fileName (s);
2540 char sostr[MAXBUFFLEN], kstr[10], basedstr[MAXBUFFLEN], objstr[MAXBUFFLEN];
2541 bool tmp;
2542 tagInfo ti;
2543 lsymbol sname, bname, new_name, objName;
2544 sort objSort;
2545 char *lineptr;
2546 int col; /* for keeping column number */
2547 ltoken tagid;
2548
2549 if (sscanf (line, "sort %s %s %s %s", &(sostr[0]), &(kstr[0]),
2550 &(basedstr[0]), &(objstr[0])) != 4)
2551 {
2552 /* if this fails, can have weird errors */
2553 /* strEnd, unionEnd, enumEnd won't return 4 args */
2554 lclplainerror
2555 (message ("%q: Imported file contains illegal sort declaration. "
2556 "Skipping this line: \n%s\n",
2557 fileloc_unparseRaw (cstring_fromChars (importfile),
2558 tsource_thisLineNumber (s)),
2559 cstring_fromChars (line)));
2560 return;
2561 }
2562
2563 sname = lsymbol_fromChars (sostr);
2564 if (sname == lsymbol_fromChars ("nil"))
2565 {
2566 /* No given sort name. Use lsymbol_undefined and generate sort name
2567 in sort building routines. */
2568 sname = lsymbol_undefined;
2569 lclerror (t, message ("Illegal sort declaration in import file: %s:\n%s",
2570 cstring_fromChars (importfile),
2571 cstring_fromChars (line)));
2572 }
2573
2574 /* Assume that when we encounter a sort S1 that is based on sort
2575 S2, S2 is before S1 in the imported file. sort table is a
2576 linear list and we create base sorts before other sorts. */
2577
2578 bname = lsymbol_fromChars (basedstr);
2579 if (strcmp (kstr, "primitive") == 0)
2580 {
2581 new_name = lsymbol_translateSort (map, sname);
2582 (void) sort_construct (new_name, SRT_PRIM, NOSORTHANDLE,
2583 lsymbol_undefined, FALSE,
2584 NOSORTHANDLE, smemberInfo_undefined);
2585 }
2586 else if (strcmp (kstr, "strMem") == 0)
2587 {
2588 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2589 mem->next = strMemList;
2590 mem->name = sname;
2591 mem->sortname = bname;
2592 mem->sort = NOSORTHANDLE;
2593 strMemList = mem;
2594 }
2595 else if (strcmp (sostr, "strEnd") == 0)
2596 { /* now process it */
2597 if (strName != lsymbol_undefined && strMemList != NULL)
2598 {
2599 sort asort = sort_construct (strName, SRT_STRUCT, NOSORTHANDLE, tagName,
2600 TRUE, NOSORTHANDLE, strMemList);
2601
2602 if (tagName != lsymbol_undefined)
2603 {
2604 tagid = ltoken_create (simpleId, tagName);
2605
2606 ti = (tagInfo) dmalloc (sizeof (*ti));
2607 ti->sort = asort;
2608 ti->kind = TAG_STRUCT;
2609 ti->id = tagid;
2610 ti->imported = FALSE;
2611
2612 (void) symtable_enterTagForce (g_symtab, ti);
2613 }
2614 }
2615 else
2616 {
2617 if (strName == lsymbol_undefined)
2618 {
2619 lclbug (message ("%q: Imported file contains unexpected null struct sort",
2620 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2621 }
2622 else
2623 {
2624 /*
2625 ** no members -> its a forward struct
2626 */
2627
2628 if (tagName != lsymbol_undefined)
2629 {
2630 tagid = ltoken_create (simpleId, tagName);
2631 (void) checkAndEnterTag (TAG_FWDSTRUCT, tagid);
2632 }
2633 }
2634 }
2635 strName = lsymbol_undefined;
2636 strMemList = NULL;
2637 tagName = lsymbol_undefined;
2638 }
2639 else if (strcmp (kstr, "str") == 0)
2640 {
2641 if (strName != lsymbol_undefined || strMemList != NULL)
2642 {
2643 lclbug (message ("%q: unexpected non-null struct sort or "
2644 "non-empty member list",
2645 fileloc_unparseRaw (cstring_fromChars (importfile),
2646 tsource_thisLineNumber (s))));
2647 }
2648 /* see if a tag is associated with this sort */
2649 if (strcmp (basedstr, "nil") == 0)
2650 {
2651 llfatalerror (message ("%s: Struct missing tag. Obsolete .lcs file, remove and rerun lcl.",
2652 cstring_fromChars (importfile)));
2653 /*
2654 strName = sortTag_toSymbol ("Struct", nulltok, &tmp);
2655 tagName = lsymbol_undefined;
2656 mapping_bind (map, sname, strName);
2657 */
2658 }
2659 else /* a tag exists */
2660 { /* create tag in symbol table and add tagged sort in sort table */
2661 tagName = bname;
2662 tagid = ltoken_create (simpleId, bname);
2663
2664 strName = sortTag_toSymbol ("Struct", tagid, &tmp);
2665 ti = symtable_tagInfo (g_symtab, tagName);
2666
2667 /*
2668 ** No error for redefining a tag in an import.
2669 */
2670 }
2671 /* to be processed later in sort_import */
2672 lsymbolList_addh (slist, strName);
2673 }
2674 else if (strcmp (kstr, "enumMem") == 0)
2675 {
2676 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2677 mem->next = enumMemList;
2678 mem->sortname = enumName;
2679 mem->name = sname;
2680 mem->sort = NOSORTHANDLE;
2681 enumMemList = mem;
2682 }
2683 else if (strcmp (sostr, "enumEnd") == 0)
2684 {
2685 if (enumName != lsymbol_undefined && enumMemList != NULL)
2686 {
2687 sort asort = sort_construct (enumName, SRT_ENUM, NOSORTHANDLE, tagName,
2688 FALSE, NOSORTHANDLE, enumMemList);
2689
2690 if (tagName != lsymbol_undefined)
2691 {
2692 tagid = ltoken_create (simpleId, tagName);
2693
2694 ti = (tagInfo) dmalloc (sizeof (*ti));
2695 ti->sort = asort;
2696 ti->kind = TAG_ENUM;
2697 ti->id = tagid;
2698 ti->imported = FALSE;
2699
2700 (void) symtable_enterTagForce (g_symtab, ti);
2701 }
2702 }
2703 else
2704 {
2705 lclbug (message ("%q: unexpected null enum sort or empty member list",
2706 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2707 }
2708 enumName = lsymbol_undefined;
2709 enumMemList = NULL;
2710 tagName = lsymbol_undefined;
2711 }
2712 else if (strcmp (kstr, "enum") == 0)
2713 {
2714 if (enumName != lsymbol_undefined || enumMemList != NULL)
2715 {
2716 lclbug (message ("%q: Unexpected non-null enum sort or "
2717 "non-empty member list",
2718 fileloc_unparseRaw (cstring_fromChars (importfile),
2719 tsource_thisLineNumber (s))));
2720 }
2721
2722 /* see if a tag is associated with this sort */
2723 if (strcmp (basedstr, "nil") == 0)
2724 {
2725 llfatalerror (message ("%s: Enum missing tag. Obsolete .lcs file, "
2726 "remove and rerun lcl.",
2727 cstring_fromChars (importfile)));
2728 }
2729 else
2730 { /* a tag exists */
2731 tagName = bname;
2732 tagid = ltoken_create (simpleId, bname);
2733 enumName = sortTag_toSymbol ("Enum", tagid, &tmp);
2734 ti = symtable_tagInfo (g_symtab, bname);
2735 }
2736 }
2737 else if (strcmp (kstr, "unionMem") == 0)
2738 {
2739 smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
2740 mem->next = unionMemList;
2741 mem->sortname = bname;
2742 mem->name = sname;
2743 mem->sort = NOSORTHANDLE;
2744 unionMemList = mem;
2745 }
2746 else if (strcmp (sostr, "unionEnd") == 0)
2747 {
2748 if (unionName != lsymbol_undefined && unionMemList != NULL)
2749 {
2750 sort asort = sort_construct (unionName, SRT_UNION, NOSORTHANDLE, tagName,
2751 FALSE, NOSORTHANDLE, unionMemList);
2752
2753 if (tagName != lsymbol_undefined)
2754 {
2755 tagid = ltoken_create (simpleId, tagName);
2756
2757 ti = (tagInfo) dmalloc (sizeof (*ti));
2758 ti->sort = asort;
2759 ti->kind = TAG_UNION;
2760 ti->id = tagid;
2761 ti->imported = FALSE;
2762
2763 (void) symtable_enterTagForce (g_symtab, ti);
2764 }
2765 }
2766 else
2767 {
2768 if (unionName == lsymbol_undefined)
2769 {
2770 lclbug
2771 (message ("%q: Imported file contains unexpected null union sort",
2772 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2773 }
2774 else
2775 {
2776 /*
2777 ** no members -> its a forward struct
2778 */
2779
2780 if (tagName != lsymbol_undefined)
2781 {
2782 tagid = ltoken_create (simpleId, tagName);
2783
2784 (void) checkAndEnterTag (TAG_FWDUNION, tagid);
2785 }
2786 }
2787 }
2788
2789 unionName = lsymbol_undefined;
2790 unionMemList = NULL;
2791 tagName = lsymbol_undefined;
2792 }
2793 else if (strcmp (kstr, "union") == 0)
2794 {
2795 if (unionName != lsymbol_undefined || unionMemList != NULL)
2796 {
2797 lclbug
2798 (message
2799 ("%q: Unexpected non-null union sort or non-empty "
2800 "member list",
2801 fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
2802 }
2803 /* see if a tag is associated with this sort */
2804 if (strcmp (basedstr, "nil") == 0)
2805 {
2806 llfatalerror
2807 (message ("%s: Union missing tag. Obsolete .lcs file, "
2808 "remove and rerun lcl.",
2809 cstring_fromChars (importfile)));
2810 }
2811 else
2812 { /* a tag exists */
2813 tagName = bname;
2814 tagid = ltoken_create (simpleId, bname);
2815
2816 unionName = sortTag_toSymbol ("Union", tagid, &tmp);
2817 ti = symtable_tagInfo (g_symtab, bname);
2818 }
2819 lsymbolList_addh (slist, unionName);
2820 }
2821 else if (strcmp (kstr, "immutable") == 0)
2822 {
2823 (void) sort_constructAbstract (sname, FALSE, NOSORTHANDLE);
2824 }
2825 else if (strcmp (kstr, "hof") == 0)
2826 {
2827 (void) sort_construct (sname, SRT_HOF, NOSORTHANDLE, lsymbol_undefined,
2828 FALSE, NOSORTHANDLE, smemberInfo_undefined);
2829 }
2830 else
2831 {
2832 sort bsort = sort_lookupName (lsymbol_translateSort (map, bname));
2833
2834 if (sort_isNoSort (bsort))
2835 {
2836 lineptr = strchr (line, ' '); /* go past "sort" */
2837 llassert (lineptr != NULL);
2838 lineptr = strchr (lineptr + 1, ' '); /* go past sostr */
2839 llassert (lineptr != NULL);
2840 lineptr = strchr (lineptr + 1, ' '); /* go past kstr */
2841 llassert (lineptr != NULL);
2842 col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
2843
2844 llbug
2845 (message ("%q: Imported file contains unknown base sort: %s",
2846 fileloc_unparseRawCol (cstring_fromChars (importfile),
2847 tsource_thisLineNumber (s), col),
2848 cstring_fromChars (lsymbol_toCharsSafe (bname))));
2849 }
2850
2851 if (strcmp (kstr, "vec") == 0)
2852 {
2853 objName = lsymbol_fromChars (objstr);
2854 objSort = sort_lookupName (lsymbol_translateSort (map, objName));
2855 (void) sort_construct (sname, SRT_VECTOR, bsort, lsymbol_undefined,
2856 FALSE, objSort, smemberInfo_undefined);
2857 }
2858 else
2859 {
2860 sort_loadOther (kstr, sname, bsort);
2861 }
2862 }
2863}
2864
2865void
2866sort_import (tsource *imported, ltoken tok, mapping * map)
2867{
2868 /* tok is only used for error message line number */
2869 char *buf, *importfile;
2870 tsource *lclsource;
2871 sort bsort;
2872 lsymbolList slist = lsymbolList_new ();
2873
2874 buf = tsource_nextLine (imported);
2875
2876 llassert (buf != NULL);
2877
2878 importfile = tsource_fileName (imported);
2879
2880 if (!firstWord (buf, "%LCLSortTable"))
2881 {
2882 lclsource = LCLScanSource ();
2883
2884 lclfatalerror (tok, message ("Expecting \"%%LCLSortTable\" line "
2885 "in import file %s:\n%s",
2886 cstring_fromChars (importfile),
2887 cstring_fromChars (buf)));
2888
2889 }
2890
2891 for (;;)
2892 {
2893 buf = tsource_nextLine (imported);
2894
2895 llassert (buf != NULL);
2896
2897 if (firstWord (buf, "%LCLSortTableEnd"))
2898 {
2899 break;
2900 }
2901 else
2902 { /* a good line, remove %LCL from line first */
2903 if (firstWord (buf, "%LCL"))
2904 {
2905 parseSortLine (buf + 4, tok, imported, map, slist);
2906 }
2907 else
2908 {
2909 lclsource = LCLScanSource ();
2910 lclfatalerror
2911 (tok,
2912 message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
2913 cstring_fromChars (importfile),
2914 cstring_fromChars (buf)));
2915 }
2916 }
2917 }
2918
2919 /* now process the smemberInfo in the sort List */
2920 lsymbolList_elements (slist, s)
2921 {
2922 if (s != lsymbol_undefined)
2923 {
2924 sort sor;
2925 sortNode sn;
2926
2927 sor = sort_lookupName (s);
2928 sn = sort_quietLookup (sor);
2929
2930 switch (sn.kind)
2931 {
2932 case SRT_ENUM:
2933 { /* update the symbol table with members of enum */
2934 varInfo vi;
2935 smemberInfo *mlist = sn.members;
2936 for (; mlist != NULL; mlist = mlist->next)
2937 {
2938 /* check that enumeration constants are unique */
2939 vi = symtable_varInfo (g_symtab, mlist->name);
2940 if (!varInfo_exists (vi))
2941 { /* put info into symbol table */
2942 vi = (varInfo) dmalloc (sizeof (*vi));
2943 vi->id = ltoken_create (NOTTOKEN, mlist->name);
2944 vi->kind = VRK_ENUM;
2945 vi->sort = sor;
2946 vi->export = TRUE;
2947
2948 (void) symtable_enterVar (g_symtab, vi);
2949 varInfo_free (vi);
2950 }
2951 else
2952 {
2953 lclplainerror
2954 (message ("%s: enum member %s of %s has already been declared",
2955 cstring_fromChars (importfile),
2956 lsymbol_toString (mlist->name),
2957 lsymbol_toString (sn.name)));
2958 }
2959 }
2960 /*@switchbreak@*/ break;
2961 }
2962 case SRT_STRUCT:
2963 case SRT_UNION:
2964 {
2965 smemberInfo *mlist = sn.members;
2966
2967 for (; mlist != NULL; mlist = mlist->next)
2968 {
2969 bsort = sort_lookupName (lsymbol_translateSort (map, mlist->sortname));
2970 if (sort_isNoSort (bsort))
2971 {
2972 lclbug (message ("%s: member %s of %s has unknown sort\n",
2973 cstring_fromChars (importfile),
2974 cstring_fromChars (lsymbol_toChars (mlist->name)),
2975 cstring_fromChars (lsymbol_toChars (sn.name))));
2976 }
2977 else
2978 {
2979 mlist->sort = bsort;
2980 }
2981 }
2982 /*@switchbreak@*/ break;
2983 }
2984 default:
2985 lclbug (message ("%s: %s has unexpected sort kind %s",
2986 cstring_fromChars (importfile),
2987 cstring_fromChars (lsymbol_toChars (sn.name)),
2988 sort_unparseKind (sn.kind)));
2989 }
2990 }
2991 } end_lsymbolList_elements;
2992
2993 /* list and sorts in it are not used anymore */
2994 lsymbolList_free (slist);
2995}
2996
2997bool
2998sort_equal (sort *s1, sort *s2)
2999{
3000 sort syn1, syn2;
3001 if ((s1 != 0) && (s2 != 0))
3002 {
3003 if ((*s1) == (*s2))
3004 return TRUE;
3005 /* handle synonym sorts */
3006 syn1 = sort_getUnderlying (*s1);
3007 syn2 = sort_getUnderlying (*s2);
3008 if (syn1 == syn2)
3009 return TRUE;
3010 /* makes bool and Bool equal */
3011 }
3012 return FALSE;
3013}
3014
3015bool
3016sort_compatible (sort s1, sort s2)
3017{
3018 sort syn1, syn2;
3019 /* later: might consider "char" and enum types the same as "int" */
3020 if (s1 == s2)
3021 return TRUE;
3022 /* handle synonym sorts */
3023 syn1 = sort_getUnderlying (s1);
3024 syn2 = sort_getUnderlying (s2);
3025 if (syn1 == syn2)
3026 return TRUE;
3027 /* makes bool and Bool equal */
3028 return FALSE;
3029}
3030
3031bool
3032sort_compatible_modulo_cstring (sort s1, sort s2)
3033{
3034 /* like sort_compatible but also handles special cstring inits,
3035 allows the following 2 cases:
3036 char c[] = "abc"; (LHS: char_Obj_Arr, RHS = char_Vec)
3037 (c as implicitly coerced into c^)
3038 char *d = "abc"; (LHS: char_Obj_Ptr, RHS = char_Vec)
3039 (d as implicitly coerced into d[]^)
3040 */
3041 sort syn1, syn2;
3042 if (sort_compatible (s1, s2))
3043 return TRUE;
3044 syn1 = sort_getUnderlying (s1);
3045 syn2 = sort_getUnderlying (s2);
3046 if (sort_cstring == syn2 &&
3047 (syn1 == char_obj_ptrSort || syn1 == char_obj_ArrSort))
3048 return TRUE;
3049 return FALSE;
3050}
3051
3052lsymbol
3053sort_getLsymbol (sort sor)
3054{
3055 /* sortNode sn = sort_lookup (sor); */
3056 sortNode sn = sort_quietLookup (sor);
3057 return sn.name;
3058}
3059
3060/* a few handy routines for debugging */
3061
3062char *sort_getName (sort s)
3063{
3064 return (lsymbol_toCharsSafe (sort_getLsymbol (s)));
3065}
3066
3067/*@exposed@*/ cstring
3068sort_unparseName (sort s)
3069{
3070 return (cstring_fromChars (sort_getName (s)));
3071}
3072
3073static void
3074sortError (ltoken t, sort oldsort, sortNode newnode)
3075{
3076 sortNode old = sort_quietLookup (oldsort);
3077
3078 if ((old.kind <= SRT_FIRST || old.kind >= SRT_LAST) ||
3079 (newnode.kind <= SRT_FIRST || newnode.kind >= SRT_LAST))
3080 {
3081 llbuglit ("sortError: illegal sort kind");
3082 }
3083
3084 llassert (sortTable != NULL);
3085
3086 lclerror (t, message ("Sort %s defined as %s cannot be redefined as %s",
3087 cstring_fromChars (lsymbol_toChars (newnode.name)),
3088 sort_unparseKindName (sortTable[oldsort]),
3089 sort_unparseKindName (newnode)));
3090}
3091
3092static /*@observer@*/ cstring
3093 sort_unparseKindName (sortNode s)
3094{
3095 switch (s.kind)
3096 {
3097 case SRT_NONE:
3098 return cstring_fromChars (sortKindName[(int)s.kind]);
3099 default:
3100 if (s.abstract)
3101 {
3102 if (s.mutable)
3103 {
3104 return cstring_makeLiteralTemp ("MUTABLE");
3105 }
3106 else
3107 {
3108 return cstring_makeLiteralTemp ("IMMUTABLE");
3109 }
3110 }
3111 else
3112 return cstring_fromChars (sortKindName[(int)s.kind]);
3113 }
3114
3115 BADEXIT;
3116}
3117
3118sort
3119sort_fromLsymbol (lsymbol sortid)
3120{
3121 /* like sort_lookupName but creates sort if not already present */
3122 sort sort = sort_lookupName (sortid);
3123 if (sort == NOSORTHANDLE)
3124 sort = sort_makeSort (ltoken_undefined, sortid);
3125 return sort;
3126}
3127
3128bool
3129sort_isHOFSortKind (sort s)
3130{
3131 sortNode sn = sort_quietLookup (s);
3132 if (sn.kind == SRT_HOF)
3133 return TRUE;
3134 return FALSE;
3135}
3136
3137/*
3138** returns TRUE iff s has State operators (', ~, ^)
3139*/
3140
3141static bool
3142sort_hasStateFcns (sort s)
3143{
3144 sortNode sn = sort_quietLookup (s);
3145 sortKind kind = sn.kind;
3146
3147 if (kind == SRT_SYN)
3148 {
3149 return (sort_hasStateFcns (sn.baseSort));
3150 }
3151
3152 return ((kind == SRT_PTR) ||
3153 (kind == SRT_OBJ) ||
3154 (kind == SRT_ARRAY) ||
3155 (kind == SRT_STRUCT) ||
3156 (kind == SRT_UNION));
3157}
3158
3159
This page took 0.439995 seconds and 5 git commands to generate.