]> andersk Git - splint.git/blob - src/ctbase.i
5e3d374b02999ce27059f533e00114b21462706c
[splint.git] / src / ctbase.i
1 /* ;-*-C-*-; 
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 splint: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** ctbase.i
26 **
27 ** NOTE: This is not a stand-alone source file, but is included in ctype.c.
28 **       (This is necessary because there is no other way in C to have a
29 **       hidden scope, besides at the file level.)
30 */
31
32 /*@access cprim*/
33
34 abst_typedef /*@null@*/ struct s_ctbase *ctbase;
35
36 /*@private@*/ typedef struct {
37   ctkind kind;
38   ctbase ctbase; 
39   ctype base;     /* type I point to (or element of array) */
40   ctype ptr;     /* type of pointer to me */
41   ctype array;    /* type of array of me */
42   cstring unparse; /* unparse me, if memoized */
43 } *ctentry ;
44
45 typedef /*@only@*/ ctentry o_ctentry;
46           
47 typedef struct {
48   int size;
49   int nspace;
50   /*@relnull@*/ /*@only@*/ o_ctentry *entries;
51   /* memoize matches...maybe in context? */
52 } cttable ;
53
54 extern bool ctentry_isBogus (/*@sef@*/ ctentry p_c) /*@*/;
55 # define ctentry_isBogus(c) \
56    ((c)->kind == CTK_INVALID || (c)->kind == CTK_DNE)
57
58 static cttable cttab = { 0, 0, NULL };
59
60 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createAbstract (typeId p_u);
61 static /*@observer@*/ cstring ctentry_doUnparse (ctentry p_c) /*@modifies p_c@*/;
62 static /*@only@*/ ctentry
63   ctentry_make (ctkind p_ctk, /*@keep@*/ ctbase p_c, ctype p_base, 
64                 ctype p_ptr, ctype p_array, /*@keep@*/ cstring p_unparse);
65 static /*@only@*/ ctentry ctentry_makeNew (ctkind p_ctk, /*@only@*/ ctbase p_c);
66 static /*@only@*/ cstring ctentry_unparse (ctentry p_c) /*@*/ ;
67
68 static void cttable_grow (void);
69 static ctype cttable_addDerived (ctkind p_ctk, /*@keep@*/ ctbase p_cnew, ctype p_base);
70 static ctype cttable_addFull (/*@keep@*/ ctentry p_cnew);
71 static bool ctentry_isInteresting (ctentry p_c) /*@*/;
72 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeFixedArray (ctype p_b, size_t p_size) /*@*/ ;
73 static bool ctbase_isAnytype (/*@notnull@*/ ctbase p_b) /*@*/ ;
74
75 /* 
76 ** These are file-static macros (used in ctype.c).  No way to
77 ** declare them as static in C.
78 */
79
80 /*@-allmacros@*/ /*@-macrospec@*/ /*@-namechecks@*/
81 # define ctentry_getBase(c)       ((c)->base)
82 # define ctentry_getKind(c)       ((c)->kind)
83 # define ctentry_getArray(c)      ((c)->array)
84 # define ctentry_getPtr(c)        ((c)->ptr)
85 # define ctentry_isArray(c)       ((c)->kind == CTK_ARRAY)
86 # define ctentry_isComplex(c)     ((c)->kind == CTK_COMPLEX)
87 # define ctentry_isPlain(c)       ((c)->kind == CTK_PLAIN)
88 # define ctentry_isPointer(c)     ((c)->kind == CTK_PTR)
89 # define ctentry_setArray(c,b)    ((c)->array = (b))
90 # define ctentry_setPtr(c,b)      ((c)->ptr = (b))
91
92 # define ctbase_fixUser(c)        (c = ctbase_realType(c))
93 /*@=allmacros@*/ /*@=macrospec@*/ /*@=namechecks@*/
94
95 static ctype cttable_addComplex (/*@notnull@*/ /*@only@*/ ctbase p_cnew);
96 static /*@observer@*/ ctbase ctype_getCtbase (ctype p_c) /*@*/ ;
97 static ctype ctype_makeConjAux (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
98 static /*@notnull@*/ /*@observer@*/ ctbase ctype_getCtbaseSafe (ctype p_c) /*@*/ ;
99 static /*@observer@*/ ctentry ctype_getCtentry (ctype p_c)  /*@*/ ;
100 static /*@observer@*/ /*@notnull@*/ ctbase 
101   ctbase_realType (/*@notnull@*/ ctbase p_c) /*@*/ ;
102 static bool ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
103 static bool ctbase_isEitherArray (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
104 static /*@observer@*/ enumNameList ctbase_elist (ctbase p_c) /*@*/ ;
105 static /*@only@*/ cstring ctbase_unparse (ctbase p_c) /*@*/ ;
106 static /*@only@*/ cstring ctbase_unparseDeep (ctbase p_c) /*@*/ ;
107 static /*@only@*/ /*@notnull@*/ ctbase ctbase_copy (/*@notnull@*/ ctbase p_c) /*@*/ ;
108 static void ctbase_free (/*@only@*/ ctbase p_c);
109 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createPrim (cprim p_p) /*@*/ ;
110 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createBool (void) /*@*/ ;
111 static /*@notnull@*/ /*@observer@*/ ctbase ctbase_getBool (void) /*@*/ ;
112 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUser (typeId p_u) /*@*/ ;
113
114 static /*@notnull@*/ /*@only@*/ ctbase
115   ctbase_createStruct (/*@only@*/ cstring p_n, /*@only@*/ uentryList p_f);
116
117 static /*@notnull@*/ /*@only@*/ ctbase 
118   ctbase_createUnion  (/*@keep@*/ cstring p_n, /*@only@*/ uentryList p_f);
119 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createEnum (/*@keep@*/ cstring p_etag, /*@keep@*/ enumNameList p_emembers);
120 static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUnknown (void);
121 static bool ctbase_match (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
122 static bool ctbase_matchDef (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
123 static bool ctbase_genMatch (ctbase p_c1, ctbase p_c2, bool p_force, bool p_arg, bool p_def, bool p_deep);
124 static bool ctbase_isAbstract (/*@notnull@*/ ctbase p_c) /*@*/ ;
125 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makePointer (ctype p_b) /*@*/ ;
126 static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeArray (ctype p_b) /*@*/ ;
127 static /*@notnull@*/ ctype 
128   ctbase_makeFunction (ctype p_b, /*@only@*/ uentryList p_p) /*@*/ ;
129 static /*@notnull@*/ /*@observer@*/ ctbase 
130   ctbase_realFunction (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
131 static ctype ctbase_baseArrayPtr (/*@notnull@*/ ctbase p_c) /*@*/ ;
132 static ctype ctbase_baseFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
133 static /*@observer@*/ uentryList ctbase_argsFunction (/*@notnull@*/ ctbase p_c) /*@*/ ;
134 static /*@observer@*/ uentryList ctbase_getuentryList (/*@notnull@*/ ctbase p_c) /*@*/ ;
135 static ctype ctbase_newBase (ctype p_c, ctype p_p) /*@*/ ;
136 static ctype ctbase_newBaseExpFcn (ctype p_c, ctype p_p) /*@*/ ;
137 static bool ctbase_isFixedArray (/*@notnull@*/ ctbase p_c) /*@*/ ;
138
139 /*@-macroundef@*/
140 extern int cttable_lastIndex();
141 # define cttable_lastIndex()  (cttab.size - 1)
142 /*@=macroundef@*/
143
144 typedef struct
145 {
146   ctype rval;
147   /*@only@*/ uentryList params; 
148 } *cfcn; 
149
150 typedef struct
151 {
152   cstring   name;
153   uentryList fields;
154 } *tsu;
155
156 typedef struct
157 {
158   ctype a;
159   ctype b;
160   bool  isExplicit;
161 } *tconj;
162
163 typedef struct
164 {
165   cstring      tag;
166   enumNameList members;
167 } *tenum;
168
169 typedef struct
170 {
171   ctype base;
172   size_t size;
173 } *tfixed;
174  
175 typedef union 
176 {
177   cprim         prim;      /* primitive */
178   typeId        tid;       /* abstract, user */
179   ctype         base;      /* ptr, array */
180   cfcn          fcn;       /* function     */
181   tsu           su;        /* struct union */
182   tenum         cenum;     /* enum */
183   tconj         conj;      /* conj */
184   tfixed        farray;    /* fixed array */
185 } uconts;
186
187 struct s_ctbase
188 {
189   ctuid    type;
190   uconts   contents;
191 } ;
192
193 static /*@falsenull@*/ bool ctbase_isUA (ctbase p_c) /*@*/ ;
194 static bool ctbase_isBaseUA(ctbase p_c) /*@*/ ;
195 static typeId  ctbase_typeBaseUid(ctbase p_c) /*@*/ ;
196 static bool ctbase_isKind (/*@notnull@*/ ctbase p_c, ctuid p_kind) /*@*/ ;
197 static bool ctbase_isKind2 (/*@notnull@*/ ctbase p_c, ctuid p_kind1, ctuid p_kind2) /*@*/ ;
198 static /*@only@*/ /*@notnull@*/ ctbase 
199   ctbase_getBaseType (/*@notnull@*/ ctbase p_c) /*@*/ ;
200
201 static /*@falsenull@*/ bool ctbase_isFunction(ctbase p_c) /*@*/ ;
202
203 /*@constant null ctbase ctbase_undefined; @*/
204 # define ctbase_undefined        ((ctbase)0)
205
206 static /*@owned@*/ ctbase ctbase_bool = ctbase_undefined;
207 static /*@owned@*/ ctbase ctbase_unknown = ctbase_undefined;
208
209 static /*@falsenull@*/ bool ctbase_isDefined (ctbase c) /*@*/
210 {
211   return ((c) != ctbase_undefined);
212 }
213
214 static /*@truenull@*/ bool ctbase_isUndefined (ctbase c)
215 {
216   return ((c) == ctbase_undefined);
217 }
218
219 static ctkind ctype_getCtKind (ctype c)
220 {
221   ctentry ce = ctype_getCtentry (c);
222
223   return ctentry_getKind (ce);
224 }
225
226 static bool ctbase_isUser (ctbase c)
227 {
228   if (ctbase_isDefined (c))
229     {
230       return (ctbase_isKind (c, CT_USER));
231     }
232   else
233     {
234       return FALSE;
235     }
236 }
237
238 static bool ctbase_isEnum (ctbase c)
239 {
240   if (ctbase_isDefined (c))
241     {
242       return (ctbase_isKind (c, CT_ENUM));
243     }
244   else
245     {
246       return FALSE;
247     }
248 }
249
250 static bool ctbase_isExpFcn (ctbase c)
251 {
252   if (ctbase_isDefined (c))
253     {
254       return (c->type == CT_EXPFCN);
255     }
256   else
257     {
258       return FALSE;
259     }
260 }
261
262 static /*@falsenull@*/ bool ctbase_isConj (ctbase c)
263 {
264   if (ctbase_isDefined (c))
265     {
266       return (c->type == CT_CONJ);
267     }
268   else
269     {
270       return FALSE;
271     }
272 }
273
274 static bool ctuid_isAP (ctuid c) /*@*/ 
275 {
276   return (c == CT_ARRAY || c == CT_PTR);
277 }
278
279 static typeId ctbase_typeId (ctbase p_c);
280 static /*@only@*/ cstring ctbase_dump (ctbase p_c);
281 static /*@only@*/ ctbase ctbase_undump (char **p_c) /*@requires maxRead(*p_c) >= 2 @*/;
282 static int ctbase_compare (ctbase p_c1, ctbase p_c2, bool p_strict);
283 static bool ctbase_matchArg (ctbase p_c1, ctbase p_c2);
284 static /*@notnull@*/ /*@only@*/ ctbase 
285   ctbase_makeConj (ctype p_c1, ctype p_c2, bool p_isExplicit) /*@*/ ;
286 static ctype ctbase_getConjA (/*@notnull@*/ ctbase p_c) /*@*/ ;
287 static ctype ctbase_getConjB (/*@notnull@*/ ctbase p_c) /*@*/ ;
288 static bool ctbase_isExplicitConj (/*@notnull@*/ ctbase p_c) /*@*/ ;
289 static bool ctbase_forceMatch (ctbase p_c1, ctbase p_c2) /*@modifies p_c1, p_c2@*/ ;
290 static /*@notnull@*/ /*@only@*/ ctbase ctbase_expectFunction (ctype p_c);
291 static bool ctbase_isVoidPointer(/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
292 static bool ctbase_isUnion (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
293 static bool ctbase_isStruct (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
294 static /*@observer@*/ cstring ctbase_enumTag (/*@notnull@*/ ctbase p_ct) /*@*/ ;
295 static /*@only@*/ cstring ctbase_unparseNotypes (ctbase p_c) /*@*/ ;
296
297 static /*@out@*/ /*@notnull@*/ /*@only@*/ ctbase ctbase_new (void) /*@*/ ;
298 static int nctbases = 0;
299
300 static /*@notnull@*/ /*@only@*/ 
301   ctbase ctbase_makeLiveFunction (ctype p_b, /*@only@*/ uentryList p_p);
302
303 static bool ctbase_isUnnamedSU (ctbase c)
304 {
305   return (ctbase_isDefined (c)
306           && (ctbase_isStruct (c) || ctbase_isUnion (c))
307           && isFakeTag (c->contents.su->name));
308 }
309
310 static /*@observer@*/ ctbase ctbase_realType (ctbase c)
311 {
312   if (ctbase_isUA (c))
313     {
314       typeId uid = ctbase_typeId (c);
315
316       if (usymtab_isBoolType (uid))
317         {
318           return ctbase_getBool ();
319         }
320       else
321         {
322           ctbase ret = ctype_getCtbase 
323             (uentry_getRealType (usymtab_getTypeEntry (ctbase_typeId (c))));
324           
325           llassert (ret != ctbase_undefined);
326           return ret;
327         }
328     }
329   else
330     {
331       return c;
332     }
333 }
334
335 static bool
336 ctbase_isVoidPointer (/*@dependent@*/ /*@notnull@*/ ctbase c)
337 {
338   ctbase r = ctbase_realType (c);
339
340   return (ctbase_isKind (r, CT_PTR) &&
341           ctype_isVoid (r->contents.base));
342 }
343
344 static bool
345 ctbase_isPointer (/*@notnull@*/ /*@dependent@*/ ctbase c)
346 {
347   ctbase r = ctbase_realType (c);
348
349   return (ctbase_isKind (r, CT_PTR));
350 }
351
352 static bool
353 ctbase_isEitherArray (/*@notnull@*/ ctbase c)
354 {
355   ctbase r = ctbase_realType (c);
356
357   return (ctbase_isKind (r, CT_ARRAY)
358           || ctbase_isKind (r, CT_FIXEDARRAY));
359 }
360
361 static bool
362 ctbase_isFixedArray (/*@notnull@*/ ctbase c)
363 {
364   ctbase r = ctbase_realType (c);
365
366   return (ctbase_isKind (r, CT_FIXEDARRAY));
367 }
368
369 static bool
370 ctbase_isStruct (/*@notnull@*/ ctbase c)
371 {
372   ctbase r = ctbase_realType (c);
373
374   return (ctbase_isKind (r, CT_STRUCT));
375 }
376
377 static bool
378 ctbase_isUnion (/*@notnull@*/ ctbase c)
379 {
380   ctbase r = ctbase_realType (c);
381
382   return (ctbase_isKind (r, CT_UNION));
383 }
384
385 /*
386 ** clean this up -> typeTable should store ctype
387 */
388
389 static typeId
390 ctbase_typeBaseUid (ctbase c)
391 {
392   ctuid ct;
393
394   if (ctbase_isDefined (c))
395     {
396       ct = c->type;
397
398       if (ctuid_isAP (ct))
399         {
400           return ctbase_typeBaseUid (ctype_getCtbase (c->contents.base));
401         }
402       else if (ct == CT_USER || ct == CT_ABST)
403         {
404           return c->contents.tid;
405         }
406       else if (ct == CT_FIXEDARRAY)
407         {
408           return ctbase_typeBaseUid (ctype_getCtbase (c->contents.farray->base));
409         }
410       else
411         {
412           llcontbuglit ("ctbase_typeBaseUid: bad call");
413           return typeId_invalid;
414         }
415     }
416   return typeId_invalid;
417 }
418
419 static bool
420 ctbase_isBaseUA (ctbase c)
421 {
422   ctuid ct;
423
424   if (ctbase_isDefined (c))
425     {
426       ct = c->type;
427
428       if (ctuid_isAP (ct))
429         {
430           return ctbase_isBaseUA (ctype_getCtbase (c->contents.base));
431         }
432       else if (ct == CT_FIXEDARRAY)
433         {
434           return ctbase_isBaseUA (ctype_getCtbase (c->contents.farray->base));
435         }
436       else
437         return (ct == CT_USER || ct == CT_ABST);
438     }
439   return FALSE;
440 }
441
442 static typeId
443 ctbase_typeId (ctbase c)
444 {
445   if (ctbase_isUA (c))
446     {
447       return c->contents.tid;
448     }
449   else
450     {
451       if (ctbase_isConj (c)) 
452         {
453           return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
454         }
455       else
456         {
457           llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
458           return typeId_invalid;
459         }
460     }
461 }
462
463 static /*@only@*/ cstring
464 ctbase_unparse (ctbase c)
465 {
466   if (ctbase_isUndefined (c)) {
467     return cstring_makeLiteral ("<<undef>>");
468   }
469   
470   switch (c->type)
471     {
472     case CT_UNKNOWN:
473       return cstring_makeLiteral ("?");
474     case CT_BOOL:
475       return cstring_copy (context_printBoolName ());
476     case CT_PRIM:
477       return (cprim_unparse (c->contents.prim));
478     case CT_USER:
479       return (usymtab_getTypeEntryName (c->contents.tid));
480     case CT_ABST:
481       return (usymtab_getTypeEntryName (c->contents.tid));
482     case CT_EXPFCN:
483       return (message ("<expf: %t>", c->contents.base));
484     case CT_PTR:
485       /* no spaces for multiple pointers */
486
487       if (ctype_isPointer (c->contents.base))
488         {
489           return (cstring_appendChar (cstring_copy (ctype_unparse (c->contents.base)), '*'));
490         }
491       else
492         {
493           return (message ("%t *", c->contents.base));
494         }
495     case CT_FIXEDARRAY:
496       return (message ("%t [%d]", 
497                        c->contents.farray->base, 
498                        (int) c->contents.farray->size));
499     case CT_ARRAY:
500       return (message ("%t []", c->contents.base));
501     case CT_FCN:
502       return (message ("[function (%q) returns %t]",
503                        uentryList_unparseParams (c->contents.fcn->params),
504                        c->contents.fcn->rval));
505     case CT_STRUCT:
506       if (cstring_isDefined (c->contents.su->name) &&
507           !cstring_isEmpty (c->contents.su->name) &&
508           !isFakeTag (c->contents.su->name))
509         {
510           return (message ("struct %s", c->contents.su->name));
511         }
512       else
513         {
514           return (message ("struct { %q }", 
515                            uentryList_unparseAbbrev (c->contents.su->fields))); 
516         }
517     case CT_UNION:
518       if (cstring_isDefined (c->contents.su->name) &&
519           !cstring_isEmpty (c->contents.su->name) &&
520           !isFakeTag (c->contents.su->name))
521         {
522           return (message ("union %s", c->contents.su->name));
523         }
524       else
525         {
526           return (message ("union { %q }", 
527                            uentryList_unparseAbbrev (c->contents.su->fields)));
528         }
529     case CT_ENUM:
530       if (isFakeTag (c->contents.cenum->tag))
531         {
532           return (message ("enum { %q }", 
533                            enumNameList_unparseBrief (c->contents.cenum->members)));
534         }
535       else
536         {
537           return (message ("enum %s { %q }", 
538                            c->contents.cenum->tag,
539                            enumNameList_unparseBrief (c->contents.cenum->members)));
540         }
541     case CT_CONJ:
542       if (ctbase_isAnytype (c))
543         {
544           return (cstring_makeLiteral ("<any>"));
545         }
546       else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
547         {
548           if (!ctype_isSimple (c->contents.conj->a) ||
549               !ctype_isSimple (c->contents.conj->b))
550             {
551               return (message ("<%t> | <%t>", c->contents.conj->a, c->contents.conj->b));
552             }
553           else
554             {
555               return (message ("%t | %t", c->contents.conj->a, c->contents.conj->b));
556             }
557         }
558       else
559         {
560           return (cstring_copy (ctype_unparse (c->contents.conj->a)));
561         }
562     BADDEFAULT;
563     }
564   BADEXIT;
565 }
566
567 static /*@only@*/ cstring
568   ctbase_unparseDeep (ctbase c)
569 {
570   if (ctbase_isUndefined (c))
571     {
572       return cstring_makeLiteral ("<<undef>>");
573     }
574
575   switch (c->type)
576     {
577     case CT_UNKNOWN:
578       return cstring_makeLiteral ("?");
579     case CT_BOOL:
580       return cstring_copy (context_printBoolName ());
581     case CT_PRIM:
582       return (cprim_unparse (c->contents.prim));
583     case CT_ENUM:
584       if (cstring_isNonEmpty (c->contents.cenum->tag))
585         {
586           return (message ("enum %s { %q }",
587                            c->contents.cenum->tag,
588                            enumNameList_unparse (c->contents.cenum->members)));
589         }
590       else
591         {
592           return (message ("enum { %q }",
593                            enumNameList_unparse (c->contents.cenum->members)));
594         }
595     case CT_USER:
596       return (usymtab_getTypeEntryName (c->contents.tid));
597     case CT_ABST:
598       return (usymtab_getTypeEntryName (c->contents.tid));
599     case CT_EXPFCN:
600       return (message ("<expf: %t>", c->contents.base));
601     case CT_PTR:
602       return (message ("%t *", c->contents.base));
603     case CT_FIXEDARRAY:
604       return (message ("%t [%d]", c->contents.farray->base, 
605                        (int) c->contents.farray->size));
606     case CT_ARRAY:
607       return (message ("%t []", c->contents.base));
608     case CT_FCN:
609       return (message ("[function (%q) returns %t]",
610                        uentryList_unparse (c->contents.fcn->params),
611                        c->contents.fcn->rval));
612     case CT_STRUCT:
613       return (message ("struct %s { ... } ", c->contents.su->name));
614     case CT_UNION:
615       return (message ("union %s { ... }", c->contents.su->name));
616     case CT_CONJ:
617       if (ctbase_isAnytype (c))
618         {
619           return (cstring_makeLiteral ("<any>"));
620         }
621       else
622         {
623           return (message ("%t", c->contents.conj->a));
624         }
625     BADDEFAULT;
626     }
627   BADEXIT;
628 }
629
630 static /*@only@*/ cstring
631 ctbase_unparseNotypes (ctbase c)
632 {
633   llassert (ctbase_isDefined (c));
634
635   switch (c->type)
636     {
637     case CT_UNKNOWN:
638       return cstring_makeLiteral ("?");
639     case CT_BOOL:
640       return cstring_copy (context_printBoolName ());
641     case CT_PRIM:
642       return (cprim_unparse (c->contents.prim));
643     case CT_ENUM:
644       if (typeId_isInvalid (c->contents.tid))
645         {
646           return cstring_makeLiteral ("enum");
647         }
648       else
649         {
650           return (message ("T#%d", c->contents.tid));
651         }
652     case CT_USER:
653       return (message ("uT#%d", c->contents.tid));
654     case CT_ABST:
655       return (message ("aT#%d", c->contents.tid));
656     case CT_EXPFCN:
657       return (message ("<expf: %q >", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
658     case CT_PTR:
659       return (message ("%q  *", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
660     case CT_ARRAY:
661       return (message ("%q []", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
662     case CT_FCN:
663       return (message ("[function (%d) returns %q]", uentryList_size (c->contents.fcn->params),
664                        ctbase_unparseNotypes (ctype_getCtbase (c->contents.fcn->rval))));
665     case CT_STRUCT:
666       return (message ("struct %s", c->contents.su->name));
667     case CT_UNION:
668       return (message ("union %s", c->contents.su->name));
669     case CT_ENUMLIST:
670       return (message ("[enumlist]"));
671     case CT_CONJ:
672       if (ctbase_isAnytype (c))
673         {
674           return (cstring_makeLiteral ("<any>"));
675         }
676       else
677         {
678           return (message ("%q/%q", 
679                            ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->a)),
680                            ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->b))));
681         }
682     BADDEFAULT;
683     }
684   BADEXIT;
685 }
686
687 static /*@only@*/ cstring
688 ctbase_unparseDeclaration (ctbase c, /*@only@*/ cstring name) /*@*/ 
689 {
690   if (ctbase_isUndefined (c))
691     {
692       return name;
693     }
694   
695   switch (c->type)
696     {
697     case CT_UNKNOWN:
698       return (message ("? %q", name));
699     case CT_BOOL:
700       return (message ("%s %q", context_printBoolName (), name));
701     case CT_PRIM:
702       return (message ("%q %q", cprim_unparse (c->contents.prim), name));
703     case CT_USER:
704     case CT_ABST:
705       return (message ("%q %q", usymtab_getTypeEntryName (c->contents.tid), name));
706     case CT_EXPFCN:
707       llcontbuglit ("ctbase_unparseDeclaration: expfcn");
708       return name;
709     case CT_PTR:
710       if (ctype_isFunction (c->contents.base))
711         {
712           return ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name);
713         }
714       else
715         {
716           cstring s = cstring_prependChar ('*', name);
717           cstring ret = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), s);
718           cstring_free (name);
719           return (ret);
720         }
721     case CT_FIXEDARRAY:
722       return (message ("%q[%d]", 
723                        ctbase_unparseDeclaration (ctype_getCtbase (c->contents.farray->base), name),
724                        (int) c->contents.farray->size));
725     case CT_ARRAY:
726       return (message ("%q[]", 
727                        ctbase_unparseDeclaration (ctype_getCtbase (c->contents.base), name)));
728     case CT_FCN:
729         {
730           cstring s = message ("%q(%q)", name, 
731                                uentryList_unparseParams (c->contents.fcn->params));
732
733           return (ctbase_unparseDeclaration 
734                   (ctype_getCtbase (c->contents.fcn->rval), s));
735         }
736     case CT_STRUCT:
737       if (cstring_isDefined (c->contents.su->name) &&
738           !cstring_isEmpty (c->contents.su->name) &&
739           !isFakeTag (c->contents.su->name))
740         {
741           return (message ("struct %s %q", c->contents.su->name, name));
742         }
743       else
744         {
745           return (message ("struct { %q } %q", 
746                            uentryList_unparseAbbrev (c->contents.su->fields),
747                            name));
748         }
749     case CT_UNION:
750       if (cstring_isDefined (c->contents.su->name) &&
751           !cstring_isEmpty (c->contents.su->name) &&
752           !isFakeTag (c->contents.su->name))
753         {
754           return (message ("union %s %q", c->contents.su->name, name));
755         }
756       else
757         {
758           return (message ("union { %q } %q", 
759                            uentryList_unparseAbbrev (c->contents.su->fields),
760                            name));
761         }
762     case CT_ENUM:
763       if (isFakeTag (c->contents.cenum->tag))
764         {
765           return (message ("enum { %q } %q", 
766                            enumNameList_unparseBrief (c->contents.cenum->members),
767                            name));
768         }
769       else
770         {
771           return (message ("enum %s { %q } %q", 
772                            c->contents.cenum->tag,
773                            enumNameList_unparseBrief (c->contents.cenum->members),
774                            name));
775         }
776     case CT_CONJ:
777       if (ctbase_isAnytype (c))
778         {
779           return (message ("<any> %q", name));
780         }
781       else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
782         {
783           if (!ctype_isSimple (c->contents.conj->a) ||
784               !ctype_isSimple (c->contents.conj->b))
785             {
786               cstring name1 = cstring_copy (name);
787
788               return 
789                 (message 
790                  ("<%q> | <%q>", 
791                   ctbase_unparseDeclaration 
792                   (ctype_getCtbase (c->contents.conj->a), name1),
793                   ctbase_unparseDeclaration 
794                   (ctype_getCtbase (c->contents.conj->b), name)));
795             }
796           else
797             {
798               cstring s1 = ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->a), 
799                                                       cstring_copy (name));
800               return
801                 (message ("%q | %q", s1, 
802                           ctbase_unparseDeclaration (ctype_getCtbase (c->contents.conj->b),
803                                                      name)));
804             }
805         }
806       else
807         {
808           cstring_free (name);
809           return (cstring_copy (ctype_unparse (c->contents.conj->a)));
810         }
811       BADDEFAULT;
812     }
813   BADEXIT;
814 }
815
816 static ctbase ctbase_undump (d_char *c) /*@requires maxRead(*c) >= 2 @*/
817 {
818   ctbase res;
819   char p = **c;
820
821   (*c)++;
822
823   switch (p)
824     {
825     case '?':
826       return (ctbase_undefined);
827     case 'u':
828       return (ctbase_createUnknown ());
829     case 'b':
830       return (ctbase_createBool ());
831     case 'p':
832       res = ctbase_createPrim (cprim_fromInt (reader_getInt (c)));
833       reader_checkChar (c, '|');
834       return res;
835     case 's':
836       res = ctbase_createUser (typeId_fromInt (reader_getInt (c)));
837       reader_checkChar (c, '|');
838       return res;
839     case 'a':
840       res = ctbase_createAbstract (typeId_fromInt (reader_getInt (c)));
841       reader_checkChar (c, '|');
842       return res;
843     case 't':
844       res = ctbase_makePointer (ctype_undump (c));
845       reader_checkChar (c, '|');
846       return res;
847     case 'y':
848       res = ctbase_makeArray (ctype_undump (c));
849       reader_checkChar (c, '|');
850       return res;
851     case 'F':
852       {
853         ctype ct = ctype_undump (c);
854         size_t size;
855
856         reader_checkChar (c, '/');
857         size = size_fromInt (reader_getInt (c));
858         reader_checkChar (c, '|');
859         return (ctbase_makeFixedArray (ct, size));
860       }
861     case 'f':
862       {
863         ctype ct;
864         char *lp = strchr (*c, '(');
865
866         llassertfatal (lp != NULL);
867
868         *lp = '\0';
869         ct = ctype_undump (c);
870         *c = lp + 1;
871
872         return (ctbase_makeLiveFunction (ct, uentryList_undump (c)));
873       }
874     case 'S':
875       {
876         uentryList fields;
877         ctbase ctb;
878         char *sname;
879         char *lc = strchr (*c, '{');
880
881         llassert (lc != NULL);
882         *lc = '\0';
883
884         sname = mstring_copy (*c);
885
886         *c = lc + 1;
887
888         if (*sname == '!')
889           {
890             unsigned int i;
891
892             i = (unsigned) atoi (sname + 1);
893
894             setTagNo (i);
895           }
896
897         fields = uentryList_undumpFields (c, g_currentloc);
898
899         ctb = ctbase_createStruct (cstring_fromCharsO (sname), fields);
900         return ctb;
901       }
902     case 'U':
903       {
904         char *sname;
905         char *lc = strchr (*c, '{');
906
907         llassert (lc != NULL);
908
909         *lc = '\0';
910         sname = mstring_copy (*c);
911         llassert (sname != NULL);
912
913         *c = lc + 1;
914
915         if (*sname == '!')
916           {
917             unsigned int i;
918
919             i = (unsigned) atoi (sname + 1);
920             setTagNo (i);
921           }
922
923         return (ctbase_createUnion (cstring_fromCharsO (sname),
924                                     uentryList_undumpFields (c, g_currentloc)));
925       }
926     case 'e':
927       {
928         ctbase ret;
929         char *sname;
930         char *lc = strchr (*c, '{');
931
932         llassert (lc != NULL);
933
934         *lc = '\0';
935         sname = mstring_copy (*c);
936         *c = lc + 1;
937
938         if (*sname == '!')
939           {
940             unsigned int i;
941
942             i = (unsigned) atoi (sname + 1);
943             setTagNo (i);
944           }
945
946         ret = ctbase_createEnum (cstring_fromCharsO (sname),
947                                  enumNameList_undump (c));
948         return ret;
949       }
950     case 'C':
951       {
952         bool isExplicit;
953         ctype c1, c2;
954
955         isExplicit = bool_fromInt (reader_getInt (c));
956         reader_checkChar (c, '.');
957         c1 = ctype_undump (c);
958         reader_checkChar (c, '/');
959         c2 = ctype_undump (c);
960         reader_checkChar (c, '|');
961
962         return (ctbase_makeConj (c1, c2, isExplicit));
963       }
964
965     default:
966       (*c)--;
967       llerror (FLG_SYNTAX, 
968                message ("Bad Library line (type): %s", cstring_fromChars (*c)));
969
970   /*drl bee: pbr*/      while (**c != '\0')
971         {
972           (*c)++;
973         }
974
975       return ctbase_createUnknown ();
976     }
977 }
978
979 /* first letter of c encodes type:     */
980 /*    u  unknown                       */
981 /*    b  bool                          */
982 /*    p  prim                          */
983 /*    e  enum                          */
984 /*    l  enumList                      */
985 /*    s  uSer                          */
986 /*    a  abstract                      */
987 /*    t  poinTer                       */
988 /*    y  arraY                         */
989 /*    F  Fixed array                   */
990 /*    f  function                      */
991 /*    S  structure                     */
992 /*    U  union                         */
993 /*    C  conj                          */
994
995 static /*@only@*/ cstring
996 ctbase_dump (ctbase c)
997 {
998   if (!ctbase_isDefined (c))
999     {
1000       return cstring_makeLiteral ("?");
1001     }
1002
1003   switch (c->type)
1004     {
1005     case CT_UNKNOWN:
1006       return cstring_makeLiteral ("u");
1007     case CT_BOOL:
1008       return cstring_makeLiteral ("b");
1009     case CT_PRIM:
1010       return (message ("p%d|", c->contents.prim));
1011     case CT_USER:
1012       return (message ("s%d|", 
1013                        usymtab_convertId (c->contents.tid)));
1014     case CT_ABST:
1015       return (message ("a%d|", usymtab_convertId (c->contents.tid)));
1016     case CT_PTR:
1017       return (message ("t%q|", ctype_dump (c->contents.base)));
1018     case CT_ARRAY:
1019       return (message ("y%q|", ctype_dump (c->contents.base)));
1020     case CT_FIXEDARRAY:
1021       return (message ("F%q/%d|", 
1022                        ctype_dump (c->contents.farray->base),
1023                        (int) c->contents.farray->size));
1024     case CT_FCN:
1025       DPRINTF (("Dump function: %s", ctbase_unparse (c)));
1026       return (message ("f%q (%q)", ctype_dump (c->contents.fcn->rval),
1027                        uentryList_dumpParams (c->contents.fcn->params)));
1028     case CT_STRUCT:
1029       return (message ("S%s{%q}", c->contents.su->name,
1030                        uentryList_dumpFields (c->contents.su->fields)));
1031     case CT_UNION:
1032       return (message ("U%s{%q}", c->contents.su->name,
1033                        uentryList_dumpFields (c->contents.su->fields)));
1034     case CT_ENUM:
1035       {
1036         cstring s;
1037         
1038         if (cstring_isNonEmpty (c->contents.cenum->tag))
1039           {
1040             s = message ("e%s{%q}", 
1041                          c->contents.cenum->tag,
1042                          enumNameList_dump (c->contents.cenum->members));
1043           }
1044         else
1045           {
1046             s = message ("e{%q}", 
1047                          enumNameList_dump (c->contents.cenum->members));
1048           }
1049         return (s);
1050       }
1051     case CT_CONJ:
1052       return (message ("C%d.%q/%q|", 
1053                        bool_toInt (c->contents.conj->isExplicit),
1054                        ctype_dump (c->contents.conj->a),
1055                        ctype_dump (c->contents.conj->b)));
1056     case CT_EXPFCN:
1057       /* should clean them up! */
1058       return (cstring_makeLiteral ("?"));
1059     case CT_ENUMLIST:
1060       llcontbug (message ("Cannot dump: %q", ctbase_unparse (c))); 
1061       return (message ("u"));
1062     BADDEFAULT;
1063     }
1064
1065   BADEXIT;
1066 }
1067
1068 static /*@only@*/ ctbase
1069 ctbase_copy (/*@notnull@*/ ctbase c)
1070 {
1071   switch (c->type)
1072     {
1073     case CT_UNKNOWN:
1074       return (ctbase_createUnknown ());
1075     case CT_BOOL:
1076       return (ctbase_createBool ());
1077     case CT_ENUM:
1078       return (ctbase_createEnum (cstring_copy (c->contents.cenum->tag), 
1079                                  enumNameList_copy (c->contents.cenum->members)));
1080     case CT_PRIM:
1081       return (ctbase_createPrim (c->contents.prim));
1082     case CT_USER:
1083       return (ctbase_createUser (c->contents.tid));
1084     case CT_ABST:
1085       return (ctbase_createAbstract (c->contents.tid));
1086     case CT_EXPFCN:
1087       return (ctbase_expectFunction (c->contents.base));
1088     case CT_PTR:
1089       return (ctbase_makePointer (c->contents.base));
1090     case CT_ARRAY:
1091       return (ctbase_makeArray (c->contents.base));
1092     case CT_FCN:
1093       return (ctbase_makeLiveFunction (c->contents.fcn->rval,
1094                                        uentryList_copy (c->contents.fcn->params)));     
1095     case CT_STRUCT:
1096       return (ctbase_createStruct (cstring_copy (c->contents.su->name),
1097                                    uentryList_copy (c->contents.su->fields)));
1098     case CT_UNION:
1099       return (ctbase_createUnion (cstring_copy (c->contents.su->name),
1100                                   uentryList_copy (c->contents.su->fields)));
1101     case CT_CONJ:
1102       /*@i@*/ return (c); /* not a real copy for conj's */
1103     default:
1104       llbug (message ("ctbase_copy: %q", ctbase_unparse (c)));
1105     }
1106
1107   BADEXIT;
1108 }
1109                                 
1110 static enumNameList
1111 ctbase_elist (ctbase c)
1112 {
1113   llassert (ctbase_isDefined (c));
1114   llassert (c->type == CT_ENUM);
1115
1116   return (c->contents.cenum->members);
1117 }
1118
1119 static void
1120 ctbase_free (/*@only@*/ ctbase c)
1121 {
1122   if (c == ctbase_bool || c == ctbase_unknown)
1123     {
1124       /*@-mustfree@*/ return; /*@=mustfree@*/
1125     }
1126
1127   --nctbases;
1128   
1129     
1130   if (ctbase_isDefined (c))
1131     {
1132       switch (c->type)
1133         {
1134         case CT_UNKNOWN:
1135           sfree (c);
1136           break;
1137         case CT_PRIM:
1138           sfree (c);
1139           break;
1140         case CT_ENUM:
1141           sfree (c);
1142           break;
1143         case CT_ENUMLIST:
1144           /* sfree list? */
1145           sfree (c);
1146           break;
1147         case CT_USER:
1148           sfree (c);
1149           break;
1150         case CT_ABST:
1151           sfree (c);
1152           break;
1153         case CT_PTR:
1154         case CT_ARRAY:
1155           sfree (c);
1156           break;
1157         case CT_FCN:
1158           /*@i32@*/ /* uentryList_free (c->contents.fcn->params); */
1159           sfree (c);
1160           break;
1161         case CT_STRUCT:
1162         case CT_UNION:
1163           cstring_free (c->contents.su->name);
1164           uentryList_free (c->contents.su->fields); 
1165           sfree (c);
1166           break;
1167         case CT_CONJ:
1168           /* Don't bree conj's, */
1169           break;
1170         default:
1171           sfree (c);
1172           break;
1173         }
1174     }
1175 }
1176
1177 /*
1178 ** c should be * <unknown>
1179 */
1180
1181 static /*@only@*/ ctbase
1182 ctbase_expectFunction (ctype c)
1183 {
1184   ctbase f = ctbase_new ();
1185
1186   f->type = CT_EXPFCN;
1187   f->contents.base = c;
1188
1189   return (f);
1190 }
1191
1192 static bool
1193 ctbase_isExpectFunction (/*@notnull@*/ ctbase ct) /*@*/
1194 {
1195   return (ct->type == CT_EXPFCN);
1196 }
1197
1198 static ctype
1199 ctbase_getExpectFunction (/*@notnull@*/ ctbase ct)
1200 {
1201   llassert (ctbase_isExpectFunction (ct));
1202   return ct->contents.base;
1203 }
1204
1205 static bool
1206 ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def, bool deep)
1207 {
1208   ctuid c1tid, c2tid;
1209   
1210   /* undefined types never match */
1211   
1212   if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
1213     return FALSE;
1214   
1215   /* abstract types match user types of same name */
1216
1217   c1 = ctbase_realType (c1);
1218   c2 = ctbase_realType (c2);
1219   
1220   DPRINTF (("Matching: %s / %s", ctbase_unparse (c1),
1221             ctbase_unparse (c2)));
1222   
1223   c1tid = c1->type;
1224   c2tid = c2->type;
1225   
1226   if (c1tid == CT_CONJ)
1227     {
1228       return (ctbase_genMatch (ctype_getCtbase (c1->contents.conj->a), c2,
1229                                force, arg, def, deep)
1230               || ctbase_genMatch (ctype_getCtbase (c1->contents.conj->b), c2,
1231                                   force, arg, def, deep));
1232     }
1233   
1234   if (c2tid == CT_CONJ)
1235     {
1236       return (ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->a),
1237                                force, arg, def, deep)
1238               || ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->b),
1239                                   force, arg, def, deep));
1240     }
1241
1242   /*
1243   ** if the types don't match, there are some special cases...
1244   */
1245
1246   if (c1tid != c2tid)
1247     {
1248       /* unknowns match anything */
1249       
1250       if (c1tid == CT_UNKNOWN || c2tid == CT_UNKNOWN)
1251         {
1252           return TRUE;
1253         }
1254
1255       if (c1tid == CT_FIXEDARRAY 
1256           && (c2tid == CT_ARRAY || (!def && c2tid == CT_PTR)))
1257         {
1258           if (ctype_isVoid (c2->contents.base))
1259             {
1260               return (context_getFlag (FLG_ABSTVOIDP) ||
1261                       (!(ctype_isRealAbstract (c1->contents.farray->base)) &&
1262                        !(ctype_isRealAbstract (c2->contents.base))));
1263             }
1264
1265           return (ctbase_genMatch (ctype_getCtbase (c1->contents.farray->base),
1266                                    ctype_getCtbase (c2->contents.base),
1267                                    force, arg, def, deep));
1268         }
1269
1270
1271       if (c2tid == CT_FIXEDARRAY 
1272           && (c1tid == CT_ARRAY || (!def && c1tid == CT_PTR)))
1273         {
1274           if (ctype_isVoid (c1->contents.base))
1275             {
1276               return (context_getFlag (FLG_ABSTVOIDP) ||
1277                       (!(ctype_isRealAbstract (c2->contents.farray->base)) &&
1278                        !(ctype_isRealAbstract (c1->contents.base))));
1279             }
1280
1281           return (ctbase_genMatch (ctype_getCtbase (c1->contents.base),
1282                                    ctype_getCtbase (c2->contents.farray->base),
1283                                    force, arg, def, deep));
1284         }
1285       
1286       /* evs 2000-07-25: Bool's may match user/abstract types */
1287
1288       if ((c1tid == CT_BOOL 
1289            && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1290           (c2tid == CT_BOOL 
1291            && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1292         {
1293           return (context_msgBoolInt ());
1294         }
1295
1296       if ((c1tid == CT_BOOL && (c2tid == CT_ABST || c2tid == CT_USER))) {
1297         ctype t2c = c2->contents.base;
1298
1299         return (ctype_isBool (t2c));
1300       }
1301
1302       if ((c2tid == CT_BOOL && (c1tid == CT_ABST || c1tid == CT_USER))) {
1303         ctype t1c = c1->contents.base;
1304
1305         return (ctype_isBool (t1c));
1306       }
1307
1308       if ((c1tid == CT_ENUM
1309            && (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
1310           (c2tid == CT_ENUM
1311            && (c1tid == CT_PRIM && cprim_isInt (c1->contents.prim))))
1312         {
1313           return (context_msgEnumInt ());
1314         }
1315
1316       /*
1317       ** arrays and pointers...yuk!
1318       **
1319       ** Considered equivalent except in definitions.  
1320       ** (e.g., function parameters are equivalent)
1321       **
1322       */
1323       
1324       if (!def)
1325         {
1326           if (ctuid_isAP (c1tid) && ctuid_isAP (c2tid))
1327             {
1328               c2tid = c1tid;
1329             }
1330         }
1331
1332       /*
1333       ** Function pointers can be removed.
1334       **
1335       ** [function ..] is equivalent to [function ..] *
1336       */
1337
1338       if (c1tid == CT_PTR && c2tid == CT_FCN)
1339         {
1340           if (ctype_isFunction (ctype_realType (c1->contents.base)))
1341             {
1342               c1 = ctbase_realType (ctype_getCtbaseSafe (c1->contents.base));
1343               c1tid = c1->type;
1344             }
1345         }
1346
1347       if (c2tid == CT_PTR && c1tid == CT_FCN)
1348         {
1349           if (ctype_isFunction (ctype_realType (c2->contents.base)))
1350             {
1351               c2 = ctbase_realType (ctype_getCtbaseSafe (c2->contents.base));
1352               c2tid = c2->type;
1353             }
1354         }
1355
1356       /*
1357       ** we allow forward declarations to structures like,
1358       **
1359       **          typedef struct _t *t;
1360       ** 
1361       ** to allow,
1362       **           struct _t * to match t
1363       */
1364   
1365       if (context_getFlag (FLG_FORWARDDECL))
1366         {
1367           if (c1tid == CT_ABST || c1tid == CT_USER)
1368             {
1369               if (ctuid_isAP (c2tid))
1370                 {
1371                   ctype ts = c2->contents.base;
1372                   
1373                   if (ctype_isUA (ts))
1374                     {
1375                       typeId ttid = ctype_typeId (ts);
1376                       typeId ctid = c1->contents.tid ;
1377                       
1378                       if (usymtab_matchForwardStruct (ctid, ttid))
1379                         {
1380                           return TRUE;
1381                         }
1382                     }
1383                 }
1384             }
1385           
1386           if (c2tid == CT_ABST || c2tid == CT_USER)
1387             {
1388               if (ctuid_isAP (c1tid))
1389                 {
1390                   ctype ts = c1->contents.base;
1391                   
1392                   if (ctype_isUA (ts))
1393                     {
1394                       typeId ttid = ctype_typeId (ts);
1395                       typeId ctid = c2->contents.tid ;
1396                       
1397                       if (usymtab_matchForwardStruct (ctid, ttid))
1398                         {
1399                           return TRUE;
1400                         }
1401                     }
1402                 }
1403             }
1404         }
1405     }
1406
1407   if (c1tid != c2tid)
1408     return FALSE;
1409
1410   switch (c1tid)
1411     {
1412     case CT_UNKNOWN:
1413       return (TRUE);
1414     case CT_PRIM:
1415       if (deep) {
1416         return (cprim_closeEnoughDeep (c1->contents.prim, c2->contents.prim));
1417       } else {
1418         return (cprim_closeEnough (c1->contents.prim, c2->contents.prim));
1419       }
1420     case CT_BOOL:
1421       return (TRUE);
1422     case CT_ABST:
1423       return (typeId_equal (c1->contents.tid, c2->contents.tid));
1424     case CT_USER:
1425       return (typeId_equal (c1->contents.tid, c2->contents.tid));
1426     case CT_ENUM:       
1427       return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
1428     case CT_PTR:
1429       if (ctype_isVoid (c1->contents.base)
1430           || (ctype_isVoid (c2->contents.base)))
1431         {
1432           if (ctype_isFunction (ctype_realType (c1->contents.base))
1433               || ctype_isFunction (ctype_realType (c2->contents.base)))
1434             {
1435               return (!context_getFlag (FLG_CASTFCNPTR));
1436             }
1437           else
1438             {
1439               return (context_getFlag (FLG_ABSTVOIDP) ||
1440                       (!(ctype_isRealAbstract (c1->contents.base)) &&
1441                        !(ctype_isRealAbstract (c2->contents.base))));
1442             }
1443         }
1444       else
1445         {
1446           /* Only allow one implicit function pointer. */
1447                           
1448           if (!bool_equal (ctype_isRealPointer (c1->contents.base),
1449                            ctype_isRealPointer (c2->contents.base))
1450               && (ctype_isRealFunction (c1->contents.base)
1451                   || ctype_isRealFunction (c2->contents.base)))
1452             {
1453               return FALSE;
1454             }
1455
1456           return (ctype_genMatch (c1->contents.base,
1457                                   c2->contents.base, force, arg, def, TRUE));
1458         }
1459     case CT_FIXEDARRAY:
1460       if (ctype_isVoid (c1->contents.farray->base) 
1461           || ctype_isVoid (c2->contents.farray->base))
1462         return TRUE;
1463       return (ctype_genMatch (c1->contents.farray->base, 
1464                               c2->contents.farray->base, 
1465                               force, arg, def, deep));
1466     case CT_ARRAY:
1467       if (ctype_isVoid (c1->contents.base) || ctype_isVoid (c2->contents.base))
1468         return TRUE;
1469       return (ctype_genMatch (c1->contents.base, c2->contents.base, force, arg, def, TRUE));
1470     case CT_FCN:
1471       return (ctype_genMatch (c1->contents.fcn->rval, 
1472                               c2->contents.fcn->rval, 
1473                               force, arg, def, TRUE) 
1474               && uentryList_matchParams (c1->contents.fcn->params, 
1475                                          c2->contents.fcn->params, 
1476                                          force, TRUE));
1477     case CT_STRUCT:
1478     case CT_UNION:
1479       DPRINTF (("Struct: %s / %s",
1480                 c1->contents.su->name,
1481                 c2->contents.su->name));
1482
1483       if (isFakeTag (c1->contents.su->name)
1484           && isFakeTag (c2->contents.su->name))
1485         {
1486           /* Both fake tags, check structure */
1487           if (cstring_equal (c1->contents.su->name, c2->contents.su->name))
1488             {
1489               return TRUE;
1490             }
1491           else
1492             {
1493               return uentryList_matchFields (c1->contents.su->fields, 
1494                                              c2->contents.su->fields);
1495             }
1496         }
1497       else
1498         {
1499           if (!cstring_isEmpty (c1->contents.su->name))
1500             {
1501               return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
1502             }
1503           else
1504             {
1505               if (!cstring_isEmpty (c2->contents.su->name))
1506                 {
1507                   return FALSE;
1508                 }
1509               
1510               llcontbuglit ("ctbase_genMatch: match fields");
1511               return (FALSE);
1512             }
1513         }
1514     default:
1515       llcontbug (message ("ctbase_genMatch: unknown type: %d\n", (int)c1tid));
1516       return (FALSE);
1517     }
1518 }
1519
1520 /*
1521 ** like ctbase_match, except for conjuncts:
1522 **   modifies conjuncts to match only
1523 */
1524
1525 static bool
1526 ctbase_forceMatch (ctbase c1, ctbase c2) /*@modifies c1, c2@*/
1527 {
1528   return (ctbase_genMatch (c1, c2, TRUE, FALSE, FALSE, FALSE));
1529 }
1530
1531 static bool
1532 ctbase_match (ctbase c1, ctbase c2) /*@modifies nothing@*/
1533 {
1534   return (ctbase_genMatch (c1, c2, FALSE, FALSE, FALSE, FALSE));
1535 }
1536
1537 static bool
1538 ctbase_matchDef (ctbase c1, ctbase c2) /*@modifies nothing@*/
1539 {
1540   return (ctbase_genMatch (c1, c2, FALSE, FALSE, TRUE, FALSE));
1541 }
1542
1543 static bool
1544 ctbase_matchArg (ctbase c1, ctbase c2)
1545 {
1546   return (ctbase_genMatch (c1, c2, FALSE, TRUE, FALSE, FALSE));
1547 }
1548
1549 static /*@out@*/ /*@only@*/ /*@notnull@*/ ctbase 
1550 ctbase_new ()
1551 {
1552   ctbase c = (ctbase) dmalloc (sizeof (*c));
1553
1554   nctbases++;
1555  /*
1556    if (nctbases % 100 == 0 && nctbases > lastnc)
1557      {
1558        llmsg (message ("ctbases: %d", nctbases));
1559        lastnc = nctbases;
1560      }
1561  */
1562   return (c);
1563 }
1564
1565 static /*@only@*/ ctbase
1566 ctbase_createPrim (cprim p)
1567 {
1568   ctbase c = ctbase_new ();
1569
1570   c->type = CT_PRIM;
1571   c->contents.prim = p;
1572
1573   return (c);
1574 }
1575
1576 static /*@observer@*/ ctbase
1577 ctbase_getBool (void)
1578 {
1579   /*@i@*/ return ctbase_createBool ();
1580 }
1581
1582 static ctbase
1583 ctbase_createBool ()
1584 {
1585   if (!ctbase_isDefined (ctbase_bool))
1586     {
1587       ctbase_bool = ctbase_new ();
1588       ctbase_bool->type = CT_BOOL;
1589       ctbase_bool->contents.prim = CTX_BOOL;
1590     }
1591
1592   /*@-retalias@*/ /*@-globstate@*/
1593   return ctbase_bool;
1594   /*@=retalias@*/ /*@=globstate@*/
1595 }
1596
1597 static /*@only@*/ ctbase
1598 ctbase_createUser (typeId u)
1599 {
1600   ctbase c = ctbase_new ();
1601
1602   c->type = CT_USER;
1603   c->contents.tid = u;
1604
1605   llassert (typeId_isValid (u));
1606
1607   return (c);
1608 }
1609
1610 static /*@only@*/ ctbase
1611 ctbase_createEnum (/*@keep@*/ cstring etag, /*@keep@*/ enumNameList emembers)
1612 {
1613   ctbase c = ctbase_new ();
1614
1615   c->type = CT_ENUM;
1616
1617   if (cstring_isUndefined (etag))
1618     {
1619       llcontbuglit ("Undefined enum tag!");
1620       etag = fakeTag ();
1621     }
1622
1623   c->contents.cenum = (tenum) dmalloc (sizeof (*c->contents.cenum));
1624   c->contents.cenum->tag = etag;
1625   c->contents.cenum->members = emembers;
1626
1627   return (c);
1628 }
1629
1630 static /*@observer@*/ cstring
1631 ctbase_enumTag (/*@notnull@*/ ctbase ct)
1632 {
1633   return (ct->contents.cenum->tag);
1634 }
1635
1636 static /*@only@*/ ctbase
1637 ctbase_createAbstract (typeId u)
1638 {
1639   ctbase c = ctbase_new ();
1640
1641   c->type = CT_ABST;
1642   c->contents.tid = u;
1643
1644  /* also check its abstract? */
1645
1646   llassert (typeId_isValid (c->contents.tid));
1647
1648   return (c);
1649 }
1650
1651 static /*@only@*/ ctbase
1652 ctbase_createUnknown (void)
1653 {
1654   if (!ctbase_isDefined (ctbase_unknown))
1655     {
1656       ctbase_unknown = ctbase_new ();
1657       ctbase_unknown->type = CT_UNKNOWN;
1658       ctbase_unknown->contents.prim = CTX_UNKNOWN;
1659     }
1660
1661   /*@-retalias@*/ /*@-globstate@*/
1662   return ctbase_unknown;
1663   /*@=retalias@*/ /*@=globstate@*/
1664 }
1665
1666 /*
1667 ** requires: result is not assigned to b
1668 **           (should copy, but no way to reclaim storage)
1669 */
1670
1671 static /*@only@*/ ctbase
1672 ctbase_makePointer (ctype b)
1673 {
1674   ctbase c = ctbase_new ();
1675
1676   c->type = CT_PTR;
1677   c->contents.base = b;
1678
1679   return (c);
1680 }
1681
1682 static /*@only@*/ ctbase
1683 ctbase_makeArray (ctype b)
1684 {
1685   ctbase c = ctbase_new ();
1686
1687   c->type = CT_ARRAY;
1688   c->contents.base = b;
1689
1690   return (c);
1691 }
1692
1693 static /*@notnull@*/ /*@only@*/ ctbase
1694 ctbase_makeFixedArray (ctype b, size_t size)
1695 {
1696   ctbase c = ctbase_new ();
1697
1698   c->type = CT_FIXEDARRAY;
1699
1700   c->contents.farray = (tfixed) dmalloc (sizeof (*c->contents.farray));
1701   c->contents.farray->base = b;
1702   c->contents.farray->size = size;
1703
1704   return (c);
1705 }
1706
1707 static ctype
1708 ctbase_makeFunction (ctype b, /*@only@*/ uentryList p)
1709 {
1710   ctbase c = ctbase_new ();
1711   ctype ct;
1712   
1713   c->type = CT_FCN;
1714   c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1715
1716   if (ctype_isFunction (b)) /* was: && ctype_isPointer (b)) */
1717     {
1718       ctbase ctb;
1719       ctype rval;
1720       
1721       if (ctype_isPointer (b))
1722         {
1723           ctb  = ctype_getCtbase (ctype_baseArrayPtr (b));
1724         }
1725       else
1726         {
1727           ctb = ctype_getCtbase (b);
1728         }
1729       
1730       llassert (ctbase_isDefined (ctb));
1731       llassert (ctb->type == CT_FCN);
1732       
1733       rval = ctype_makeFunction (ctb->contents.fcn->rval, p);
1734
1735       c->contents.fcn->rval = rval;
1736       c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params); /* no copy before */
1737     }
1738   else
1739     {
1740       c->contents.fcn->rval = b;
1741       c->contents.fcn->params = uentryList_copy (p); /* no copy before */
1742       /*@-branchstate@*/ /* p is really released on this branch */
1743     } 
1744   /*@=branchstate@*/
1745
1746   ct = cttable_addComplex (c);  
1747   return (ct); /* was: ctype_makePointer (ct)); */
1748 }
1749
1750 static ctype
1751 ctbase_makeNFFunction (ctype b, /*@only@*/ uentryList p)
1752 {
1753   ctbase c = ctbase_new ();
1754   ctype ct;
1755
1756   c->type = CT_FCN;
1757   c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1758
1759   if (ctype_isFunction (b)) /* was && ctype_isPointer (b)) */
1760     {
1761       ctbase ctb;
1762       ctype rval;
1763       
1764       if (ctype_isPointer (b))
1765         {
1766           ctb  = ctype_getCtbase (ctype_baseArrayPtr (b));
1767         }
1768       else
1769         {
1770           ctb = ctype_getCtbase (b);
1771         }
1772
1773       llassert (ctbase_isDefined (ctb));
1774       llassert (ctb->type == CT_FCN);
1775       
1776       rval = ctype_makeNFParamsFunction (ctb->contents.fcn->rval, p);
1777       
1778       c->contents.fcn->rval = rval;
1779       c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params);
1780     }
1781   else
1782     {
1783       c->contents.fcn->rval = b;
1784       c->contents.fcn->params = uentryList_copy (p);
1785       /*@-branchstate@*/ 
1786     }
1787   /*@=branchstate@*/
1788
1789   ct = cttable_addComplex (c);
1790   return (ct); /* was: ctype_makePointer (ct)); */
1791 }
1792
1793 static /*@only@*/ ctbase
1794   ctbase_makeLiveFunction (ctype b, /*@only@*/ uentryList p)
1795 {
1796   ctbase c = ctbase_new ();
1797
1798   c->type = CT_FCN;
1799
1800   c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
1801   c->contents.fcn->rval = b;
1802   c->contents.fcn->params = p;
1803
1804   /*@-mustfree@*/ return (c); /*@=mustfree@*/
1805 }
1806
1807 static /*@observer@*/ /*@notnull@*/ ctbase
1808 ctbase_realFunction (/*@dependent@*/ /*@notnull@*/ ctbase c)
1809 {
1810   ctbase res;
1811
1812   if (c->type == CT_FCN)
1813     {
1814       return c;
1815     }
1816
1817   llassert (ctbase_isFunction (c));
1818
1819   res = ctype_getCtbase (c->contents.base);
1820   
1821   llassert (ctbase_isDefined (res));
1822
1823   return (res);
1824 }
1825
1826 static bool
1827 ctbase_isFunction (ctbase c)
1828 {
1829   llassert (c != ctbase_undefined);
1830
1831   if (c->type == CT_FCN)
1832     {
1833       return TRUE;
1834     }
1835   else
1836     {
1837       if (c->type == CT_PTR)
1838         {
1839           ctbase fcn = ctype_getCtbase (ctbase_baseArrayPtr (c));
1840
1841           return (ctbase_isDefined (fcn) && fcn->type == CT_FCN);
1842         }
1843
1844       return FALSE;
1845     }
1846 }
1847
1848 /* doesn't copy c1 and c2 */
1849
1850 static /*@only@*/ ctbase
1851   ctbase_makeConj (ctype c1, ctype c2, bool isExplicit)
1852 {
1853   ctbase c = ctbase_new ();
1854
1855   c->type = CT_CONJ;
1856
1857   c->contents.conj = (tconj) dmalloc (sizeof (*c->contents.conj));
1858   c->contents.conj->a = c1;
1859   c->contents.conj->b = c2;
1860   c->contents.conj->isExplicit = isExplicit;
1861
1862   return (c);
1863 }
1864
1865 static bool ctbase_isAnytype (/*@notnull@*/ ctbase b)
1866 {
1867   /*
1868   ** A unknown|dne conj is a special representation for an anytype.
1869   */
1870
1871   if (b->type == CT_CONJ)
1872     {
1873       /*@access ctype@*/
1874       return (b->contents.conj->a == ctype_unknown
1875               && b->contents.conj->b == ctype_dne);
1876       /*@noaccess ctype@*/ 
1877     }
1878   
1879   return FALSE;
1880 }
1881
1882 static ctype
1883 ctbase_getConjA (/*@notnull@*/ ctbase c)
1884 {
1885   llassert (c->type == CT_CONJ);
1886   return (c->contents.conj->a);
1887 }
1888
1889 static ctype
1890 ctbase_getConjB (/*@notnull@*/ ctbase c)
1891 {
1892   llassert (c->type == CT_CONJ);
1893   return (c->contents.conj->b);
1894 }
1895
1896 static bool
1897 ctbase_isExplicitConj (/*@notnull@*/ ctbase c)
1898 {
1899   llassert (c->type == CT_CONJ);
1900   return (c->contents.conj->isExplicit);
1901 }
1902
1903 static /*@only@*/ ctbase
1904 ctbase_createStruct (/*@only@*/ cstring n, /*@only@*/ uentryList f)
1905 {
1906   ctbase c = ctbase_new ();
1907
1908   c->type = CT_STRUCT;
1909
1910   c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
1911   c->contents.su->name = n;
1912   c->contents.su->fields = f;
1913
1914   return (c);
1915 }
1916
1917 static /*@observer@*/ uentryList
1918 ctbase_getuentryList (/*@notnull@*/ ctbase c)
1919 {
1920   c = ctbase_realType (c);
1921
1922   if (!(c->type == CT_STRUCT || c->type == CT_UNION))
1923     llfatalbug (message ("ctbase_getuentryList: bad invocation: %q", ctbase_unparse (c)));
1924
1925   return (c->contents.su->fields);
1926 }
1927
1928 static ctbase
1929 ctbase_createUnion (/*@keep@*/ cstring n, /*@only@*/ uentryList f)
1930 {
1931   ctbase c = ctbase_new ();
1932
1933   c->type = CT_UNION;
1934
1935   c->contents.su = (tsu) dmalloc (sizeof (*c->contents.su));
1936   c->contents.su->name = n;
1937   c->contents.su->fields = f;
1938
1939   return (c);
1940 }
1941
1942 static ctype
1943 ctbase_baseArrayPtr (/*@notnull@*/ ctbase c)
1944 {
1945   ctuid ct;
1946   c = ctbase_realType (c);
1947   ct = c->type;
1948
1949   if (ct == CT_FIXEDARRAY)
1950     {
1951       return c->contents.farray->base;
1952     }
1953   else
1954     {
1955       llassert (ctuid_isAP (ct));
1956
1957       return c->contents.base;
1958     }
1959 }
1960
1961 static ctype
1962 ctbase_baseFunction (/*@notnull@*/ ctbase c)
1963 {
1964   ctbase_fixUser (c);
1965   c = ctbase_realFunction (c);
1966
1967   if (c->type != CT_FCN)
1968     {
1969       llfatalbug (message ("ctbase_baseFunction: bad call: %q", ctbase_unparse (c)));
1970     }
1971
1972   return (c->contents.fcn->rval);
1973 }
1974
1975 static uentryList
1976 ctbase_argsFunction (/*@notnull@*/ ctbase c)
1977 {
1978   ctbase_fixUser (c);
1979   c = ctbase_realFunction (c);
1980
1981   if (c->type != CT_FCN)
1982     {
1983       llfatalbug (message ("ctbase_argsFunction: bad call: %q", 
1984                            ctbase_unparse (c)));
1985     }
1986   return (c->contents.fcn->params);
1987 }
1988
1989 static bool
1990 ctbase_baseisExpFcn (ctype c)
1991 {
1992   ctbase cb;
1993   c = ctype_removePointers (c);
1994
1995   cb = ctype_getCtbase (c);
1996   llassert (ctbase_isDefined (cb));
1997
1998   if (cb->type == CT_FCN)
1999     {
2000       c = ctype_removePointers (ctype_getReturnType (c));
2001
2002       cb = ctype_getCtbase (c);
2003       llassert (ctbase_isDefined (cb));
2004
2005       return (cb->type == CT_EXPFCN);
2006     }
2007   return FALSE;
2008 }
2009
2010 /*
2011 ** ctbase_newBase behaves specially when p is a CONJ:
2012 **
2013 **    c -> conj (newBase (c, p.a), p.b)
2014 */
2015
2016 static ctype
2017 ctbase_newBase (ctype c, ctype p)
2018 {
2019   ctbase cb;
2020
2021   DPRINTF (("New base: %s / %s", ctype_unparse (c), ctype_unparse (p)));
2022
2023   if (ctype_isUndefined (c) || ctype_isUnknown (c))
2024     {
2025       return p;
2026     }
2027
2028   cb = ctype_getCtbase (c);
2029
2030   if (ctype_isConj (p))
2031     {
2032       ctbase pb = ctype_getCtbase (p);
2033
2034       llassert (ctbase_isDefined (pb));
2035
2036       if (pb->contents.conj->isExplicit)
2037         {
2038           return (ctype_makeExplicitConj (ctype_newBase (c, pb->contents.conj->a),
2039                                           pb->contents.conj->b)); 
2040                                           
2041         }
2042       else
2043         {
2044           return (ctype_makeConj (ctype_newBase (c, pb->contents.conj->a),
2045                                   pb->contents.conj->b));
2046                                   
2047         }
2048     }
2049
2050   if (ctbase_baseisExpFcn (c))
2051     {
2052       return (ctbase_newBaseExpFcn (c, p));
2053     }
2054
2055   llassert (ctbase_isDefined (cb));
2056
2057   switch (cb->type)
2058     {
2059     case CT_UNKNOWN:
2060     case CT_PRIM:
2061     case CT_USER:
2062     case CT_ENUM:
2063     case CT_ABST:
2064     case CT_STRUCT:
2065     case CT_UNION:
2066     case CT_EXPFCN:
2067       return (p);
2068
2069     case CT_PTR:
2070       {
2071         ctype ret;
2072         ctype cbn;
2073
2074         cbn = ctbase_newBase (cb->contents.base, p);
2075         ret = ctype_makePointer (cbn);
2076
2077         return ret;
2078       }
2079     case CT_FIXEDARRAY:
2080       return (ctype_makeFixedArray (ctbase_newBase (cb->contents.farray->base, p),
2081                                     cb->contents.farray->size));
2082     case CT_ARRAY:
2083       return (ctype_makeArray (ctbase_newBase (cb->contents.base, p)));
2084     case CT_FCN:
2085       return (ctype_makeRawFunction (ctbase_newBase (cb->contents.fcn->rval, p),
2086                                       cb->contents.fcn->params));
2087     case CT_CONJ:
2088       return (ctype_makeConjAux (ctbase_newBase (cb->contents.conj->a, p),
2089                                  ctbase_newBase (cb->contents.conj->b, p),
2090                                  cb->contents.conj->isExplicit));
2091     default:
2092       llcontbug (message ("ctbase_newBase: bad ctbase: %q", ctbase_unparse (cb))); 
2093       return (p); 
2094     }
2095   BADEXIT;
2096 }
2097
2098 static ctype
2099 ctbase_newBaseExpFcn (ctype c, ctype p)
2100 {
2101   ctbase cb = ctype_getCtbase (c);
2102   ctbase tcb;
2103   ctype ret, tmpct;
2104   ctype fp = ctype_unknown;
2105   uentryList ctargs = ctype_argsFunction (c);
2106
2107   /*
2108   ** okay, this is really ugly...
2109   **
2110   ** pointers inside <expf> mean pointers to the function;
2111   ** pointers outside <expf> are pointers to the return value;
2112   ** because its a function there is one superfluous pointer.
2113   */
2114   
2115   /*
2116   ** bf is a ctype, used to derived structure of cb
2117   */
2118   
2119   if (!ctbase_isFunction (cb))
2120     llbuglit ("ctbase_newBaseExpFcn: expFcn -> not a function");
2121   
2122   tmpct = ctype_getBaseType (ctype_getReturnType (c));
2123   
2124   /*
2125   ** pointers before expfcn -> p are pointers to function, not result
2126   **
2127   */
2128   
2129   tcb = ctype_getCtbase (tmpct);
2130
2131   llassert (ctbase_isDefined (tcb));
2132   tmpct = tcb->contents.base;
2133   
2134   /*
2135   ** record pointers to base in fp
2136   */
2137   
2138   while (!ctype_isUnknown (tmpct))
2139     {
2140       if (ctype_isExpFcn (tmpct)) {
2141         ctbase ttcb = ctype_getCtbase (tmpct);
2142
2143         /*
2144         ** evs 2000-05-16: This is necessary to deal with function pointers in parens.  
2145         ** The whole function pointer parsing is a major kludge, but it seems to work,
2146         ** and I'm only embarrassed by it when I haven't look at the C spec recently...
2147         */
2148            
2149         llassert (ctbase_isDefined (ttcb));
2150         tmpct = ttcb->contents.base;
2151         llassert (!ctype_isUnknown (tmpct));
2152       }
2153
2154       switch (ctype_getCtKind (tmpct))
2155         {
2156         case CTK_PTR:
2157           fp = ctype_makePointer (fp);
2158           /*@switchbreak@*/ break;
2159         case CTK_ARRAY:
2160           fp = ctype_makeArray (fp);
2161           /*@switchbreak@*/ break;
2162         case CTK_COMPLEX:
2163           {
2164             ctbase fbase = ctype_getCtbase (tmpct);
2165
2166             if (ctbase_isFunction (fbase))
2167               {
2168                 fp = ctype_makeFunction (fp, uentryList_copy (ctargs));
2169                 ctargs = ctbase_argsFunction (fbase);
2170               }
2171             else
2172               {
2173                 llbug 
2174                   (message
2175                    ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s [base: %q]",
2176                     ctype_unparse (tmpct), ctbase_unparse (fbase)));
2177               }
2178             goto exitLoop;
2179           }
2180         default:
2181           {
2182             llcontbug 
2183               (message ("ctbase_newBaseExpFcn: fixing expfunction: bad type: %s",
2184                         ctype_unparse (tmpct)));
2185             goto exitLoop; 
2186           }
2187         }
2188       tmpct = ctype_baseArrayPtr (tmpct);
2189     }
2190
2191  exitLoop:
2192   tmpct = ctype_getReturnType (c);
2193
2194   /*
2195   ** pointers to expf are pointers to return value
2196   */
2197   
2198   while (!ctype_isExpFcn (tmpct))
2199     {
2200       switch (ctype_getCtKind (tmpct))
2201         {
2202         case CTK_PTR:
2203           p = ctype_makePointer (p);
2204           /*@switchbreak@*/ break;
2205         case CTK_ARRAY:
2206           p = ctype_makeArray (p);
2207           /*@switchbreak@*/ break;
2208         case CTK_COMPLEX:
2209           {
2210             ctbase fbase = ctype_getCtbase (tmpct);
2211           
2212             if (ctbase_isFunction (fbase))
2213               {
2214                 p = ctype_makeFunction (p, uentryList_copy (ctbase_argsFunction (fbase)));
2215               }
2216             else
2217               {
2218                 llbug 
2219                   (message
2220                    ("ctbase_newBaseExpFcn: fixing expfunction: bad complex type: %s",
2221                     ctype_unparse (tmpct)));
2222               }
2223             goto exitLoop2;
2224           }
2225
2226         default:
2227           {
2228             llcontbug 
2229               (message ("ctbase_newBaseExpFcn: fixing expfunction2: bad type: %t", 
2230                         tmpct));
2231             goto exitLoop2; 
2232           }
2233         }
2234       tmpct = ctype_baseArrayPtr (tmpct);
2235     }
2236   
2237  exitLoop2:
2238   
2239   /*
2240   ** pointers to fp are pointers to function type
2241   */
2242
2243   ret = ctype_makeRawFunction (p, uentryList_copy (ctargs));
2244   
2245   while (ctype_getCtKind (fp) > CTK_PLAIN)
2246     {
2247       switch (ctype_getCtKind (fp))
2248         {
2249         case CTK_PTR:
2250           ret = ctype_makePointer (ret);
2251           /*@switchbreak@*/ break;
2252         case CTK_ARRAY:
2253           ret = ctype_makeArray (ret);
2254           /*@switchbreak@*/ break;
2255         case CTK_COMPLEX:
2256           {
2257             ctbase fbase = ctype_getCtbase (fp);
2258             
2259             if (ctbase_isFunction (fbase))
2260               {
2261                 ret = 
2262                   ctype_makeFunction (ret,
2263                                       uentryList_copy (ctbase_argsFunction (fbase)));
2264               }
2265             else
2266               {
2267                 BADBRANCH;
2268               }
2269             goto exitLoop3;
2270           }
2271
2272         default:
2273           {
2274             llcontbug (message ("post-fixing expfunction: bad type: %t", fp));
2275             goto exitLoop3;
2276           }
2277         }
2278       fp = ctype_baseArrayPtr (fp);
2279     }
2280   
2281  exitLoop3:
2282   return (ret);
2283 }
2284
2285 /*
2286 ** returns lowest level base of c: plain type
2287 */
2288
2289 static /*@notnull@*/ /*@only@*/ ctbase
2290 ctbase_getBaseType (/*@notnull@*/ ctbase c)
2291 {
2292   switch (c->type)
2293     {
2294     case CT_UNKNOWN:
2295     case CT_PRIM:
2296     case CT_USER:
2297     case CT_ENUM:
2298     case CT_ENUMLIST:
2299     case CT_BOOL:
2300     case CT_ABST:
2301     case CT_FCN:
2302     case CT_STRUCT:
2303     case CT_UNION:
2304       return (ctbase_copy (c));
2305
2306     case CT_PTR:
2307     case CT_ARRAY:
2308       return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.base)));
2309
2310     case CT_FIXEDARRAY:
2311       return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.farray->base)));
2312     case CT_CONJ:               /* base type of A conj branch? */
2313       return (ctbase_getBaseType (ctype_getCtbaseSafe (c->contents.conj->a)));
2314     case CT_EXPFCN:
2315       return (ctbase_copy (c));
2316
2317     default:
2318       llfatalbug (message ("ctbase_getBaseType: bad ctbase: %q", ctbase_unparse (c)));
2319     }
2320
2321   BADEXIT;
2322 }
2323
2324 static int
2325 ctbase_compare (ctbase c1, ctbase c2, bool strict)
2326 {
2327   ctuid c1tid, c2tid;
2328
2329   if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2330     {
2331       llcontbuglit ("ctbase_compare: undefined ctbase");
2332       return -1;
2333     }
2334
2335   c1tid = c1->type;
2336   c2tid = c2->type;
2337
2338   if (c1tid < c2tid)
2339     return -1;
2340   if (c1tid > c2tid)
2341     return 1;
2342
2343   switch (c1tid)
2344     {
2345     case CT_UNKNOWN:
2346       return 0;
2347     case CT_PRIM:
2348       return (int_compare (c1->contents.prim, c2->contents.prim));
2349     case CT_BOOL:
2350       return 0;
2351     case CT_USER:
2352       return (int_compare (c1->contents.tid, c2->contents.tid));
2353     case CT_ENUMLIST:        
2354       return 1;
2355     case CT_ENUM:               /* for now, keep like abstract */
2356     case CT_ABST:
2357       return (int_compare (c1->contents.tid, c2->contents.tid));
2358     case CT_PTR:
2359       return (ctype_compare (c1->contents.base, c2->contents.base));
2360     case CT_FIXEDARRAY:
2361       INTCOMPARERETURN (c1->contents.farray->size, c2->contents.farray->size);
2362
2363       return (ctype_compare (c1->contents.farray->base,
2364                              c2->contents.farray->base));
2365     case CT_ARRAY:
2366       return (ctype_compare (c1->contents.base, c2->contents.base));
2367     case CT_FCN:
2368       {
2369         COMPARERETURN (ctype_compare (c1->contents.fcn->rval, c2->contents.fcn->rval));
2370
2371         if (strict)
2372           {
2373             return (uentryList_compareStrict (c1->contents.fcn->params, 
2374                                               c2->contents.fcn->params));
2375           }
2376         else
2377           {
2378             return (uentryList_compareParams (c1->contents.fcn->params, 
2379                                               c2->contents.fcn->params));
2380           }
2381       }
2382     case CT_EXPFCN:
2383       return (ctype_compare (c1->contents.base, c2->contents.base));
2384     case CT_STRUCT:
2385     case CT_UNION:
2386       /* evs 2000-07-28: this block was missing! */
2387       if (strict) {
2388         int ncmp = cstring_compare (c1->contents.su->name,
2389                                     c2->contents.su->name);
2390
2391         if (ncmp != 0) {
2392           if (isFakeTag (c1->contents.su->name) 
2393               && isFakeTag (c2->contents.su->name)) {
2394             ; /* If they are both fake struct tags, don't require match. */
2395           } else {
2396             return ncmp;
2397           }
2398         }
2399       }
2400
2401       DPRINTF (("Comparing fields: %s / %s",
2402                 ctbase_unparse (c1),
2403                 ctbase_unparse (c2)));
2404
2405       return (uentryList_compareFields (c1->contents.su->fields,
2406                                         c2->contents.su->fields));
2407     case CT_CONJ:
2408       {
2409         COMPARERETURN (ctype_compare (c1->contents.conj->a,
2410                                       c2->contents.conj->a));
2411         COMPARERETURN (ctype_compare (c1->contents.conj->b,
2412                                       c2->contents.conj->b));
2413         return (bool_compare (c1->contents.conj->isExplicit,
2414                               c2->contents.conj->isExplicit));
2415       }
2416     }
2417   BADEXIT;
2418 }
2419
2420 static int
2421 ctbase_compareStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2422 {
2423  return (ctbase_compare (c1, c2, TRUE));
2424 }
2425
2426 static bool ctbase_equivStrict (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2427 {
2428   return (ctbase_compareStrict (c1,c2) == 0);
2429 }
2430
2431 static bool ctbase_equiv (/*@notnull@*/ ctbase c1, /*@notnull@*/ ctbase c2)
2432 {
2433   return (ctbase_compare (c1, c2, FALSE) == 0);
2434 }
2435
2436 static bool
2437 ctbase_isKind (/*@notnull@*/ ctbase c, ctuid kind)
2438 {
2439   ctuid ck = c->type;
2440
2441   if (ck == kind)
2442     return TRUE;
2443
2444   if (ck == CT_CONJ)
2445     return (ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->a), kind) ||
2446             ctbase_isKind (ctype_getCtbaseSafe (c->contents.conj->b), kind));
2447
2448   return FALSE;
2449 }
2450
2451 static bool
2452 ctbase_isKind2 (/*@notnull@*/ ctbase c, ctuid kind1, ctuid kind2)
2453 {
2454   ctuid ck = c->type;
2455
2456   if (ck == kind1 || ck == kind2)
2457     return TRUE;
2458
2459   if (ck == CT_CONJ)
2460     return (ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->a), kind1, kind2) ||
2461        ctbase_isKind2 (ctype_getCtbaseSafe (c->contents.conj->b), kind1, kind2));
2462
2463   return FALSE;
2464 }
2465
2466 static bool
2467 ctbase_isAbstract (/*@notnull@*/ ctbase c)
2468 {
2469   return (c->type == CT_ABST);
2470 }
2471
2472 static bool ctbase_isUA (ctbase c) 
2473 {
2474   return (ctbase_isDefined (c) && ((c)->type == CT_USER || (c)->type == CT_ABST));
2475 }
2476
2477 static bool
2478 ctbase_almostEqual (ctbase c1, ctbase c2)
2479 {
2480   ctuid c1tid, c2tid;
2481   
2482   /* undefined types never match */
2483   
2484   if (ctbase_isUndefined (c1) || ctbase_isUndefined (c2))
2485     return FALSE;
2486   
2487   c1tid = c1->type;
2488   c2tid = c2->type;
2489   
2490   if (c1tid == CT_FIXEDARRAY && c2tid == CT_ARRAY)
2491     {
2492       return (ctbase_almostEqual (ctype_getCtbase (c1->contents.farray->base),
2493                                   ctype_getCtbase (c2->contents.base)));
2494     }
2495   
2496   if (c2tid == CT_FIXEDARRAY && c1tid == CT_ARRAY)
2497     {
2498       return (ctbase_almostEqual (ctype_getCtbase (c1->contents.base),
2499                                   ctype_getCtbase (c2->contents.farray->base)));
2500     }
2501   
2502   if (c1tid != c2tid)
2503     return FALSE;
2504
2505   switch (c1tid)
2506     {
2507     case CT_UNKNOWN:
2508       return TRUE;
2509     case CT_PRIM:
2510       return (cprim_equal (c1->contents.prim, c2->contents.prim));
2511     case CT_BOOL:
2512       return TRUE;
2513     case CT_ABST:
2514       return (typeId_equal (c1->contents.tid, c2->contents.tid));
2515     case CT_USER:
2516       return (typeId_equal (c1->contents.tid, c2->contents.tid));
2517     case CT_ENUM:       
2518       return (cstring_equal (c1->contents.cenum->tag, c2->contents.cenum->tag));
2519     case CT_PTR:
2520       return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2521     case CT_FIXEDARRAY:
2522       return (ctype_almostEqual (c1->contents.farray->base, 
2523                                  c2->contents.farray->base));
2524     case CT_ARRAY:
2525       return (ctype_almostEqual (c1->contents.base, c2->contents.base));
2526     case CT_FCN:
2527       return (ctype_almostEqual (c1->contents.fcn->rval, c2->contents.fcn->rval)
2528               && uentryList_matchParams (c1->contents.fcn->params, 
2529                                          c2->contents.fcn->params, FALSE, TRUE));
2530     case CT_STRUCT:
2531     case CT_UNION:
2532       if (!cstring_isEmpty (c1->contents.su->name))
2533         {
2534           return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
2535         }
2536       else
2537         {
2538           if (!cstring_isEmpty (c2->contents.su->name))
2539             {
2540               return FALSE;
2541             }
2542
2543           llcontbuglit ("ctbase_almostEqual: match fields");
2544           return (FALSE);
2545         }
2546     default:
2547       llcontbug (message ("ctbase_almostEqual: unknown type: %d\n", (int)c1tid));
2548       return (FALSE);
2549     }
2550 }
2551
2552 /*drl added July 02, 001
2553   called by ctype_getArraySize
2554 */
2555
2556 size_t ctbase_getArraySize (ctbase ctb)
2557 {
2558   /*drl 1/25/2002 fixed discovered by Jim Francis */
2559   ctbase r;
2560   
2561   llassert (ctbase_isDefined (ctb) );
2562   r = ctbase_realType (ctb);
2563   llassert (ctbase_isFixedArray(r) );
2564
2565   return (r->contents.farray->size);
2566 }
This page took 1.217165 seconds and 3 git commands to generate.