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