Less permissive syntax for notreached comment.
[splint-patched.git] / src / uentryList.c
blobb6ee94fbf4ad32bdad430fcecdce9cd9bd8d7a00
1 /*
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.
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"
29 # include "basic.h"
31 /*@only@*/ /*@notnull@*/ uentryList
32 uentryList_new (void)
34 uentryList s = (uentryList) dmalloc (sizeof (*s));
36 s->nelements = 0;
37 s->nspace = uentryListBASESIZE;
38 s->elements = (uentry *)
39 dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
40 s->current = 0;
42 return (s);
45 /*@only@*/ uentryList
46 uentryList_single (/*@keep@*/ uentry el)
48 uentryList s = (uentryList) dmalloc (sizeof (*s));
50 s->nelements = 1;
51 s->nspace = uentryListBASESIZE - 1;
52 s->elements = (uentry *) dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
54 s->elements[0] = el;
55 s->current = 0;
57 return (s);
60 static void
61 uentryList_grow (uentryList s)
63 int i;
64 uentry *newelements;
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];
78 sfree (s->elements);
79 s->elements = newelements;
82 void uentryList_clear (uentryList s)
84 if (uentryList_isUndefined (s))
88 else
90 s->nspace += s->nelements;
91 s->nelements = 0;
95 uentryList uentryList_add (uentryList s, /*@keep@*/ uentry el)
97 if (uentryList_isUndefined (s))
99 s = uentryList_new ();
102 if (s->nspace <= 0)
103 uentryList_grow (s);
105 s->nspace--;
106 s->elements[s->nelements] = el;
107 s->nelements++;
109 return s;
112 /*@only@*/ cstring
113 uentryList_unparse (uentryList s)
115 cstring st = cstring_undefined;
116 int i;
118 if (uentryList_isDefined (s))
120 for (i = 0; i < uentryList_size (s); i++)
122 if (i == 0)
124 st = message ("%q;", uentry_unparse (s->elements[i]));
126 else
127 st = message ("%q %q;", st, uentry_unparse (s->elements[i]));
131 return (st);
134 /*@unused@*/ /*@only@*/ cstring
135 uentryList_unparseFull (uentryList s)
137 cstring st = cstring_undefined;
138 int i;
140 if (uentryList_isDefined (s))
142 for (i = 0; i < uentryList_size (s); i++)
144 if (i == 0)
146 st = message ("%q;", uentry_unparseFull (s->elements[i]));
148 else
150 st = message ("%q %q;", st, uentry_unparseFull (s->elements[i]));
155 return (st);
158 cstring uentryList_unparseParams (uentryList s)
160 int i;
161 cstring st = cstring_undefined;
164 if (uentryList_isUndefined (s))
166 return st;
168 else if (uentryList_isVoid (s))
170 return (cstring_makeLiteral ("void"));
172 else
174 for (i = 0; i < uentryList_size (s); i++)
176 if (i == 0)
178 st = message ("%s", ctype_unparse (uentry_getType (s->elements[i])));
180 else
182 st = message ("%q, %s", st, ctype_unparse (uentry_getType (s->elements[i])));
186 return st;
190 bool uentryList_matchParams (uentryList p1, uentryList p2, bool force, bool arg)
192 int sz1 = uentryList_size (p1);
193 int sz2 = uentryList_size (p2);
194 int i;
196 if (p1 == p2) return TRUE;
198 if (uentryList_isMissingParams (p1) || uentryList_isMissingParams (p2))
200 return TRUE;
203 if (sz1 != sz2)
204 return FALSE;
206 for (i = 0; i < sz1; i++)
208 if (!ctype_genMatch (uentry_getType (p1->elements[i]),
209 uentry_getType (p2->elements[i]),
210 force, arg, FALSE, FALSE))
212 return FALSE;
216 return TRUE;
219 /*@only@*/ cstring
220 uentryList_unparseAbbrev (uentryList p)
222 bool first = TRUE;
223 cstring s = cstring_undefined;
224 int i = 0;
226 if (uentryList_isUndefined (p))
227 return s;
229 if (uentryList_size (p) == 0)
230 return cstring_makeLiteral ("void");
232 for (i = 0; i < p->nelements && i < uentryList_abbrevBreadth; i++)
234 if (first)
236 s = message ("%q;", uentry_unparseAbbrev (p->elements[i]));
237 first = FALSE;
239 else
241 s = message ("%q %q;", s, uentry_unparseAbbrev (p->elements[i]));
245 if (i != uentryList_size (p))
246 s = message ("%q, ...", s);
248 return (s);
251 static int
252 uentryList_lookupDirectName (uentryList s, cstring name)
254 if (uentryList_isDefined (s))
256 int i;
258 for (i = 0; i < uentryList_size (s); i++)
260 if (cstring_equal (name, uentry_rawName (s->elements[i])))
262 return i;
267 return -1;
271 uentryList_lookupRealName (uentryList s, cstring name)
273 if (uentryList_isDefined (s))
275 int i;
277 for (i = 0; i < uentryList_size (s); i++)
279 cstring uname = uentry_getName (s->elements[i]);
281 if (cstring_equal (name, uname))
283 cstring_free (uname);
284 return i;
287 cstring_free (uname);
291 return -1;
294 uentryList uentryList_copy (uentryList s)
296 if (uentryList_isDefined (s))
298 uentryList t = (uentryList) dmalloc (sizeof (*t));
299 int i;
301 t->nelements = s->nelements;
302 t->nspace = 0;
303 t->current = s->current;
305 if (s->nelements > 0)
307 t->elements = (uentry *) dmalloc (sizeof (*t->elements) * t->nelements);
309 for (i = 0; i < s->nelements; i++)
311 t->elements[i] = uentry_copy (s->elements[i]);
314 else
316 t->elements = NULL;
319 return t;
321 else
323 return uentryList_undefined;
327 void
328 uentryList_free (uentryList s)
330 if (!uentryList_isUndefined (s))
332 int i;
334 for (i = 0; i < s->nelements; i++)
336 uentry_free (s->elements[i]);
339 sfree (s->elements);
340 sfree (s);
344 bool
345 uentryList_isVoid (uentryList cl)
347 if (cl != NULL && cl->nelements == 1)
349 return (ctype_isVoid (ctype_realType (uentry_getType (cl->elements[0]))));
352 return FALSE;
355 /*@exposed@*/ uentry
356 uentryList_getN (uentryList p, int n)
358 llassert (uentryList_isDefined (p));
360 if (n < 0 || (n >= uentryList_size (p)))
362 llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
363 n, uentryList_size (p)));
364 return uentry_undefined;
367 return (p->elements[n]);
370 void uentryList_fixMissingNames (uentryList cl)
372 uentryList_elements (cl, ce)
374 if (!uentry_hasRealName (ce))
376 ctype ct = uentry_getType (ce);
378 if (ctype_isUA (ct))
380 uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
382 else
384 llbug (message ("uentryList_fixMissingNames: not UA: %s",
385 ctype_unparse (ct)));
388 uentry_setType (ce, ctype_int);
390 } end_uentryList_elements;
393 void uentryList_fixImpParams (uentryList cl)
396 if (context_getFlag (FLG_PARAMIMPTEMP))
398 uentryList_elements (cl, ce)
400 sRef s = uentry_getSref (ce);
401 alkind ak = sRef_getAliasKind (s);
403 if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
405 exkind ek = sRef_getExKind (s);
407 if (exkind_isKnown (ek))
409 sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
411 else
413 sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
416 else
419 } end_uentryList_elements;
424 uentryList_compareParams (uentryList s, uentryList t)
426 int i, sz;
428 if (s == t) return 0;
430 if (uentryList_isUndefined (s)) return 1;
431 if (uentryList_isUndefined (t)) return -1;
433 sz = uentryList_size (s);
435 INTCOMPARERETURN (uentryList_size (t), sz);
437 for (i = 0; i < sz; i++)
439 COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
442 return 0;
446 uentryList_compareStrict (uentryList s, uentryList t)
448 int i, sz;
450 if (s == t)
452 return 0;
455 if (uentryList_isMissingParams (s))
457 if (uentryList_isMissingParams (t))
459 return 0;
461 else
463 return 1;
466 else
468 if (uentryList_isMissingParams (t))
470 return -1;
472 else
474 sz = uentryList_size (s);
476 INTCOMPARERETURN (uentryList_size (t), sz);
478 for (i = 0; i < sz; i++)
480 COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
483 return 0;
489 uentryList_compareFields (uentryList s, uentryList t)
491 int i, sz;
493 if (s == t) return 0;
495 if (uentryList_isUndefined (s))
496 return 1;
497 if (uentryList_isUndefined (t))
498 return -1;
500 sz = uentryList_size (s);
502 if (uentryList_size (t) != sz)
504 return (int_compare (sz, uentryList_size (t)));
507 for (i = 0; i < sz; i++)
509 uentry se = s->elements[i];
510 uentry te = t->elements[i];
511 int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
513 if (namecmp == 0)
515 int uc = uentry_compare (s->elements[i], t->elements[i]);
517 if (uc != 0)
519 DPRINTF (("Bad compare: %s / %s",
520 uentry_unparseFull (s->elements [i]),
521 uentry_unparseFull (t->elements [i])));
523 return uc;
526 else
528 return (namecmp);
532 return 0;
535 /*@exposed@*/ uentry
536 uentryList_current (uentryList s)
538 llassert (uentryList_isDefined (s));
539 llassert (!(s->current < 0 || (s->current >= s->nelements)));
540 return (s->elements[s->current]);
543 cstring
544 uentryList_dumpParams (uentryList s)
546 cstring st = cstring_undefined;
548 if (uentryList_isUndefined (s)) return st;
550 uentryList_elements (s, current)
552 DPRINTF (("Dump param: %s", uentry_unparse (current)));
553 st = message ("%q%q,", st, uentry_dumpParam (current));
554 } end_uentryList_elements;
556 return st;
559 /*@only@*/ cstring
560 uentryList_dumpFields (uentryList s)
562 cstring st = cstring_undefined;
564 if (uentryList_isUndefined (s)) return st;
566 uentryList_elements (s, current)
568 if (!uentry_isVariable (current))
570 llassert (uentry_isFunction (current));
571 DPRINTF (("Dump field: %s", uentry_unparse (current)));
572 st = message ("%q!%q,", st, uentry_dump (current));
574 else
576 DPRINTF (("Dump field: %s", uentry_unparse (current)));
577 st = message ("%q%q,", st, uentry_dump (current));
579 } end_uentryList_elements;
581 return st;
584 /*@only@*/ uentryList
585 uentryList_undumpFields (char **s, fileloc loc)
587 uentryList ul = uentryList_new ();
589 while (**s != '\0' && **s != '}')
591 if (**s == '!')
593 reader_checkChar (s, '!');
594 ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
596 else
598 ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
600 reader_checkChar (s, ',');
603 reader_checkChar (s, '}');
604 return ul;
607 /*@only@*/ uentryList
608 uentryList_undump (char **s)
610 char c;
611 uentryList pn = uentryList_new ();
612 int paramno = 0;
614 c = **s;
616 while (c != '#' && c != '@' && c != ')')
618 uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
621 if (!uentry_isUndefined (ue))
623 pn = uentryList_add (pn, ue);
625 else
627 uentry_free (ue);
630 reader_checkChar (s, ',');
631 c = **s;
632 paramno++;
635 reader_checkChar (s, ')');
636 return pn;
639 void
640 uentryList_reset (uentryList s)
642 if (uentryList_isUndefined (s)) return;
643 s->current = 0;
646 bool
647 uentryList_isFinished (uentryList s)
649 if (uentryList_isUndefined (s)) return TRUE;
650 return (s->current > s->nelements - 1);
653 void
654 uentryList_advanceSafe (uentryList s)
656 if (uentryList_isUndefined (s)) return;
658 s->current++;
660 if (s->current > s->nelements)
662 s->current = s->nelements;
667 uentryList_size (uentryList s)
669 if (uentryList_isUndefined (s)) return 0;
671 if (uentryList_isVoid (s))
672 return 0;
674 return s->nelements;
677 bool
678 uentryList_isMissingParams (uentryList s)
680 return (uentryList_isUndefined (s) || s->nelements == 0);
683 bool uentryList_hasReturned (uentryList ul)
685 uentryList_elements (ul, current)
687 if (uentry_isReturned (current)) return TRUE;
688 } end_uentryList_elements;
690 return FALSE;
693 /*@exposed@*/ uentry
694 uentryList_lookupField (uentryList f, cstring name)
696 int i = uentryList_lookupDirectName (f, name);
698 if (i >= 0)
700 return (uentryList_getN (f, i));
702 else
704 uentryList_elements (f, el)
706 if (uentry_isUnnamedVariable (el))
708 ctype ct = uentry_getType (el);
710 if (ctype_isStruct (ct) || ctype_isUnion (ct))
712 uentryList fields = ctype_getFields (ct);
713 uentry ue = uentryList_lookupField (fields, name);
715 if (uentry_isValid (ue))
717 return ue;
722 end_uentryList_elements ;
724 return uentry_undefined;
728 /*@only@*/ uentryList
729 uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
731 DPRINTF (("Merge: %s + %s", uentryList_unparse (f1), uentryList_unparse (f2)));
733 if (uentryList_isUndefined (f1))
735 return (f2);
738 if (uentryList_isDefined (f2))
740 uentryList_elements (f2, current)
742 uentry old = uentryList_lookupField (f1, uentry_rawName (current));
744 if (uentry_isValid (old))
746 voptgenerror
747 (FLG_SYNTAX,
748 message ("Field name reused: %s", uentry_rawName (current)),
749 uentry_whereDefined (current));
750 llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
751 uentry_whereDefined (old));
754 /* okay to use exposed current since f2 is killed */
755 /*@-exposetrans@*/ /*@-dependenttrans@*/
756 f1 = uentryList_add (f1, current);
757 /*@=exposetrans@*/ /*@=dependenttrans@*/
759 } end_uentryList_elements;
761 sfree (f2->elements);
762 sfree (f2);
765 return (f1);
768 void
769 uentryList_showFieldDifference (uentryList p1, uentryList p2)
771 uentry cp1, cp2;
772 int index;
774 llassert (NOALIAS (p1, p2));
775 llassert (uentryList_isDefined (p1));
776 llassert (uentryList_isDefined (p2));
778 for (index = 0; index < p1->nelements; index++)
780 cp1 = p1->elements[index];
782 if (index == p2->nelements)
784 llgenindentmsg
785 (message ("Field present in %s, missing in %rdeclaration: %q",
786 uentry_specDeclName (cp1),
787 uentry_isDeclared (cp1),
788 uentry_unparse (cp1)),
789 uentry_whereEither (cp1));
790 return;
793 cp2 = p2->elements[index];
795 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
797 llgenindentmsg
798 (message ("Field %s in %s corresponds to %s in %rdeclaration",
799 uentry_rawName (cp1),
800 uentry_specOrDefName (cp1),
801 uentry_rawName (cp2),
802 uentry_isCodeDefined (cp1)),
803 uentry_whereDefined (cp2));
804 uentry_showWhereLastPlain (cp1);
805 return;
807 else
809 /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
811 if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
813 llgenindentmsg
814 (message ("Field %s %rdeclared as %s, %s as %s",
815 uentry_rawName (cp2),
816 uentry_isCodeDefined (cp1),
817 ctype_unparse (uentry_getType (cp1)),
818 uentry_specOrDefName (cp2),
819 ctype_unparse (uentry_getType (cp2))),
820 uentry_whereDefined (cp2));
821 uentry_showWhereLastPlain (cp1);
822 return;
827 if (index != p2->nelements)
829 cp2 = p2->elements[index];
831 llgenindentmsg
832 (message ("Extra field in new declaration: %q",
833 uentry_unparse (cp2)),
834 uentry_whereEither (cp2));
836 return;
839 llbug (message ("uentryList_showFieldDifference: match: %q / %q",
840 uentryList_unparse (p1), uentryList_unparse (p2)));
843 bool
844 uentryList_equivFields (uentryList p1, uentryList p2)
846 return (uentryList_compareFields (p1, p2) == 0);
849 bool
850 uentryList_matchFields (uentryList p1, uentryList p2)
852 int index;
853 uentry cp1, cp2;
855 if (p1 == p2)
857 return (TRUE);
860 if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
862 return (TRUE);
865 if (uentryList_size (p1) != uentryList_size (p2))
867 return FALSE;
870 for (index = 0; index < p1->nelements; index++)
872 cp1 = p1->elements[index];
873 cp2 = p2->elements[index];
876 ** Should compare uentry's --- need to fix report errors too.
879 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
880 && (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))
882 return FALSE;
886 return TRUE;