]>
Commit | Line | Data |
---|---|---|
885824d3 | 1 | /* ;-*-C-*-; |
2 | ** Copyright (c) Massachusetts Institute of Technology 1994-1998. | |
3 | ** All Rights Reserved. | |
4 | ** Unpublished rights reserved under the copyright laws of | |
5 | ** the United States. | |
6 | ** | |
7 | ** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED | |
8 | ** OR IMPLIED. ANY USE IS AT YOUR OWN RISK. | |
9 | ** | |
10 | ** This code is distributed freely and may be used freely under the | |
11 | ** following conditions: | |
12 | ** | |
13 | ** 1. This notice may not be removed or altered. | |
14 | ** | |
15 | ** 2. Works derived from this code are not distributed for | |
16 | ** commercial gain without explicit permission from MIT | |
17 | ** (for permission contact lclint-request@sds.lcs.mit.edu). | |
18 | */ | |
19 | /* | |
20 | ** cttable.i | |
21 | ** | |
22 | ** NOTE: This is not a stand-alone source file, but is included in ctype.c. | |
23 | ** (This is necessary becuase there is no other way in C to have a | |
24 | ** hidden scope, besides at the file level.) | |
25 | */ | |
26 | ||
27 | /*@access ctype@*/ | |
28 | ||
29 | /* | |
30 | ** type definitions and forward declarations in ctbase.i | |
31 | */ | |
32 | ||
33 | static void | |
34 | ctentry_free (/*@only@*/ ctentry c) | |
35 | { | |
36 | ctbase_free (c->ctbase); | |
37 | cstring_free (c->unparse); | |
38 | sfree (c); | |
39 | } | |
40 | ||
41 | static void cttable_reset (void) | |
42 | /*@globals cttab@*/ | |
43 | /*@modifies cttab@*/ | |
44 | { | |
45 | if (cttab.entries != NULL) | |
46 | { | |
47 | int i; | |
48 | ||
49 | for (i = 0; i < cttab.size; i++) | |
50 | { | |
51 | ctentry_free (cttab.entries[i]); | |
52 | } | |
53 | ||
54 | /*@-compdestroy@*/ | |
55 | sfree (cttab.entries); | |
56 | /*@=compdestroy@*/ | |
57 | ||
58 | cttab.entries = NULL; | |
59 | } | |
60 | ||
61 | cttab.size = 0 ; | |
62 | cttab.nspace = 0 ; | |
63 | } | |
64 | ||
65 | static /*@observer@*/ ctbase ctype_getCtbase (ctype c) | |
66 | { | |
67 | /*@+enumint@*/ | |
68 | if (c >= 0 && c < cttab.size) | |
69 | { | |
70 | return (cttab.entries[c]->ctbase); | |
71 | } | |
72 | else | |
73 | { | |
74 | if (c == CTK_UNKNOWN) | |
75 | llbuglit ("ctype_getCtbase: ctype unknown"); | |
76 | if (c == CTK_INVALID) | |
77 | llbuglit ("ctype_getCtbase: ctype invalid"); | |
78 | if (c == CTK_DNE) | |
79 | llbuglit ("ctype_getCtbase: ctype dne"); | |
80 | if (c == CTK_ELIPS) | |
81 | llbuglit ("ctype_getCtbase: elips marker"); | |
82 | ||
83 | llfatalbug (message ("ctype_getCtbase: ctype out of range: %d", c)); | |
84 | BADEXIT; | |
85 | } | |
86 | ||
87 | /*@=enumint@*/ | |
88 | } | |
89 | ||
90 | static /*@notnull@*/ /*@observer@*/ ctbase | |
91 | ctype_getCtbaseSafe (ctype c) | |
92 | { | |
93 | ctbase res = ctype_getCtbase (c); | |
94 | ||
95 | llassert (ctbase_isDefined (res)); | |
96 | return res; | |
97 | } | |
98 | ||
99 | /* | |
100 | ** ctentry | |
101 | */ | |
102 | ||
103 | static ctentry | |
104 | ctype_getCtentry (ctype c) | |
105 | { | |
106 | static /*@only@*/ ctentry errorEntry = NULL; | |
107 | ||
108 | if (cttab.size == 0) | |
109 | { | |
110 | if (errorEntry == NULL) | |
111 | { | |
112 | errorEntry = ctentry_makeNew (CTK_UNKNOWN, ctbase_undefined); | |
113 | } | |
114 | ||
115 | return errorEntry; | |
116 | } | |
117 | ||
118 | /*@+enumint@*/ | |
119 | if (c >= CTK_PLAIN && c < cttab.size) | |
120 | { | |
121 | return (cttab.entries[c]); | |
122 | } | |
123 | else if (c == CTK_UNKNOWN) | |
124 | llcontbuglit ("ctype_getCtentry: ctype unknown"); | |
125 | else if (c == CTK_INVALID) | |
126 | llcontbuglit ("ctype_getCtentry: ctype invalid (ctype_undefined)"); | |
127 | else if (c == CTK_DNE) | |
128 | llcontbuglit ("ctype_getCtentry: ctype dne"); | |
a0a162cd | 129 | else if (c == CTK_ELIPS) |
130 | llcontbuglit ("ctype_getCtentry: ctype elipsis"); | |
131 | else if (c == CTK_MISSINGPARAMS) | |
132 | llcontbuglit ("ctype_getCtentry: ctype missing params"); | |
885824d3 | 133 | else |
134 | llbug (message ("ctype_getCtentry: ctype out of range: %d", c)); | |
135 | ||
136 | return (cttab.entries[ctype_unknown]); | |
137 | /*@=enumint@*/ | |
138 | } | |
139 | ||
140 | static ctentry | |
141 | ctentry_makeNew (ctkind ctk, /*@only@*/ ctbase c) | |
142 | { | |
143 | ||
144 | return (ctentry_make (ctk, c, ctype_dne, ctype_dne, ctype_dne, cstring_undefined)); | |
145 | } | |
146 | ||
147 | static /*@only@*/ ctentry | |
148 | ctentry_make (ctkind ctk, | |
149 | /*@keep@*/ ctbase c, ctype base, | |
150 | ctype ptr, ctype array, | |
151 | /*@keep@*/ cstring unparse) /*@*/ | |
152 | { | |
153 | ctentry cte = (ctentry) dmalloc (sizeof (*cte)); | |
154 | cte->kind = ctk; | |
155 | cte->ctbase = c; | |
156 | cte->base = base; | |
157 | cte->ptr = ptr; | |
158 | cte->array = array; | |
159 | cte->unparse = unparse; | |
160 | return cte; | |
161 | } | |
162 | ||
163 | static cstring | |
164 | ctentry_unparse (ctentry c) | |
165 | { | |
166 | return (message | |
167 | ("%20s [%d] [%d] [%d]", | |
168 | (cstring_isDefined (c->unparse) ? c->unparse : cstring_makeLiteral ("<no name>")), | |
169 | c->base, | |
170 | c->ptr, | |
171 | c->array)); | |
172 | } | |
173 | ||
174 | static bool | |
175 | ctentry_isInteresting (ctentry c) | |
176 | { | |
177 | return (cstring_isNonEmpty (c->unparse)); | |
178 | } | |
179 | ||
180 | static /*@only@*/ cstring | |
181 | ctentry_dump (ctentry c) | |
182 | { | |
a0a162cd | 183 | DPRINTF (("Dumping: %s", ctentry_unparse (c))); |
184 | ||
885824d3 | 185 | if (c->ptr == ctype_dne |
186 | && c->array == ctype_dne | |
187 | && c->base == ctype_dne) | |
188 | { | |
189 | return (message ("%d %q&", | |
190 | ctkind_toInt (c->kind), | |
191 | ctbase_dump (c->ctbase))); | |
192 | } | |
193 | else if (c->base == ctype_undefined | |
194 | && c->array == ctype_dne) | |
195 | { | |
196 | if (c->ptr == ctype_dne) | |
197 | { | |
198 | return (message ("%d %q!", | |
199 | ctkind_toInt (c->kind), | |
200 | ctbase_dump (c->ctbase))); | |
201 | } | |
202 | else | |
203 | { | |
204 | return (message ("%d %q^%d", | |
205 | ctkind_toInt (c->kind), | |
206 | ctbase_dump (c->ctbase), | |
207 | c->ptr)); | |
208 | } | |
209 | } | |
210 | else if (c->ptr == ctype_dne | |
211 | && c->array == ctype_dne) | |
212 | { | |
213 | return (message ("%d %q%d&", | |
214 | ctkind_toInt (c->kind), | |
215 | ctbase_dump (c->ctbase), | |
216 | c->base)); | |
217 | } | |
218 | else | |
219 | { | |
220 | return (message ("%d %q%d %d %d", | |
221 | ctkind_toInt (c->kind), | |
222 | ctbase_dump (c->ctbase), | |
223 | c->base, c->ptr, c->array)); | |
224 | } | |
225 | } | |
226 | ||
227 | ||
228 | static /*@only@*/ ctentry | |
229 | ctentry_undump (/*@dependent@*/ char *s) | |
230 | { | |
231 | int base, ptr, array; | |
232 | ctkind kind; | |
233 | ctbase ct; | |
234 | ||
235 | kind = ctkind_fromInt (getInt (&s)); | |
236 | ct = ctbase_undump (&s); | |
237 | ||
238 | if (optCheckChar (&s, '&')) | |
239 | { | |
240 | base = ctype_dne; | |
241 | ptr = ctype_dne; | |
242 | array = ctype_dne; | |
243 | } | |
244 | else if (optCheckChar (&s, '!')) | |
245 | { | |
246 | base = ctype_undefined; | |
247 | ptr = ctype_dne; | |
248 | array = ctype_dne; | |
249 | } | |
250 | else if (optCheckChar (&s, '^')) | |
251 | { | |
252 | base = ctype_undefined; | |
253 | ptr = getInt (&s); | |
254 | array = ctype_dne; | |
255 | } | |
256 | else | |
257 | { | |
258 | base = getInt (&s); | |
259 | ||
260 | if (optCheckChar (&s, '&')) | |
261 | { | |
262 | ptr = ctype_dne; | |
263 | array = ctype_dne; | |
264 | } | |
265 | else | |
266 | { | |
267 | ptr = getInt (&s); | |
268 | array = getInt (&s); | |
269 | } | |
270 | } | |
271 | ||
272 | /* can't unparse w/o typeTable */ | |
273 | return (ctentry_make (kind, ct, base, ptr, array, cstring_undefined)); | |
274 | } | |
275 | ||
276 | static /*@observer@*/ cstring | |
277 | ctentry_doUnparse (ctentry c) /*@modifies c@*/ | |
278 | { | |
279 | if (cstring_isDefined (c->unparse)) | |
280 | { | |
281 | return (c->unparse); | |
282 | } | |
283 | else | |
284 | { | |
285 | cstring s = ctbase_unparse (c->ctbase); | |
286 | ||
287 | if (!cstring_isEmpty (s) && !cstring_containsChar (s, '<')) | |
288 | { | |
289 | c->unparse = s; | |
290 | } | |
291 | else | |
292 | { | |
293 | cstring_markOwned (s); | |
294 | } | |
295 | ||
296 | return (s); | |
297 | } | |
298 | } | |
299 | ||
300 | static /*@observer@*/ cstring | |
301 | ctentry_doUnparseDeep (ctentry c) | |
302 | { | |
303 | if (cstring_isDefined (c->unparse)) | |
304 | { | |
305 | return (c->unparse); | |
306 | } | |
307 | else | |
308 | { | |
309 | c->unparse = ctbase_unparseDeep (c->ctbase); | |
310 | return (c->unparse); | |
311 | } | |
312 | } | |
313 | ||
314 | /* | |
315 | ** cttable operations | |
316 | */ | |
317 | ||
318 | static /*@only@*/ cstring | |
319 | cttable_unparse (void) | |
320 | { | |
321 | int i; | |
322 | cstring s = cstring_undefined; | |
323 | ||
324 | /*@access ctbase@*/ | |
325 | for (i = 0; i < cttab.size; i++) | |
326 | { | |
327 | ctentry cte = cttab.entries[i]; | |
328 | if (ctentry_isInteresting (cte)) | |
329 | { | |
330 | if (ctbase_isUA (cte->ctbase)) | |
331 | { | |
332 | s = message ("%s%d\t%q [%d]\n", s, i, ctentry_unparse (cttab.entries[i]), | |
333 | cte->ctbase->contents.tid); | |
334 | } | |
335 | else | |
336 | { | |
337 | s = message ("%s%d\t%q\n", s, i, ctentry_unparse (cttab.entries[i])); | |
338 | } | |
339 | } | |
340 | } | |
341 | /*@noaccess ctbase@*/ | |
342 | return (s); | |
343 | } | |
344 | ||
345 | void | |
346 | cttable_print (void) | |
347 | { | |
348 | int i; | |
349 | ||
350 | /*@access ctbase@*/ | |
351 | for (i = 0; i < cttab.size; i++) | |
352 | { | |
353 | ctentry cte = cttab.entries[i]; | |
354 | ||
355 | if (ctentry_isInteresting (cte)) | |
356 | { | |
357 | if (ctbase_isUA (cte->ctbase)) | |
358 | { | |
359 | fprintf (g_msgstream, "%3d: %s [%d]\n", i, | |
360 | cstring_toCharsSafe (ctentry_doUnparse (cttab.entries[i])), | |
361 | cte->ctbase->contents.tid); | |
362 | } | |
363 | else | |
364 | { | |
365 | fprintf (g_msgstream, "%3d: %s\n", i, | |
366 | cstring_toCharsSafe (ctentry_doUnparse (cttab.entries[i]))); | |
367 | } | |
368 | } | |
369 | else | |
370 | { | |
371 | /* fprintf (g_msgstream, "%3d: <no name>\n", i); */ | |
372 | } | |
373 | } | |
374 | /*@noaccess ctbase@*/ | |
375 | } | |
376 | ||
377 | /* | |
378 | ** cttable_dump | |
379 | ** | |
380 | ** Output cttable for dump file | |
381 | */ | |
382 | ||
383 | static void | |
384 | cttable_dump (FILE *fout) | |
385 | { | |
386 | bool showdots = FALSE; | |
387 | int showdotstride = 0; | |
388 | int i; | |
389 | ||
390 | if (context_getFlag (FLG_SHOWSCAN) && cttab.size > 5000) | |
391 | { | |
392 | fprintf (g_msgstream, " >\n"); /* end dumping to */ | |
393 | fprintf (g_msgstream, "< Dumping type table (%d types) ", cttab.size); | |
394 | showdotstride = cttab.size / 5; | |
395 | showdots = TRUE; | |
396 | } | |
397 | ||
398 | for (i = 0; i < cttab.size; i++) | |
399 | { | |
400 | cstring s; | |
401 | ||
402 | s = ctentry_dump (cttab.entries[i]); | |
403 | llassert (cstring_length (s) < MAX_DUMP_LINE_LENGTH); | |
404 | fputline (fout, cstring_toCharsSafe (s)); | |
405 | cstring_free (s); | |
406 | ||
407 | if (showdots && (i != 0 && ((i - 1) % showdotstride == 0))) | |
408 | { | |
409 | (void) fflush (g_msgstream); | |
410 | fprintf (stderr, "."); | |
411 | (void) fflush (stderr); | |
412 | } | |
413 | } | |
414 | ||
415 | if (showdots) | |
416 | { | |
417 | fprintf (stderr, " >\n< Continuing dump "); | |
418 | } | |
419 | ||
a0a162cd | 420 | } |
885824d3 | 421 | |
422 | /* | |
423 | ** load cttable from init file | |
424 | */ | |
425 | ||
426 | static void cttable_load (FILE *f) | |
427 | /*@globals cttab @*/ | |
428 | /*@modifies cttab, f @*/ | |
429 | { | |
430 | char *s = mstring_create (MAX_DUMP_LINE_LENGTH); | |
431 | ctentry cte; | |
432 | ||
433 | cttable_reset (); | |
434 | ||
435 | while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL && *s == ';') | |
436 | { | |
437 | ; | |
438 | } | |
439 | ||
440 | if (mstring_length (s) == (MAX_DUMP_LINE_LENGTH - 1)) | |
441 | { | |
442 | llbug (message ("Library line too long: %s\n", cstring_fromChars (s))); | |
443 | } | |
444 | ||
445 | while (s != NULL && *s != ';' && *s != '\0') | |
446 | { | |
447 | ctype ct; | |
448 | ||
449 | cte = ctentry_undump (s); | |
450 | ct = cttable_addFull (cte); | |
451 | ||
452 | if (ctbase_isConj (cte->ctbase) | |
453 | && !(cte->ctbase->contents.conj->isExplicit)) | |
454 | { | |
455 | ctype_recordConj (ct); | |
456 | } | |
457 | ||
458 | (void) fgets (s, MAX_DUMP_LINE_LENGTH, f); | |
459 | } | |
460 | ||
461 | sfree (s); | |
462 | } | |
463 | ||
464 | /* | |
465 | ** cttable_init | |
466 | ** | |
467 | ** fill up the cttable with basic types, and first order derivations. | |
468 | ** this is done without using our constructors for efficiency reasons | |
469 | ** (probably bogus) | |
470 | ** | |
471 | */ | |
472 | ||
473 | /*@access cprim@*/ | |
474 | static void cttable_init (void) | |
475 | /*@globals cttab@*/ /*@modifies cttab@*/ | |
476 | { | |
477 | ctkind i; | |
478 | cprim j; | |
479 | ctbase ct = ctbase_undefined; | |
480 | ||
481 | llassert (cttab.size == 0); | |
482 | ||
483 | /* do for plain, pointer, arrayof */ | |
484 | for (i = CTK_PLAIN; i <= CTK_ARRAY; i++) | |
485 | { | |
486 | for (j = CTX_UNKNOWN; j <= CTX_LAST; j++) | |
487 | { | |
488 | if (i == CTK_PLAIN) | |
489 | { | |
490 | if (j == CTX_BOOL) | |
491 | { | |
492 | ct = ctbase_createBool (); /* why different? */ | |
493 | } | |
494 | else if (j == CTX_UNKNOWN) | |
495 | { | |
496 | ct = ctbase_createUnknown (); | |
497 | } | |
498 | else | |
499 | { | |
500 | ct = ctbase_createPrim ((cprim)j); | |
501 | } | |
502 | ||
503 | (void) cttable_addFull | |
504 | (ctentry_make (CTK_PLAIN, | |
505 | ct, ctype_undefined, | |
506 | j + CTK_PREDEFINED, j + CTK_PREDEFINED2, | |
507 | ctbase_unparse (ct))); | |
508 | } | |
509 | else | |
510 | { | |
511 | switch (i) | |
512 | { | |
513 | case CTK_PTR: | |
514 | ct = ctbase_makePointer (j); | |
515 | /*@switchbreak@*/ break; | |
516 | case CTK_ARRAY: | |
517 | ct = ctbase_makeArray (j); | |
518 | /*@switchbreak@*/ break; | |
519 | default: | |
520 | llbugexitlit ("cttable_init: base case"); | |
521 | } | |
522 | ||
523 | (void) cttable_addDerived (i, ct, j); | |
524 | } | |
525 | } | |
526 | } | |
527 | ||
528 | /**** reserve a slot for userBool ****/ | |
529 | (void) cttable_addFull (ctentry_make (CTK_INVALID, ctbase_undefined, | |
530 | ctype_undefined, ctype_dne, ctype_dne, | |
531 | cstring_undefined)); | |
532 | } | |
533 | ||
534 | /*@noaccess cprim@*/ | |
535 | ||
536 | static void | |
537 | cttable_grow () | |
538 | { | |
539 | int i; | |
540 | o_ctentry *newentries ; | |
541 | ||
542 | cttab.nspace = CTK_BASESIZE; | |
543 | newentries = (ctentry *) dmalloc (sizeof (*newentries) * (cttab.size + cttab.nspace)); | |
544 | ||
545 | if (newentries == NULL) | |
546 | { | |
547 | llfatalerror (message ("cttable_grow: out of memory. Size: %d", | |
548 | cttab.size)); | |
549 | } | |
550 | ||
551 | for (i = 0; i < cttab.size; i++) | |
552 | { | |
553 | newentries[i] = cttab.entries[i]; | |
554 | } | |
555 | ||
556 | /*@-compdestroy@*/ | |
557 | sfree (cttab.entries); | |
558 | /*@=compdestroy@*/ | |
559 | ||
560 | cttab.entries = newentries; | |
561 | /*@-compdef@*/ | |
562 | } /*@=compdef@*/ | |
563 | ||
564 | static ctype | |
565 | cttable_addDerived (ctkind ctk, /*@keep@*/ ctbase cnew, ctype base) | |
566 | { | |
567 | if (cttab.nspace == 0) | |
568 | cttable_grow (); | |
569 | ||
570 | cttab.entries[cttab.size] = | |
571 | ctentry_make (ctk, cnew, base, ctype_dne, ctype_dne, cstring_undefined); | |
572 | ||
573 | cttab.nspace--; | |
574 | ||
575 | return (cttab.size++); | |
576 | } | |
577 | ||
578 | static ctype | |
579 | cttable_addComplex (/*@only@*/ /*@notnull@*/ ctbase cnew) | |
580 | /*@modifies cttab; @*/ | |
581 | { | |
582 | if (cnew->type != CT_FCN && cnew->type != CT_EXPFCN) | |
583 | { | |
584 | ctype i; | |
585 | int ctstop = cttable_lastIndex () - DEFAULT_OPTLEVEL; | |
586 | ||
587 | if (ctstop < LAST_PREDEFINED) | |
588 | { | |
589 | ctstop = LAST_PREDEFINED; | |
590 | } | |
591 | ||
592 | for (i = cttable_lastIndex (); i >= ctstop; i--) /* better to go from back... */ | |
593 | { | |
594 | ctbase ctb; | |
595 | ||
885824d3 | 596 | ctb = ctype_getCtbase (i); |
597 | ||
598 | if (ctbase_isDefined (ctb) && ctbase_equivStrict (cnew, ctb)) | |
599 | { | |
a0a162cd | 600 | DPRINTF (("EQUIV!! %s / %s", |
601 | ctbase_unparse (cnew), | |
602 | ctbase_unparse (ctb))); | |
885824d3 | 603 | ctbase_free (cnew); |
885824d3 | 604 | return i; |
605 | } | |
606 | } | |
607 | } | |
608 | ||
609 | if (cttab.nspace == 0) | |
610 | cttable_grow (); | |
611 | ||
612 | cttab.entries[cttab.size] = ctentry_make (CTK_COMPLEX, cnew, ctype_undefined, | |
613 | ctype_dne, ctype_dne, | |
614 | cstring_undefined); | |
615 | cttab.nspace--; | |
616 | ||
617 | return (cttab.size++); | |
618 | } | |
619 | ||
620 | static ctype | |
621 | cttable_addFull (ctentry cnew) | |
622 | { | |
623 | if (cttab.nspace == 0) | |
624 | { | |
625 | cttable_grow (); | |
626 | } | |
627 | ||
628 | cttab.entries[cttab.size] = cnew; | |
629 | cttab.nspace--; | |
630 | ||
631 | return (cttab.size++); | |
632 | } | |
633 | ||
634 | static ctype | |
635 | cttable_addFullSafe (/*@only@*/ ctentry cnew) | |
636 | { | |
637 | int i; | |
638 | ctbase cnewbase = cnew->ctbase; | |
639 | ||
640 | llassert (ctbase_isDefined (cnewbase)); | |
641 | ||
642 | for (i = cttable_lastIndex (); i >= CT_FIRST; i--) | |
643 | { | |
644 | ctbase ctb = ctype_getCtbase (i); | |
645 | ||
646 | if (ctbase_isDefined (ctb) | |
647 | && ctbase_equiv (cnewbase, ctype_getCtbaseSafe (i))) | |
648 | { | |
649 | ctentry_free (cnew); | |
650 | return i; | |
651 | } | |
652 | } | |
653 | ||
654 | if (cttab.nspace == 0) | |
655 | cttable_grow (); | |
656 | ||
657 | cttab.entries[cttab.size] = cnew; | |
658 | ||
659 | cttab.nspace--; | |
660 | ||
661 | return (cttab.size++); | |
662 | } | |
663 |