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