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