2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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_unparseParams (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
++)
178 st
= message ("%s", ctype_unparse (uentry_getType (s
->elements
[i
])));
182 st
= message ("%q, %s", st
, ctype_unparse (uentry_getType (s
->elements
[i
])));
190 bool uentryList_matchParams (uentryList p1
, uentryList p2
, bool force
, bool arg
)
192 int sz1
= uentryList_size (p1
);
193 int sz2
= uentryList_size (p2
);
196 if (p1
== p2
) return TRUE
;
198 if (uentryList_isMissingParams (p1
) || uentryList_isMissingParams (p2
))
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
))
220 uentryList_unparseAbbrev (uentryList p
)
223 cstring s
= cstring_undefined
;
226 if (uentryList_isUndefined (p
))
229 if (uentryList_size (p
) == 0)
230 return cstring_makeLiteral ("void");
232 for (i
= 0; i
< p
->nelements
&& i
< uentryList_abbrevBreadth
; i
++)
236 s
= message ("%q;", uentry_unparseAbbrev (p
->elements
[i
]));
241 s
= message ("%q %q;", s
, uentry_unparseAbbrev (p
->elements
[i
]));
245 if (i
!= uentryList_size (p
))
246 s
= message ("%q, ...", s
);
252 uentryList_lookupDirectName (uentryList s
, cstring name
)
254 if (uentryList_isDefined (s
))
258 for (i
= 0; i
< uentryList_size (s
); i
++)
260 if (cstring_equal (name
, uentry_rawName (s
->elements
[i
])))
271 uentryList_lookupRealName (uentryList s
, cstring name
)
273 if (uentryList_isDefined (s
))
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
);
287 cstring_free (uname
);
294 uentryList
uentryList_copy (uentryList s
)
296 if (uentryList_isDefined (s
))
298 uentryList t
= (uentryList
) dmalloc (sizeof (*t
));
301 t
->nelements
= s
->nelements
;
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
]);
323 return uentryList_undefined
;
328 uentryList_free (uentryList s
)
330 if (!uentryList_isUndefined (s
))
334 for (i
= 0; i
< s
->nelements
; i
++)
336 uentry_free (s
->elements
[i
]);
345 uentryList_isVoid (uentryList cl
)
347 if (cl
!= NULL
&& cl
->nelements
== 1)
349 return (ctype_isVoid (ctype_realType (uentry_getType (cl
->elements
[0]))));
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
);
380 uentry_setName (ce
, usymtab_getTypeEntryName (ctype_typeId (ct
)));
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
);
413 sRef_setAliasKind (s
, AK_IMPTEMP
, fileloc_undefined
);
419 } end_uentryList_elements
;
424 uentryList_compareParams (uentryList s
, uentryList t
)
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
]));
446 uentryList_compareStrict (uentryList s
, uentryList t
)
455 if (uentryList_isMissingParams (s
))
457 if (uentryList_isMissingParams (t
))
468 if (uentryList_isMissingParams (t
))
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
]));
489 uentryList_compareFields (uentryList s
, uentryList t
)
493 if (s
== t
) return 0;
495 if (uentryList_isUndefined (s
))
497 if (uentryList_isUndefined (t
))
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
));
515 int uc
= uentry_compare (s
->elements
[i
], t
->elements
[i
]);
519 DPRINTF (("Bad compare: %s / %s",
520 uentry_unparseFull (s
->elements
[i
]),
521 uentry_unparseFull (t
->elements
[i
])));
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
]);
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
;
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
));
576 DPRINTF (("Dump field: %s", uentry_unparse (current
)));
577 st
= message ("%q%q,", st
, uentry_dump (current
));
579 } end_uentryList_elements
;
584 /*@only@*/ uentryList
585 uentryList_undumpFields (char **s
, fileloc loc
)
587 uentryList ul
= uentryList_new ();
589 while (**s
!= '\0' && **s
!= '}')
593 reader_checkChar (s
, '!');
594 ul
= uentryList_add (ul
, uentry_undump (ekind_function
, loc
, s
));
598 ul
= uentryList_add (ul
, uentry_undump (ekind_variable
, loc
, s
));
600 reader_checkChar (s
, ',');
603 reader_checkChar (s
, '}');
607 /*@only@*/ uentryList
608 uentryList_undump (char **s
)
611 uentryList pn
= uentryList_new ();
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
);
630 reader_checkChar (s
, ',');
635 reader_checkChar (s
, ')');
640 uentryList_reset (uentryList s
)
642 if (uentryList_isUndefined (s
)) return;
647 uentryList_isFinished (uentryList s
)
649 if (uentryList_isUndefined (s
)) return TRUE
;
650 return (s
->current
> s
->nelements
- 1);
654 uentryList_advanceSafe (uentryList s
)
656 if (uentryList_isUndefined (s
)) return;
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
))
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
;
694 uentryList_lookupField (uentryList f
, cstring name
)
696 int i
= uentryList_lookupDirectName (f
, name
);
700 return (uentryList_getN (f
, i
));
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
))
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
))
738 if (uentryList_isDefined (f2
))
740 uentryList_elements (f2
, current
)
742 uentry old
= uentryList_lookupField (f1
, uentry_rawName (current
));
744 if (uentry_isValid (old
))
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
);
769 uentryList_showFieldDifference (uentryList p1
, uentryList p2
)
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
)
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
));
793 cp2
= p2
->elements
[index
];
795 if (!(cstring_equal (uentry_rawName (cp1
), uentry_rawName (cp2
))))
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
);
809 /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
811 if (!ctype_almostEqual (uentry_getType (cp1
), uentry_getType (cp2
)))
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
);
827 if (index
!= p2
->nelements
)
829 cp2
= p2
->elements
[index
];
832 (message ("Extra field in new declaration: %q",
833 uentry_unparse (cp2
)),
834 uentry_whereEither (cp2
));
839 llbug (message ("uentryList_showFieldDifference: match: %q / %q",
840 uentryList_unparse (p1
), uentryList_unparse (p2
)));
844 uentryList_equivFields (uentryList p1
, uentryList p2
)
846 return (uentryList_compareFields (p1
, p2
) == 0);
850 uentryList_matchFields (uentryList p1
, uentryList p2
)
860 if (uentryList_isEmpty (p1
) || uentryList_isEmpty (p2
))
865 if (uentryList_size (p1
) != uentryList_size (p2
))
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
)))))