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