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