]> andersk Git - splint.git/blame - src/uentryList.c
Fixed all /*@i...@*/ tags (except 1).
[splint.git] / src / uentryList.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
616915dd 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** uentryList.c (from slist_template.c)
26*/
27
1b8ae690 28# include "splintMacros.nf"
616915dd 29# include "basic.h"
30
31/*@only@*/ /*@notnull@*/ uentryList
32uentryList_new ()
33{
34 uentryList s = (uentryList) dmalloc (sizeof (*s));
35
36 s->nelements = 0;
37 s->nspace = uentryListBASESIZE;
38 s->elements = (uentry *)
39 dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
40 s->current = 0;
41
42 return (s);
43}
44
45/*@only@*/ uentryList
46uentryList_single (/*@keep@*/ uentry el)
47{
48 uentryList s = (uentryList) dmalloc (sizeof (*s));
49
50 s->nelements = 1;
51 s->nspace = uentryListBASESIZE - 1;
52 s->elements = (uentry *) dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
53
54 s->elements[0] = el;
55 s->current = 0;
56
57 return (s);
58}
59
60static void
61uentryList_grow (uentryList s)
62{
63 int i;
64 uentry *newelements;
65
66 llassert (!uentryList_isUndefined (s));
67
68 s->nspace += uentryListBASESIZE;
69
70 newelements = (uentry *) dmalloc (sizeof (*newelements)
71 * (s->nelements + s->nspace));
72
73 for (i = 0; i < s->nelements; i++)
74 {
75 newelements[i] = s->elements[i];
76 }
77
78 sfree (s->elements);
79 s->elements = newelements;
80}
81
82void uentryList_clear (uentryList s)
83{
84 if (uentryList_isUndefined (s))
85 {
86 ;
87 }
88 else
89 {
90 s->nspace += s->nelements;
91 s->nelements = 0;
92 }
93}
94
95uentryList uentryList_add (uentryList s, /*@keep@*/ uentry el)
96{
97 if (uentryList_isUndefined (s))
98 {
99 s = uentryList_new ();
100 }
101
102 if (s->nspace <= 0)
103 uentryList_grow (s);
104
105 s->nspace--;
106 s->elements[s->nelements] = el;
107 s->nelements++;
108
109 return s;
110}
111
112/*@only@*/ cstring
113 uentryList_unparse (uentryList s)
114{
115 cstring st = cstring_undefined;
116 int i;
117
118 if (uentryList_isDefined (s))
119 {
120 for (i = 0; i < uentryList_size (s); i++)
121 {
122 if (i == 0)
123 {
124 st = message ("%q;", uentry_unparse (s->elements[i]));
125 }
126 else
127 st = message ("%q %q;", st, uentry_unparse (s->elements[i]));
128 }
129 }
130
131 return (st);
132}
133
134/*@unused@*/ /*@only@*/ cstring
135 uentryList_unparseFull (uentryList s)
136{
137 cstring st = cstring_undefined;
138 int i;
139
140 if (uentryList_isDefined (s))
141 {
142 for (i = 0; i < uentryList_size (s); i++)
143 {
144 if (i == 0)
145 {
146 st = message ("%q;", uentry_unparseFull (s->elements[i]));
147 }
148 else
149 {
150 st = message ("%q %q;", st, uentry_unparseFull (s->elements[i]));
151 }
152 }
153 }
154
155 return (st);
156}
157
158cstring uentryList_unparseParams (uentryList s)
159{
160 int i;
161 cstring st = cstring_undefined;
162
163
164 if (uentryList_isUndefined (s))
165 {
166 return st;
167 }
168 else if (uentryList_isVoid (s))
169 {
170 return (cstring_makeLiteral ("void"));
171 }
172 else
173 {
174 for (i = 0; i < uentryList_size (s); i++)
175 {
176 if (i == 0)
177 {
178 st = message ("%s", ctype_unparse (uentry_getType (s->elements[i])));
179 }
180 else
181 {
182 st = message ("%q, %s", st, ctype_unparse (uentry_getType (s->elements[i])));
183 }
184 }
185
186 return st;
187 }
188}
189
190bool uentryList_matchParams (uentryList p1, uentryList p2, bool force, bool arg)
191{
192 int sz1 = uentryList_size (p1);
193 int sz2 = uentryList_size (p2);
194 int i;
195
196 if (p1 == p2) return TRUE;
197
198 if (uentryList_isMissingParams (p1) || uentryList_isMissingParams (p2))
199 {
200 return TRUE;
201 }
202
203 if (sz1 != sz2)
204 return FALSE;
205
206 for (i = 0; i < sz1; i++)
207 {
208 if (!ctype_genMatch (uentry_getType (p1->elements[i]),
209 uentry_getType (p2->elements[i]),
210 force, arg, FALSE, FALSE))
211 {
212 return FALSE;
213 }
214 }
215
216 return TRUE;
217}
218
219/*@only@*/ cstring
220uentryList_unparseAbbrev (uentryList p)
221{
222 bool first = TRUE;
223 cstring s = cstring_undefined;
224 int i = 0;
225
226 if (uentryList_isUndefined (p))
227 return s;
228
229 if (uentryList_size (p) == 0)
230 return cstring_makeLiteral ("void");
231
abd7f895 232 for (i = 0; i < p->nelements && i < uentryList_abbrevBreadth; i++)
616915dd 233 {
234 if (first)
235 {
236 s = message ("%q;", uentry_unparseAbbrev (p->elements[i]));
237 first = FALSE;
238 }
239 else
240 {
241 s = message ("%q %q;", s, uentry_unparseAbbrev (p->elements[i]));
242 }
243 }
244
245 if (i != uentryList_size (p))
246 s = message ("%q, ...", s);
247
248 return (s);
249}
250
251static int
252uentryList_lookupDirectName (uentryList s, cstring name)
253{
254 if (uentryList_isDefined (s))
255 {
256 int i;
257
258 for (i = 0; i < uentryList_size (s); i++)
259 {
260 if (cstring_equal (name, uentry_rawName (s->elements[i])))
261 {
262 return i;
263 }
264 }
265 }
266
267 return -1;
268}
269
270int
271uentryList_lookupRealName (uentryList s, cstring name)
272{
273 if (uentryList_isDefined (s))
274 {
275 int i;
276
277 for (i = 0; i < uentryList_size (s); i++)
278 {
279 cstring uname = uentry_getName (s->elements[i]);
280
281 if (cstring_equal (name, uname))
282 {
283 cstring_free (uname);
284 return i;
285 }
286
287 cstring_free (uname);
288 }
289 }
290
291 return -1;
292}
293
294uentryList uentryList_copy (uentryList s)
295{
616915dd 296 if (uentryList_isDefined (s))
297 {
298 uentryList t = (uentryList) dmalloc (sizeof (*t));
299 int i;
300
301 t->nelements = s->nelements;
302 t->nspace = 0;
303 t->current = s->current;
304
305 if (s->nelements > 0)
306 {
307 t->elements = (uentry *) dmalloc (sizeof (*t->elements) * t->nelements);
308
309 for (i = 0; i < s->nelements; i++)
310 {
28bf4b0b 311 t->elements[i] = uentry_copy (s->elements[i]);
312 }
616915dd 313 }
314 else
315 {
316 t->elements = NULL;
317 }
28bf4b0b 318
616915dd 319 return t;
320 }
321 else
322 {
323 return uentryList_undefined;
324 }
325}
326
327void
328uentryList_free (uentryList s)
329{
616915dd 330 if (!uentryList_isUndefined (s))
331 {
332 int i;
333
334 for (i = 0; i < s->nelements; i++)
335 {
336 uentry_free (s->elements[i]);
337 }
338
339 sfree (s->elements);
340 sfree (s);
341 }
342}
343
b73d1009 344void
345uentryList_freeShallow (uentryList s)
346{
347 if (!uentryList_isUndefined (s))
348 {
349 /*@-mustfree@*/ /* free shallow does not free the element */
350 sfree (s->elements);
351 /*@=mustfree@*/
352 sfree (s);
353 }
354}
355
616915dd 356bool
357uentryList_isVoid (uentryList cl)
358{
359 if (cl != NULL && cl->nelements == 1)
360 {
2c88d156 361 return (ctype_isVoid (ctype_realType (uentry_getType (cl->elements[0]))));
616915dd 362 }
2c88d156 363
616915dd 364 return FALSE;
365}
366
367/*@exposed@*/ uentry
368uentryList_getN (uentryList p, int n)
369{
370 llassert (uentryList_isDefined (p));
371
372 if (n < 0 || (n >= uentryList_size (p)))
373 {
374 llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
375 n, uentryList_size (p)));
376 return uentry_undefined;
377 }
378
379 return (p->elements[n]);
380}
381
382void uentryList_fixMissingNames (uentryList cl)
383{
384 uentryList_elements (cl, ce)
385 {
386 if (!uentry_hasRealName (ce))
387 {
388 ctype ct = uentry_getType (ce);
389
390 if (ctype_isUA (ct))
391 {
392 uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
393 }
394 else
395 {
396 llbug (message ("uentryList_fixMissingNames: not UA: %s",
397 ctype_unparse (ct)));
398 }
399
400 uentry_setType (ce, ctype_int);
401 }
402 } end_uentryList_elements;
403}
404
405void uentryList_fixImpParams (uentryList cl)
406{
407
408 if (context_getFlag (FLG_PARAMIMPTEMP))
409 {
410 uentryList_elements (cl, ce)
411 {
412 sRef s = uentry_getSref (ce);
413 alkind ak = sRef_getAliasKind (s);
414
415 if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
416 {
417 exkind ek = sRef_getExKind (s);
418
419 if (exkind_isKnown (ek))
420 {
421 sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
422 }
423 else
424 {
425 sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
426 }
427 }
428 else
429 {
430 }
431 } end_uentryList_elements;
432 }
433}
434
435int
436uentryList_compareParams (uentryList s, uentryList t)
437{
438 int i, sz;
439
440 if (s == t) return 0;
441
442 if (uentryList_isUndefined (s)) return 1;
443 if (uentryList_isUndefined (t)) return -1;
444
445 sz = uentryList_size (s);
446
447 INTCOMPARERETURN (uentryList_size (t), sz);
448
449 for (i = 0; i < sz; i++)
450 {
451 COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
452 }
453
454 return 0;
455}
456
457int
458uentryList_compareStrict (uentryList s, uentryList t)
459{
460 int i, sz;
461
462 if (s == t)
463 {
464 return 0;
465 }
466
467 if (uentryList_isMissingParams (s))
468 {
469 if (uentryList_isMissingParams (t))
470 {
471 return 0;
472 }
473 else
474 {
475 return 1;
476 }
477 }
478 else
479 {
480 if (uentryList_isMissingParams (t))
481 {
482 return -1;
483 }
484 else
485 {
486 sz = uentryList_size (s);
487
488 INTCOMPARERETURN (uentryList_size (t), sz);
489
490 for (i = 0; i < sz; i++)
491 {
492 COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
493 }
494
495 return 0;
496 }
497 }
498}
499
500int
501uentryList_compareFields (uentryList s, uentryList t)
502{
503 int i, sz;
504
505 if (s == t) return 0;
506
507 if (uentryList_isUndefined (s))
508 return 1;
509 if (uentryList_isUndefined (t))
510 return -1;
511
512 sz = uentryList_size (s);
513
514 if (uentryList_size (t) != sz)
515 {
516 return (int_compare (sz, uentryList_size (t)));
517 }
518
519 for (i = 0; i < sz; i++)
520 {
521 uentry se = s->elements[i];
522 uentry te = t->elements[i];
523 int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
524
525 if (namecmp == 0)
526 {
527 int uc = uentry_compare (s->elements[i], t->elements[i]);
528
529 if (uc != 0)
530 {
28bf4b0b 531 DPRINTF (("Bad compare: %s / %s",
532 uentry_unparseFull (s->elements [i]),
533 uentry_unparseFull (t->elements [i])));
534
616915dd 535 return uc;
536 }
537 }
538 else
539 {
540 return (namecmp);
541 }
542 }
543
544 return 0;
545}
546
547/*@exposed@*/ uentry
548uentryList_current (uentryList s)
549{
550 llassert (uentryList_isDefined (s));
551 llassert (!(s->current < 0 || (s->current >= s->nelements)));
552 return (s->elements[s->current]);
553}
554
555cstring
556uentryList_dumpParams (uentryList s)
557{
558 cstring st = cstring_undefined;
559
560 if (uentryList_isUndefined (s)) return st;
561
562 uentryList_elements (s, current)
563 {
28bf4b0b 564 DPRINTF (("Dump param: %s", uentry_unparse (current)));
616915dd 565 st = message ("%q%q,", st, uentry_dumpParam (current));
566 } end_uentryList_elements;
567
568 return st;
569}
570
571/*@only@*/ cstring
572uentryList_dumpFields (uentryList s)
573{
574 cstring st = cstring_undefined;
575
576 if (uentryList_isUndefined (s)) return st;
577
578 uentryList_elements (s, current)
579 {
580 if (!uentry_isVariable (current))
581 {
582 llassert (uentry_isFunction (current));
28bf4b0b 583 DPRINTF (("Dump field: %s", uentry_unparse (current)));
616915dd 584 st = message ("%q!%q,", st, uentry_dump (current));
585 }
586 else
587 {
28bf4b0b 588 DPRINTF (("Dump field: %s", uentry_unparse (current)));
616915dd 589 st = message ("%q%q,", st, uentry_dump (current));
590 }
591 } end_uentryList_elements;
592
593 return st;
594}
595
596/*@only@*/ uentryList
597uentryList_undumpFields (char **s, fileloc loc)
598{
599 uentryList ul = uentryList_new ();
600
601 while (**s != '\0' && **s != '}')
602 {
603 if (**s == '!')
604 {
28bf4b0b 605 reader_checkChar (s, '!');
616915dd 606 ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
607 }
608 else
609 {
610 ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
611 }
28bf4b0b 612 reader_checkChar (s, ',');
616915dd 613 }
614
28bf4b0b 615 reader_checkChar (s, '}');
616915dd 616 return ul;
617}
618
619/*@only@*/ uentryList
620uentryList_undump (char **s)
621{
622 char c;
623 uentryList pn = uentryList_new ();
624 int paramno = 0;
625
626 c = **s;
627
628 while (c != '#' && c != '@' && c != ')')
629 {
630 uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
631
632
633 if (!uentry_isUndefined (ue))
634 {
635 pn = uentryList_add (pn, ue);
636 }
637 else
638 {
639 uentry_free (ue);
640 }
641
28bf4b0b 642 reader_checkChar (s, ',');
616915dd 643 c = **s;
644 paramno++;
645 }
646
28bf4b0b 647 reader_checkChar (s, ')');
616915dd 648 return pn;
649}
650
651void
652uentryList_reset (uentryList s)
653{
654 if (uentryList_isUndefined (s)) return;
655 s->current = 0;
656}
657
658bool
659uentryList_isFinished (uentryList s)
660{
661 if (uentryList_isUndefined (s)) return TRUE;
662 return (s->current > s->nelements - 1);
663}
664
665void
666uentryList_advanceSafe (uentryList s)
667{
668 if (uentryList_isUndefined (s)) return;
669
670 s->current++;
671
672 if (s->current > s->nelements)
673 {
674 s->current = s->nelements;
675 }
676}
677
678int
679uentryList_size (uentryList s)
680{
681 if (uentryList_isUndefined (s)) return 0;
682
2c88d156 683 if (uentryList_isVoid (s))
616915dd 684 return 0;
685
686 return s->nelements;
687}
688
689bool
690uentryList_isMissingParams (uentryList s)
691{
692 return (uentryList_isUndefined (s) || s->nelements == 0);
693}
694
695bool uentryList_hasReturned (uentryList ul)
696{
697 uentryList_elements (ul, current)
698 {
699 if (uentry_isReturned (current)) return TRUE;
700 } end_uentryList_elements;
701
702 return FALSE;
703}
704
705/*@exposed@*/ uentry
706uentryList_lookupField (uentryList f, cstring name)
707{
708 int i = uentryList_lookupDirectName (f, name);
709
710 if (i >= 0)
711 {
712 return (uentryList_getN (f, i));
713 }
714 else
715 {
288cbc5c 716 uentryList_elements (f, el)
717 {
718 if (uentry_isUnnamedVariable (el))
719 {
720 ctype ct = uentry_getType (el);
721
722 if (ctype_isStruct (ct) || ctype_isUnion (ct))
723 {
724 uentryList fields = ctype_getFields (ct);
725 uentry ue = uentryList_lookupField (fields, name);
726
727 if (uentry_isValid (ue))
728 {
729 return ue;
730 }
731 }
732 }
733 }
734 end_uentryList_elements ;
735
616915dd 736 return uentry_undefined;
737 }
738}
739
740/*@only@*/ uentryList
741 uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
742{
288cbc5c 743 DPRINTF (("Merge: %s + %s", uentryList_unparse (f1), uentryList_unparse (f2)));
744
616915dd 745 if (uentryList_isUndefined (f1))
746 {
747 return (f2);
748 }
749
750 if (uentryList_isDefined (f2))
751 {
752 uentryList_elements (f2, current)
753 {
754 uentry old = uentryList_lookupField (f1, uentry_rawName (current));
755
756 if (uentry_isValid (old))
757 {
758 voptgenerror
759 (FLG_SYNTAX,
760 message ("Field name reused: %s", uentry_rawName (current)),
761 uentry_whereDefined (current));
762 llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
763 uentry_whereDefined (old));
764 }
765
766 /* okay to use exposed current since f2 is killed */
767 /*@-exposetrans@*/ /*@-dependenttrans@*/
768 f1 = uentryList_add (f1, current);
769 /*@=exposetrans@*/ /*@=dependenttrans@*/
770
771 } end_uentryList_elements;
772
773 sfree (f2->elements);
774 sfree (f2);
775 }
776
777 return (f1);
778}
779
780void
781uentryList_showFieldDifference (uentryList p1, uentryList p2)
782{
783 uentry cp1, cp2;
784 int index;
785
786 llassert (NOALIAS (p1, p2));
787 llassert (uentryList_isDefined (p1));
788 llassert (uentryList_isDefined (p2));
789
790 for (index = 0; index < p1->nelements; index++)
791 {
792 cp1 = p1->elements[index];
793
794 if (index == p2->nelements)
795 {
796 llgenindentmsg
797 (message ("Field present in %s, missing in %rdeclaration: %q",
798 uentry_specDeclName (cp1),
799 uentry_isDeclared (cp1),
800 uentry_unparse (cp1)),
801 uentry_whereEither (cp1));
802 return;
803 }
804
805 cp2 = p2->elements[index];
806
807 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
808 {
809 llgenindentmsg
810 (message ("Field %s in %s corresponds to %s in %rdeclaration",
811 uentry_rawName (cp1),
812 uentry_specOrDefName (cp1),
813 uentry_rawName (cp2),
814 uentry_isCodeDefined (cp1)),
815 uentry_whereDefined (cp2));
816 uentry_showWhereLastPlain (cp1);
817 return;
818 }
819 else
820 {
821 /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
28bf4b0b 822
616915dd 823 if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
824 {
825 llgenindentmsg
826 (message ("Field %s %rdeclared as %s, %s as %s",
827 uentry_rawName (cp2),
828 uentry_isCodeDefined (cp1),
829 ctype_unparse (uentry_getType (cp1)),
830 uentry_specOrDefName (cp2),
831 ctype_unparse (uentry_getType (cp2))),
832 uentry_whereDefined (cp2));
833 uentry_showWhereLastPlain (cp1);
834 return;
835 }
836 }
837 }
838
839 if (index != p2->nelements)
840 {
841 cp2 = p2->elements[index];
842
843 llgenindentmsg
844 (message ("Extra field in new declaration: %q",
845 uentry_unparse (cp2)),
846 uentry_whereEither (cp2));
847
848 return;
849 }
850
851 llbug (message ("uentryList_showFieldDifference: match: %q / %q",
852 uentryList_unparse (p1), uentryList_unparse (p2)));
853}
854
28bf4b0b 855bool
856uentryList_equivFields (uentryList p1, uentryList p2)
857{
858 return (uentryList_compareFields (p1, p2) == 0);
859}
860
616915dd 861bool
862uentryList_matchFields (uentryList p1, uentryList p2)
863{
864 int index;
865 uentry cp1, cp2;
866
867 if (p1 == p2)
868 {
869 return (TRUE);
870 }
871
872 if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
873 {
874 return (TRUE);
875 }
876
877 if (uentryList_size (p1) != uentryList_size (p2))
878 {
879 return FALSE;
880 }
881
882 for (index = 0; index < p1->nelements; index++)
883 {
884 cp1 = p1->elements[index];
885 cp2 = p2->elements[index];
886
68de3f33 887 /*
28bf4b0b 888 ** Should compare uentry's --- need to fix report errors too.
889 */
890
616915dd 891 if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
892 && (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))
28bf4b0b 893 {
616915dd 894 return FALSE;
895 }
896 }
897
898 return TRUE;
899}
This page took 0.183068 seconds and 5 git commands to generate.