2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** uentryList.c (from slist_template.c)
28 # include "splintMacros.nf"
31 /*@only@*/ /*@notnull@*/ uentryList
34 uentryList s = (uentryList) dmalloc (sizeof (*s));
37 s->nspace = uentryListBASESIZE;
38 s->elements = (uentry *)
39 dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
46 uentryList_single (/*@keep@*/ uentry el)
48 uentryList s = (uentryList) dmalloc (sizeof (*s));
51 s->nspace = uentryListBASESIZE - 1;
52 s->elements = (uentry *) dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
61 uentryList_grow (uentryList s)
66 llassert (!uentryList_isUndefined (s));
68 s->nspace += uentryListBASESIZE;
70 newelements = (uentry *) dmalloc (sizeof (*newelements)
71 * (s->nelements + s->nspace));
73 for (i = 0; i < s->nelements; i++)
75 newelements[i] = s->elements[i];
79 s->elements = newelements;
82 void uentryList_clear (uentryList s)
84 if (uentryList_isUndefined (s))
90 s->nspace += s->nelements;
95 uentryList uentryList_add (uentryList s, /*@keep@*/ uentry el)
97 if (uentryList_isUndefined (s))
99 s = uentryList_new ();
106 s->elements[s->nelements] = el;
113 uentryList_unparse (uentryList s)
115 cstring st = cstring_undefined;
118 if (uentryList_isDefined (s))
120 for (i = 0; i < uentryList_size (s); i++)
124 st = message ("%q;", uentry_unparse (s->elements[i]));
127 st = message ("%q %q;", st, uentry_unparse (s->elements[i]));
134 /*@unused@*/ /*@only@*/ cstring
135 uentryList_unparseFull (uentryList s)
137 cstring st = cstring_undefined;
140 if (uentryList_isDefined (s))
142 for (i = 0; i < uentryList_size (s); i++)
146 st = message ("%q;", uentry_unparseFull (s->elements[i]));
150 st = message ("%q %q;", st, uentry_unparseFull (s->elements[i]));
158 cstring uentryList_unparseParamsComplete (uentryList s)
161 cstring st = cstring_undefined;
164 if (uentryList_isUndefined (s))
168 else if (uentryList_isVoid (s))
170 return (cstring_makeLiteral ("void"));
174 for (i = 0; i < uentryList_size (s); i++)
176 cstring cQuals, name, ctypeName;
178 cQuals = qualList_unparse(s->elements[i]->cQuals);
180 name = uentry_getName(s->elements[i]);
182 if (ctype_isFunction (uentry_getType (s->elements[i])) )
184 cur = ctype_unparseFunctionPointer(uentry_getType (s->elements[i] ), cQuals, name);
185 cstring_free(cQuals);
189 ctypeName = message("%s", ctype_unparse(uentry_getType (s->elements[i] ) ) );
191 if (ctype_isFixedArray (uentry_getType (s->elements[i] ) ) )
193 cstring aType, aSize;
194 aType = cstring_beforeChar(ctypeName, '[');
195 aSize = cstring_afterChar(ctypeName, '[');
197 cur = message ("%q %q %q %s",
198 cQuals, aType, name, aSize );
200 // cstring_free(ctypeName);
202 else if (ctype_isArray (uentry_getType (s->elements[i] ) ) )
205 aType = cstring_beforeChar(ctypeName, '[');
207 cur = message ("%s %s %s []",
208 cQuals, aType, name);
210 // cstring_free(ctypeName);
212 else if (ctype_isElips (uentry_getType (s->elements[i] ) ) )
214 cur = message(" ... ");
218 cur = message ("%s %s %s",
222 if (qualList_hasInnerConstQualifier (s->elements[i]->cQuals) )
224 cur = insertInnerConstQual(cur);
230 st = message ("%q", cur);
234 st = message ("%q, %q",
243 cstring uentryList_unparseParams (uentryList s)
246 cstring st = cstring_undefined;
249 if (uentryList_isUndefined (s))
253 else if (uentryList_isVoid (s))
255 return (cstring_makeLiteral ("void"));
259 for (i = 0; i < uentryList_size (s); i++)
263 st = message ("%s", ctype_unparse (uentry_getType (s->elements[i])));
267 st = message ("%q, %s", st, ctype_unparse (uentry_getType (s->elements[i])));
275 bool uentryList_matchParams (uentryList p1, uentryList p2, bool force, bool arg)
277 int sz1 = uentryList_size (p1);
278 int sz2 = uentryList_size (p2);
281 if (p1 == p2) return TRUE;
283 if (uentryList_isMissingParams (p1) || uentryList_isMissingParams (p2))
291 for (i = 0; i < sz1; i++)
293 if (!ctype_genMatch (uentry_getType (p1->elements[i]),
294 uentry_getType (p2->elements[i]),
295 force, arg, FALSE, FALSE))
305 uentryList_unparseAbbrev (uentryList p)
308 cstring s = cstring_undefined;
311 if (uentryList_isUndefined (p))
314 if (uentryList_size (p) == 0)
315 return cstring_makeLiteral ("void");
317 for (i = 0; i < p->nelements && i < uentryList_abbrevBreadth; i++)
321 s = message ("%q;", uentry_unparseAbbrev (p->elements[i]));
326 s = message ("%q %q;", s, uentry_unparseAbbrev (p->elements[i]));
330 if (i != uentryList_size (p))
331 s = message ("%q, ...", s);
337 uentryList_lookupDirectName (uentryList s, cstring name)
339 if (uentryList_isDefined (s))
343 for (i = 0; i < uentryList_size (s); i++)
345 if (cstring_equal (name, uentry_rawName (s->elements[i])))
356 uentryList_lookupRealName (uentryList s, cstring name)
358 if (uentryList_isDefined (s))
362 for (i = 0; i < uentryList_size (s); i++)
364 cstring uname = uentry_getName (s->elements[i]);
366 if (cstring_equal (name, uname))
368 cstring_free (uname);
372 cstring_free (uname);
379 uentryList uentryList_copy (uentryList s)
381 if (uentryList_isDefined (s))
383 uentryList t = (uentryList) dmalloc (sizeof (*t));
386 t->nelements = s->nelements;
388 t->current = s->current;
390 if (s->nelements > 0)
392 t->elements = (uentry *) dmalloc (sizeof (*t->elements) * t->nelements);
394 for (i = 0; i < s->nelements; i++)
396 t->elements[i] = uentry_copy (s->elements[i]);
408 return uentryList_undefined;
413 uentryList_free (uentryList s)
416 if (!uentryList_isUndefined (s))
420 for (i = 0; i < s->nelements; i++)
422 uentry_free (s->elements[i]);
431 uentryList_isVoid (uentryList cl)
433 if (cl != NULL && cl->nelements == 1)
435 return (ctype_isVoid (ctype_realType (uentry_getType (cl->elements[0]))));
442 uentryList_getN (uentryList p, int n)
444 llassert (uentryList_isDefined (p));
446 if (n < 0 || (n >= uentryList_size (p)))
448 llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
449 n, uentryList_size (p)));
450 return uentry_undefined;
453 return (p->elements[n]);
456 void uentryList_fixMissingNames (uentryList cl)
458 uentryList_elements (cl, ce)
460 if (!uentry_hasRealName (ce))
462 ctype ct = uentry_getType (ce);
466 uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
470 llbug (message ("uentryList_fixMissingNames: not UA: %s",
471 ctype_unparse (ct)));
474 uentry_setType (ce, ctype_int);
476 } end_uentryList_elements;
479 void uentryList_fixImpParams (uentryList cl)
482 if (context_getFlag (FLG_PARAMIMPTEMP))
484 uentryList_elements (cl, ce)
486 sRef s = uentry_getSref (ce);
487 alkind ak = sRef_getAliasKind (s);
489 if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
491 exkind ek = sRef_getExKind (s);
493 if (exkind_isKnown (ek))
495 sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
499 sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
505 } end_uentryList_elements;
510 uentryList_compareParams (uentryList s, uentryList t)
514 if (s == t) return 0;
516 if (uentryList_isUndefined (s)) return 1;
517 if (uentryList_isUndefined (t)) return -1;
519 sz = uentryList_size (s);
521 INTCOMPARERETURN (uentryList_size (t), sz);
523 for (i = 0; i < sz; i++)
525 COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
532 uentryList_compareStrict (uentryList s, uentryList t)
541 if (uentryList_isMissingParams (s))
543 if (uentryList_isMissingParams (t))
554 if (uentryList_isMissingParams (t))
560 sz = uentryList_size (s);
562 INTCOMPARERETURN (uentryList_size (t), sz);
564 for (i = 0; i < sz; i++)
566 COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
575 uentryList_compareFields (uentryList s, uentryList t)
579 if (s == t) return 0;
581 if (uentryList_isUndefined (s))
583 if (uentryList_isUndefined (t))
586 sz = uentryList_size (s);
588 if (uentryList_size (t) != sz)
590 return (int_compare (sz, uentryList_size (t)));
593 for (i = 0; i < sz; i++)
595 uentry se = s->elements[i];
596 uentry te = t->elements[i];
597 int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
601 int uc = uentry_compare (s->elements[i], t->elements[i]);
605 DPRINTF (("Bad compare: %s / %s",
606 uentry_unparseFull (s->elements [i]),
607 uentry_unparseFull (t->elements [i])));
622 uentryList_current (uentryList s)
624 llassert (uentryList_isDefined (s));
625 llassert (!(s->current < 0 || (s->current >= s->nelements)));
626 return (s->elements[s->current]);
630 uentryList_dumpParams (uentryList s)
632 cstring st = cstring_undefined;
634 if (uentryList_isUndefined (s)) return st;
636 uentryList_elements (s, current)
638 DPRINTF (("Dump param: %s", uentry_unparse (current)));
639 st = message ("%q%q,", st, uentry_dumpParam (current));
640 } end_uentryList_elements;
646 uentryList_dumpFields (uentryList s)
648 cstring st = cstring_undefined;
650 if (uentryList_isUndefined (s)) return st;
652 uentryList_elements (s, current)
654 if (!uentry_isVariable (current))
656 llassert (uentry_isFunction (current));
657 DPRINTF (("Dump field: %s", uentry_unparse (current)));
658 st = message ("%q!%q,", st, uentry_dump (current));
662 DPRINTF (("Dump field: %s", uentry_unparse (current)));
663 st = message ("%q%q,", st, uentry_dump (current));
665 } end_uentryList_elements;
670 /*@only@*/ uentryList
671 uentryList_undumpFields (char **s, fileloc loc)
673 uentryList ul = uentryList_new ();
675 while (**s != '\0' && **s != '}')
679 reader_checkChar (s, '!');
680 ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
684 ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
686 reader_checkChar (s, ',');
689 reader_checkChar (s, '}');
693 /*@only@*/ uentryList
694 uentryList_undump (char **s)
697 uentryList pn = uentryList_new ();
702 while (c != '#' && c != '@' && c != ')')
704 uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
707 if (!uentry_isUndefined (ue))
709 pn = uentryList_add (pn, ue);
716 reader_checkChar (s, ',');
721 reader_checkChar (s, ')');
726 uentryList_reset (uentryList s)
728 if (uentryList_isUndefined (s)) return;
733 uentryList_isFinished (uentryList s)
735 if (uentryList_isUndefined (s)) return TRUE;
736 return (s->current > s->nelements - 1);
740 uentryList_advanceSafe (uentryList s)
742 if (uentryList_isUndefined (s)) return;
746 if (s->current > s->nelements)
748 s->current = s->nelements;
753 uentryList_size (uentryList s)
755 if (uentryList_isUndefined (s)) return 0;
757 if (uentryList_isVoid (s))
764 uentryList_isMissingParams (uentryList s)
766 return (uentryList_isUndefined (s) || s->nelements == 0);
769 bool uentryList_hasReturned (uentryList ul)
771 uentryList_elements (ul, current)
773 if (uentry_isReturned (current)) return TRUE;
774 } end_uentryList_elements;
780 uentryList_lookupField (uentryList f, cstring name)
782 int i = uentryList_lookupDirectName (f, name);
786 return (uentryList_getN (f, i));
790 uentryList_elements (f, el)
792 if (uentry_isUnnamedVariable (el))
794 ctype ct = uentry_getType (el);
796 if (ctype_isStruct (ct) || ctype_isUnion (ct))
798 uentryList fields = ctype_getFields (ct);
799 uentry ue = uentryList_lookupField (fields, name);
801 if (uentry_isValid (ue))
808 end_uentryList_elements ;
810 return uentry_undefined;
814 /*@only@*/ uentryList
815 uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
817 DPRINTF (("Merge: %s + %s", uentryList_unparse (f1), uentryList_unparse (f2)));
819 if (uentryList_isUndefined (f1))
824 if (uentryList_isDefined (f2))
826 uentryList_elements (f2, current)
828 uentry old = uentryList_lookupField (f1, uentry_rawName (current));
830 if (uentry_isValid (old))
834 message ("Field name reused: %s", uentry_rawName (current)),
835 uentry_whereDefined (current));
836 llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
837 uentry_whereDefined (old));
840 /* okay to use exposed current since f2 is killed */
841 /*@-exposetrans@*/ /*@-dependenttrans@*/
842 f1 = uentryList_add (f1, current);
843 /*@=exposetrans@*/ /*@=dependenttrans@*/
845 } end_uentryList_elements;
847 sfree (f2->elements);
855 uentryList_showFieldDifference (uentryList p1, uentryList p2)
860 llassert (NOALIAS (p1, p2));
861 llassert (uentryList_isDefined (p1));
862 llassert (uentryList_isDefined (p2));
864 for (index = 0; index < p1->nelements; index++)
866 cp1 = p1->elements[index];
868 if (index == p2->nelements)
871 (message ("Field present in %s, missing in %rdeclaration: %q",
872 uentry_specDeclName (cp1),
873 uentry_isDeclared (cp1),
874 uentry_unparse (cp1)),
875 uentry_whereEither (cp1));
879 cp2 = p2->elements[index];
881 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
884 (message ("Field %s in %s corresponds to %s in %rdeclaration",
885 uentry_rawName (cp1),
886 uentry_specOrDefName (cp1),
887 uentry_rawName (cp2),
888 uentry_isCodeDefined (cp1)),
889 uentry_whereDefined (cp2));
890 uentry_showWhereLastPlain (cp1);
895 /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
897 if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
900 (message ("Field %s %rdeclared as %s, %s as %s",
901 uentry_rawName (cp2),
902 uentry_isCodeDefined (cp1),
903 ctype_unparse (uentry_getType (cp1)),
904 uentry_specOrDefName (cp2),
905 ctype_unparse (uentry_getType (cp2))),
906 uentry_whereDefined (cp2));
907 uentry_showWhereLastPlain (cp1);
913 if (index != p2->nelements)
915 cp2 = p2->elements[index];
918 (message ("Extra field in new declaration: %q",
919 uentry_unparse (cp2)),
920 uentry_whereEither (cp2));
925 llbug (message ("uentryList_showFieldDifference: match: %q / %q",
926 uentryList_unparse (p1), uentryList_unparse (p2)));
930 uentryList_equivFields (uentryList p1, uentryList p2)
932 return (uentryList_compareFields (p1, p2) == 0);
936 uentryList_matchFields (uentryList p1, uentryList p2)
946 if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
951 if (uentryList_size (p1) != uentryList_size (p2))
956 for (index = 0; index < p1->nelements; index++)
958 cp1 = p1->elements[index];
959 cp2 = p2->elements[index];
963 ** Should compare uentry's --- need to fix report errors too.
966 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
967 && (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))