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