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