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