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