]> andersk Git - splint.git/blob - src/uentryList.c
975f2a060098527d5ececd92e6d3bc2e669cab59
[splint.git] / src / uentryList.c
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.
19 **
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
23 */
24 /*
25 ** uentryList.c (from slist_template.c)
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30
31 /*@only@*/ /*@notnull@*/ uentryList
32 uentryList_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
46 uentryList_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
60 static void
61 uentryList_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
82 void 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
95 uentryList 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
158 cstring 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
190 bool 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
220 uentryList_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
232   for (i = 0; i < p->nelements && i < uentryList_abbrevBreadth; i++)
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
251 static int
252 uentryList_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
270 int
271 uentryList_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
294 uentryList uentryList_copy (uentryList s)
295 {
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             {
311               t->elements[i] = uentry_copy (s->elements[i]); 
312             }
313         }
314       else
315         {
316           t->elements = NULL;
317         }
318       
319       return t;
320     }
321   else
322     {
323       return uentryList_undefined;
324     }
325 }
326
327 void
328 uentryList_free (uentryList s)
329 {
330   
331   if (!uentryList_isUndefined (s)) 
332     {
333       int i;
334
335       for (i = 0; i < s->nelements; i++)
336         {
337           uentry_free (s->elements[i]);  
338         }
339
340       sfree (s->elements);
341       sfree (s);
342     }
343 }
344
345 bool
346 uentryList_isVoid (uentryList cl)
347 {
348   if (cl != NULL && cl->nelements == 1)
349     {
350       return (ctype_isVoid (ctype_realType (uentry_getType (cl->elements[0]))));
351     }
352
353   return FALSE;
354 }
355
356 /*@exposed@*/ uentry
357 uentryList_getN (uentryList p, int n)
358 {
359   llassert (uentryList_isDefined (p));
360
361   if (n < 0 || (n >= uentryList_size (p)))
362     {
363       llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
364                           n, uentryList_size (p)));
365       return uentry_undefined;
366     }
367
368   return (p->elements[n]);
369 }
370
371 void uentryList_fixMissingNames (uentryList cl)
372 {
373   uentryList_elements (cl, ce)
374     {
375       if (!uentry_hasRealName (ce))
376         {
377           ctype ct = uentry_getType (ce);
378
379           if (ctype_isUA (ct))
380             {
381               uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
382             }
383           else
384             {
385               llbug (message ("uentryList_fixMissingNames: not UA: %s", 
386                               ctype_unparse (ct)));
387             }
388
389           uentry_setType (ce, ctype_int);
390         }
391     } end_uentryList_elements;
392 }
393
394 void uentryList_fixImpParams (uentryList cl)
395 {
396   
397   if (context_getFlag (FLG_PARAMIMPTEMP))
398     {
399       uentryList_elements (cl, ce)
400         {
401           sRef s = uentry_getSref (ce);
402           alkind ak = sRef_getAliasKind (s);
403
404           if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
405             {
406               exkind ek = sRef_getExKind (s);
407
408               if (exkind_isKnown (ek))
409                 {
410                   sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
411                 }
412               else
413                 {
414                   sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
415                 }
416                     }
417           else
418             {
419                     }
420         } end_uentryList_elements;
421     }
422 }
423
424 int
425 uentryList_compareParams (uentryList s, uentryList t)
426 {
427   int i, sz;
428
429   if (s == t) return 0;
430
431   if (uentryList_isUndefined (s)) return 1;
432   if (uentryList_isUndefined (t)) return -1;
433   
434   sz = uentryList_size (s);
435   
436   INTCOMPARERETURN (uentryList_size (t), sz);
437   
438   for (i = 0; i < sz; i++)
439     {
440       COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
441     }
442   
443   return 0;
444 }
445
446 int
447 uentryList_compareStrict (uentryList s, uentryList t)
448 {
449   int i, sz;
450
451   if (s == t) 
452     {
453       return 0;
454     }
455   
456   if (uentryList_isMissingParams (s))
457     {
458       if (uentryList_isMissingParams (t))
459         {
460           return 0;
461         }
462       else
463         {
464           return 1;
465         }
466     }
467   else 
468     {
469       if (uentryList_isMissingParams (t))
470         {
471           return -1;
472         }
473       else
474         {
475           sz = uentryList_size (s);
476           
477           INTCOMPARERETURN (uentryList_size (t), sz);
478           
479           for (i = 0; i < sz; i++)
480             {
481               COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
482             }
483           
484           return 0;
485         }
486     }
487 }
488
489 int
490 uentryList_compareFields (uentryList s, uentryList t)
491 {
492   int i, sz;
493
494   if (s == t) return 0;
495
496   if (uentryList_isUndefined (s))
497     return 1;
498   if (uentryList_isUndefined (t))
499     return -1;
500   
501   sz = uentryList_size (s);
502   
503   if (uentryList_size (t) != sz)
504     {
505       return (int_compare (sz, uentryList_size (t)));
506     }
507   
508   for (i = 0; i < sz; i++)
509     {
510       uentry se = s->elements[i];
511       uentry te = t->elements[i];
512       int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
513
514       if (namecmp == 0)
515         {
516           int uc = uentry_compare (s->elements[i], t->elements[i]);
517           
518           if (uc != 0) 
519             { 
520               DPRINTF (("Bad compare: %s / %s",
521                         uentry_unparseFull (s->elements [i]),
522                         uentry_unparseFull (t->elements [i])));
523
524               return uc; 
525             }
526         }
527       else
528         {
529           return (namecmp);
530         }
531     }
532
533   return 0;
534 }
535
536 /*@exposed@*/ uentry 
537 uentryList_current (uentryList s)
538 {
539   llassert (uentryList_isDefined (s));
540   llassert (!(s->current < 0 || (s->current >= s->nelements)));
541   return (s->elements[s->current]);
542 }
543
544 cstring
545 uentryList_dumpParams (uentryList s)
546 {
547   cstring st = cstring_undefined;
548
549   if (uentryList_isUndefined (s)) return st;
550   
551   uentryList_elements (s, current)
552     {
553       DPRINTF (("Dump param: %s", uentry_unparse (current)));
554       st = message ("%q%q,", st, uentry_dumpParam (current));
555   } end_uentryList_elements;
556
557   return st;
558 }
559
560 /*@only@*/ cstring
561 uentryList_dumpFields (uentryList s)
562 {
563   cstring st = cstring_undefined;
564
565   if (uentryList_isUndefined (s)) return st;
566
567   uentryList_elements (s, current)
568   {
569     if (!uentry_isVariable (current))
570       {
571         llassert (uentry_isFunction (current));
572         DPRINTF (("Dump field: %s", uentry_unparse (current)));
573         st = message ("%q!%q,", st, uentry_dump (current));
574       }
575     else
576       {
577         DPRINTF (("Dump field: %s", uentry_unparse (current)));
578         st = message ("%q%q,", st, uentry_dump (current));
579       }
580   } end_uentryList_elements;
581   
582   return st;
583 }
584
585 /*@only@*/ uentryList 
586 uentryList_undumpFields (char **s, fileloc loc)
587 {
588   uentryList ul = uentryList_new ();
589
590   while (**s != '\0' && **s != '}') 
591     {
592       if (**s == '!')
593         {
594           reader_checkChar (s, '!');
595           ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
596         }
597       else
598         {
599           ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
600         }
601       reader_checkChar (s, ',');
602     }
603
604   reader_checkChar (s, '}');
605   return ul;
606 }
607
608 /*@only@*/ uentryList
609 uentryList_undump (char **s)
610 {
611   char c;
612   uentryList pn = uentryList_new ();
613   int paramno = 0;
614
615   c = **s;
616
617   while (c != '#' && c != '@' && c != ')')
618     {
619       uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
620       
621       
622       if (!uentry_isUndefined (ue))
623         {
624           pn = uentryList_add (pn, ue);
625         }
626       else
627         {
628           uentry_free (ue);
629         }
630
631       reader_checkChar (s, ',');
632       c = **s;
633       paramno++;
634     }
635
636   reader_checkChar (s, ')');
637   return pn;
638 }
639
640 void 
641 uentryList_reset (uentryList s)
642 {
643   if (uentryList_isUndefined (s)) return;
644   s->current = 0;
645 }
646
647 bool
648 uentryList_isFinished (uentryList s)
649 {
650   if (uentryList_isUndefined (s)) return TRUE;
651   return (s->current > s->nelements - 1);
652 }
653
654 void 
655 uentryList_advanceSafe (uentryList s)
656 {
657   if (uentryList_isUndefined (s)) return;
658
659   s->current++;
660
661   if (s->current > s->nelements)
662     {
663       s->current = s->nelements;
664     }
665 }
666
667 int
668 uentryList_size (uentryList s)
669 {
670   if (uentryList_isUndefined (s)) return 0;
671
672   if (uentryList_isVoid (s))
673     return 0;
674   
675   return s->nelements;
676 }
677
678 bool
679 uentryList_isMissingParams (uentryList s)
680 {
681   return (uentryList_isUndefined (s) || s->nelements == 0);
682 }
683
684 bool uentryList_hasReturned (uentryList ul)
685 {
686   uentryList_elements (ul, current)
687     {
688       if (uentry_isReturned (current)) return TRUE;
689     } end_uentryList_elements;
690
691   return FALSE;
692 }
693
694 /*@exposed@*/ uentry 
695 uentryList_lookupField (uentryList f, cstring name)
696 {
697   int i = uentryList_lookupDirectName (f, name);
698
699   if (i >= 0)
700     {
701       return (uentryList_getN (f, i));
702     }
703   else
704     {
705       uentryList_elements (f, el)
706         {
707           if (uentry_isUnnamedVariable (el))
708             {
709               ctype ct = uentry_getType (el);
710
711               if (ctype_isStruct (ct) || ctype_isUnion (ct))
712                 {
713                   uentryList fields = ctype_getFields (ct);
714                   uentry ue = uentryList_lookupField (fields, name);
715
716                   if (uentry_isValid (ue))
717                     {
718                       return ue;
719                     }
720                 }
721             }
722         }
723       end_uentryList_elements ;
724
725       return uentry_undefined;
726     }
727 }
728
729 /*@only@*/ uentryList
730   uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
731 {
732   DPRINTF (("Merge: %s + %s", uentryList_unparse (f1), uentryList_unparse (f2)));
733
734   if (uentryList_isUndefined (f1))
735     {
736       return  (f2);
737     }
738
739   if (uentryList_isDefined (f2))
740     {
741       uentryList_elements (f2, current)
742         {
743           uentry old = uentryList_lookupField (f1, uentry_rawName (current));
744           
745           if (uentry_isValid (old))
746             {
747               voptgenerror
748                 (FLG_SYNTAX,
749                  message ("Field name reused: %s", uentry_rawName (current)),
750                  uentry_whereDefined (current));
751               llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
752                         uentry_whereDefined (old));
753             }
754           
755           /* okay to use exposed current since f2 is killed */
756           /*@-exposetrans@*/ /*@-dependenttrans@*/
757           f1 = uentryList_add (f1, current); 
758           /*@=exposetrans@*/ /*@=dependenttrans@*/
759
760         } end_uentryList_elements;
761       
762       sfree (f2->elements);
763       sfree (f2);
764     }
765
766   return (f1);
767 }
768
769 void
770 uentryList_showFieldDifference (uentryList p1, uentryList p2)
771 {
772   uentry cp1, cp2;
773   int index;
774
775   llassert (NOALIAS (p1, p2));
776   llassert (uentryList_isDefined (p1));
777   llassert (uentryList_isDefined (p2));
778   
779   for (index = 0; index < p1->nelements; index++)
780     {
781       cp1 = p1->elements[index];
782
783       if (index == p2->nelements)
784         {
785           llgenindentmsg
786             (message ("Field present in %s, missing in %rdeclaration: %q", 
787                       uentry_specDeclName (cp1),
788                       uentry_isDeclared (cp1),
789                       uentry_unparse (cp1)),
790              uentry_whereEither (cp1));
791           return;
792         }
793           
794       cp2 = p2->elements[index];
795
796       if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
797         {
798           llgenindentmsg 
799             (message ("Field %s in %s corresponds to %s in %rdeclaration", 
800                       uentry_rawName (cp1),
801                       uentry_specOrDefName (cp1),
802                       uentry_rawName (cp2),
803                       uentry_isCodeDefined (cp1)),
804              uentry_whereDefined (cp2));
805           uentry_showWhereLastPlain (cp1);
806           return;
807         }
808       else 
809         {
810           /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
811
812           if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
813             {
814               llgenindentmsg 
815                 (message ("Field %s %rdeclared as %s, %s as %s",
816                           uentry_rawName (cp2),
817                           uentry_isCodeDefined (cp1),
818                           ctype_unparse (uentry_getType (cp1)),
819                           uentry_specOrDefName (cp2),
820                           ctype_unparse (uentry_getType (cp2))),
821                  uentry_whereDefined (cp2));
822               uentry_showWhereLastPlain (cp1);
823               return;
824             }
825         }
826     }
827
828   if (index != p2->nelements)
829     {
830       cp2 = p2->elements[index];
831
832       llgenindentmsg 
833         (message ("Extra field in new declaration: %q",
834                   uentry_unparse (cp2)),
835          uentry_whereEither (cp2));
836
837       return;
838     }
839
840   llbug (message ("uentryList_showFieldDifference: match: %q / %q",
841                   uentryList_unparse (p1), uentryList_unparse (p2)));
842 }
843
844 bool
845 uentryList_equivFields (uentryList p1, uentryList p2)
846 {
847   return (uentryList_compareFields (p1, p2) == 0);
848 }
849
850 bool
851 uentryList_matchFields (uentryList p1, uentryList p2)
852 {
853   int index;
854   uentry cp1, cp2;
855
856   if (p1 == p2) 
857     {
858       return (TRUE);
859     }
860
861   if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
862     {
863       return (TRUE);
864     }
865
866   if (uentryList_size (p1) != uentryList_size (p2))
867     {
868       return FALSE;
869     }
870
871   for (index = 0; index < p1->nelements; index++)
872     {
873       cp1 = p1->elements[index];
874       cp2 = p2->elements[index];
875
876       /*@i32*/
877       /*
878       ** Should compare uentry's --- need to fix report errors too.
879       */
880
881       if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
882             && (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))
883         { 
884           return FALSE;
885         }
886     }
887
888   return TRUE;
889 }
This page took 0.092928 seconds and 3 git commands to generate.