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