Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

uentryList.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** uentryList.c (from slist_template.c)
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 
00031 /*@only@*/ /*@notnull@*/ uentryList
00032 uentryList_new ()
00033 {
00034   uentryList s = (uentryList) dmalloc (sizeof (*s));
00035   
00036   s->nelements = 0;
00037   s->nspace = uentryListBASESIZE;
00038   s->elements = (uentry *) 
00039     dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
00040   s->current = 0;
00041 
00042   return (s);
00043 }
00044 
00045 /*@only@*/ uentryList
00046 uentryList_single (/*@keep@*/ uentry el)
00047 {
00048   uentryList s = (uentryList) dmalloc (sizeof (*s));
00049   
00050   s->nelements = 1;
00051   s->nspace = uentryListBASESIZE - 1;
00052   s->elements = (uentry *) dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
00053   
00054   s->elements[0] = el;
00055   s->current = 0;
00056 
00057   return (s);
00058 }
00059 
00060 static void
00061 uentryList_grow (uentryList s)
00062 {
00063   int i;
00064   uentry *newelements;
00065 
00066   llassert (!uentryList_isUndefined (s));
00067 
00068   s->nspace += uentryListBASESIZE; 
00069   
00070   newelements = (uentry *) dmalloc (sizeof (*newelements) 
00071                                     * (s->nelements + s->nspace));
00072     
00073   for (i = 0; i < s->nelements; i++)
00074     {
00075       newelements[i] = s->elements[i];
00076     }
00077   
00078   sfree (s->elements);
00079   s->elements = newelements;
00080 }
00081 
00082 void uentryList_clear (uentryList s)
00083 {
00084   if (uentryList_isUndefined (s))
00085     {
00086       ;
00087     }
00088   else
00089     {
00090       s->nspace += s->nelements;
00091       s->nelements = 0;
00092     }
00093 }
00094 
00095 uentryList uentryList_add (uentryList s, /*@keep@*/ uentry el)
00096 {
00097   if (uentryList_isUndefined (s))
00098     {
00099       s = uentryList_new ();
00100     }
00101 
00102   if (s->nspace <= 0)
00103     uentryList_grow (s);
00104   
00105   s->nspace--;
00106   s->elements[s->nelements] = el;
00107   s->nelements++;
00108 
00109   return s;
00110 }
00111 
00112 /*@only@*/ cstring
00113   uentryList_unparse (uentryList s)
00114 {
00115   cstring st = cstring_undefined;
00116   int i;
00117   
00118   if (uentryList_isDefined (s))
00119     {
00120       for (i = 0; i < uentryList_size (s); i++)
00121         {
00122           if (i == 0)
00123             {
00124               st = message ("%q;", uentry_unparse (s->elements[i]));
00125             }
00126           else
00127             st = message ("%q %q;", st, uentry_unparse (s->elements[i]));
00128         }
00129     }
00130   
00131   return (st);
00132 }
00133 
00134 /*@unused@*/ /*@only@*/ cstring
00135   uentryList_unparseFull (uentryList s)
00136 {
00137   cstring st = cstring_undefined;
00138   int i;
00139   
00140   if (uentryList_isDefined (s))
00141     {
00142       for (i = 0; i < uentryList_size (s); i++)
00143         {
00144           if (i == 0)
00145             {
00146               st = message ("%q;", uentry_unparseFull (s->elements[i]));
00147             }
00148           else
00149             {
00150               st = message ("%q %q;", st, uentry_unparseFull (s->elements[i]));
00151             }
00152         }
00153     }
00154   
00155   return (st);
00156 }
00157 
00158 cstring uentryList_unparseParams (uentryList s)
00159 {
00160   int i;
00161   cstring st = cstring_undefined;
00162 
00163   
00164   if (uentryList_isUndefined (s))
00165     {
00166       return st;
00167     }
00168   else if (uentryList_isVoid (s))
00169     {
00170       return (cstring_makeLiteral ("void"));
00171     }
00172   else
00173     {
00174       for (i = 0; i < uentryList_size (s); i++)
00175         {
00176           if (i == 0)
00177             {
00178               st = message ("%s", ctype_unparse (uentry_getType (s->elements[i])));
00179             }
00180           else
00181             {
00182               st = message ("%q, %s", st, ctype_unparse (uentry_getType (s->elements[i])));
00183             }
00184         }
00185       
00186       return st;
00187     }
00188 }
00189 
00190 bool uentryList_matchParams (uentryList p1, uentryList p2, bool force, bool arg)
00191 {
00192   int sz1 = uentryList_size (p1);
00193   int sz2 = uentryList_size (p2);
00194   int i;
00195   
00196   if (p1 == p2) return TRUE;
00197 
00198   if (uentryList_isMissingParams (p1) || uentryList_isMissingParams (p2))
00199     {
00200       return TRUE;
00201     }
00202 
00203   if (sz1 != sz2)
00204     return FALSE;
00205 
00206   for (i = 0; i < sz1; i++)
00207     {
00208       if (!ctype_genMatch (uentry_getType (p1->elements[i]), 
00209                            uentry_getType (p2->elements[i]), 
00210                            force, arg, FALSE, FALSE))
00211         {
00212           return FALSE;
00213         }
00214     }
00215 
00216   return TRUE;
00217 }
00218 
00219 /*@only@*/ cstring
00220 uentryList_unparseAbbrev (uentryList p)
00221 {
00222   bool first = TRUE;
00223   cstring s = cstring_undefined;
00224   int i = 0;
00225   
00226   if (uentryList_isUndefined (p))
00227     return s;
00228 
00229   if (uentryList_size (p) == 0)
00230     return cstring_makeLiteral ("void");
00231 
00232   for (i = 0; i < p->nelements && i < PRINTBREADTH; i++)
00233     {
00234       if (first)
00235         {
00236           s = message ("%q;", uentry_unparseAbbrev (p->elements[i]));
00237           first = FALSE;
00238         }
00239       else
00240         {
00241           s = message ("%q %q;", s, uentry_unparseAbbrev (p->elements[i]));
00242         }
00243     }
00244   
00245   if (i != uentryList_size (p))
00246     s = message ("%q, ...", s);
00247   
00248   return (s);
00249 }
00250 
00251 static int
00252 uentryList_lookupDirectName (uentryList s, cstring name)
00253 {
00254   if (uentryList_isDefined (s))
00255     {
00256       int i;
00257       
00258       for (i = 0; i < uentryList_size (s); i++)
00259         {
00260           if (cstring_equal (name, uentry_rawName (s->elements[i])))
00261             {
00262               return i;
00263             }
00264         }
00265     }
00266 
00267    return -1;
00268 }
00269 
00270 int
00271 uentryList_lookupRealName (uentryList s, cstring name)
00272 {
00273   if (uentryList_isDefined (s))
00274     {
00275       int i;
00276       
00277       for (i = 0; i < uentryList_size (s); i++)
00278         {
00279           cstring uname = uentry_getName (s->elements[i]);
00280 
00281           if (cstring_equal (name, uname))
00282             {
00283               cstring_free (uname);
00284               return i;
00285             }      
00286 
00287           cstring_free (uname);
00288         }
00289     }
00290 
00291    return -1;
00292 }
00293 
00294 uentryList uentryList_copy (uentryList s)
00295 {
00296   
00297   if (uentryList_isDefined (s))
00298     {
00299       uentryList t = (uentryList) dmalloc (sizeof (*t));
00300       int i;
00301       
00302       t->nelements = s->nelements;
00303       t->nspace = 0;
00304       t->current = s->current;
00305       
00306       if (s->nelements > 0)
00307         {
00308           t->elements = (uentry *) dmalloc (sizeof (*t->elements) * t->nelements);
00309           
00310           for (i = 0; i < s->nelements; i++) 
00311             {
00312                       t->elements[i] = uentry_copy (s->elements[i]); 
00313                     }
00314         }
00315       else
00316         {
00317           t->elements = NULL;
00318         }
00319 
00320       return t;
00321     }
00322   else
00323     {
00324       return uentryList_undefined;
00325     }
00326 }
00327 
00328 void
00329 uentryList_free (uentryList s)
00330 {
00331   
00332   if (!uentryList_isUndefined (s)) 
00333     {
00334       int i;
00335 
00336       for (i = 0; i < s->nelements; i++)
00337         {
00338           uentry_free (s->elements[i]);  
00339         }
00340 
00341       sfree (s->elements);
00342       sfree (s);
00343     }
00344 }
00345 
00346 bool
00347 uentryList_isVoid (uentryList cl)
00348 {
00349   if (cl != NULL && cl->nelements == 1)
00350     {
00351       return (ctype_isVoid (uentry_getType (cl->elements[0])));
00352     }
00353   return FALSE;
00354 }
00355 
00356 /*@exposed@*/ uentry
00357 uentryList_getN (uentryList p, int n)
00358 {
00359   llassert (uentryList_isDefined (p));
00360 
00361   if (n < 0 || (n >= uentryList_size (p)))
00362     {
00363       llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
00364                           n, uentryList_size (p)));
00365       return uentry_undefined;
00366     }
00367 
00368   return (p->elements[n]);
00369 }
00370 
00371 void uentryList_fixMissingNames (uentryList cl)
00372 {
00373   uentryList_elements (cl, ce)
00374     {
00375       if (!uentry_hasRealName (ce))
00376         {
00377           ctype ct = uentry_getType (ce);
00378 
00379           if (ctype_isUA (ct))
00380             {
00381               uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
00382             }
00383           else
00384             {
00385               llbug (message ("uentryList_fixMissingNames: not UA: %s", 
00386                               ctype_unparse (ct)));
00387             }
00388 
00389           uentry_setType (ce, ctype_int);
00390         }
00391     } end_uentryList_elements;
00392 }
00393 
00394 void uentryList_fixImpParams (uentryList cl)
00395 {
00396   
00397   if (context_getFlag (FLG_PARAMIMPTEMP))
00398     {
00399       uentryList_elements (cl, ce)
00400         {
00401           sRef s = uentry_getSref (ce);
00402           alkind ak = sRef_getAliasKind (s);
00403 
00404           if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
00405             {
00406               exkind ek = sRef_getExKind (s);
00407 
00408               if (exkind_isKnown (ek))
00409                 {
00410                   sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
00411                 }
00412               else
00413                 {
00414                   sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
00415                 }
00416                     }
00417           else
00418             {
00419                     }
00420         } end_uentryList_elements;
00421     }
00422 }
00423 
00424 int
00425 uentryList_compareParams (uentryList s, uentryList t)
00426 {
00427   int i, sz;
00428 
00429   if (s == t) return 0;
00430 
00431   if (uentryList_isUndefined (s)) return 1;
00432   if (uentryList_isUndefined (t)) return -1;
00433   
00434   sz = uentryList_size (s);
00435   
00436   INTCOMPARERETURN (uentryList_size (t), sz);
00437   
00438   for (i = 0; i < sz; i++)
00439     {
00440       COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
00441     }
00442   
00443   return 0;
00444 }
00445 
00446 int
00447 uentryList_compareStrict (uentryList s, uentryList t)
00448 {
00449   int i, sz;
00450 
00451   if (s == t) 
00452     {
00453       return 0;
00454     }
00455   
00456   if (uentryList_isMissingParams (s))
00457     {
00458       if (uentryList_isMissingParams (t))
00459         {
00460           return 0;
00461         }
00462       else
00463         {
00464           return 1;
00465         }
00466     }
00467   else 
00468     {
00469       if (uentryList_isMissingParams (t))
00470         {
00471           return -1;
00472         }
00473       else
00474         {
00475           sz = uentryList_size (s);
00476           
00477           INTCOMPARERETURN (uentryList_size (t), sz);
00478           
00479           for (i = 0; i < sz; i++)
00480             {
00481               COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
00482             }
00483           
00484           return 0;
00485         }
00486     }
00487 }
00488 
00489 int
00490 uentryList_compareFields (uentryList s, uentryList t)
00491 {
00492   int i, sz;
00493 
00494   if (s == t) return 0;
00495 
00496   if (uentryList_isUndefined (s))
00497     return 1;
00498   if (uentryList_isUndefined (t))
00499     return -1;
00500   
00501   sz = uentryList_size (s);
00502   
00503   if (uentryList_size (t) != sz)
00504     {
00505       return (int_compare (sz, uentryList_size (t)));
00506     }
00507   
00508   for (i = 0; i < sz; i++)
00509     {
00510       uentry se = s->elements[i];
00511       uentry te = t->elements[i];
00512       int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
00513 
00514       if (namecmp == 0)
00515         {
00516           int uc = uentry_compare (s->elements[i], t->elements[i]);
00517           
00518           if (uc != 0) 
00519             { 
00520               return uc; 
00521             }
00522         }
00523       else
00524         {
00525           return (namecmp);
00526         }
00527     }
00528 
00529   return 0;
00530 }
00531 
00532 /*@exposed@*/ uentry 
00533 uentryList_current (uentryList s)
00534 {
00535   llassert (uentryList_isDefined (s));
00536   llassert (!(s->current < 0 || (s->current >= s->nelements)));
00537   return (s->elements[s->current]);
00538 }
00539 
00540 cstring
00541 uentryList_dumpParams (uentryList s)
00542 {
00543   cstring st = cstring_undefined;
00544 
00545   if (uentryList_isUndefined (s)) return st;
00546   
00547   uentryList_elements (s, current)
00548     {
00549       st = message ("%q%q,", st, uentry_dumpParam (current));
00550   } end_uentryList_elements;
00551 
00552   return st;
00553 }
00554 
00555 /*@only@*/ cstring
00556 uentryList_dumpFields (uentryList s)
00557 {
00558   cstring st = cstring_undefined;
00559 
00560   if (uentryList_isUndefined (s)) return st;
00561 
00562   uentryList_elements (s, current)
00563   {
00564     if (!uentry_isVariable (current))
00565       {
00566         llassert (uentry_isFunction (current));
00567         st = message ("%q!%q,", st, uentry_dump (current));
00568       }
00569     else
00570       {
00571         st = message ("%q%q,", st, uentry_dump (current));
00572       }
00573   } end_uentryList_elements;
00574   
00575   return st;
00576 }
00577 
00578 /*@only@*/ uentryList 
00579 uentryList_undumpFields (char **s, fileloc loc)
00580 {
00581   uentryList ul = uentryList_new ();
00582 
00583   while (**s != '\0' && **s != '}') 
00584     {
00585       if (**s == '!')
00586         {
00587           checkChar (s, '!');
00588           ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
00589         }
00590       else
00591         {
00592           ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
00593         }
00594       checkChar (s, ',');
00595     }
00596 
00597   checkChar (s, '}');
00598   return ul;
00599 }
00600 
00601 /*@only@*/ uentryList
00602 uentryList_undump (char **s)
00603 {
00604   char c;
00605   uentryList pn = uentryList_new ();
00606   int paramno = 0;
00607 
00608   c = **s;
00609 
00610   while (c != '#' && c != '@' && c != ')')
00611     {
00612       uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
00613       
00614       
00615       if (!uentry_isUndefined (ue))
00616         {
00617           pn = uentryList_add (pn, ue);
00618         }
00619       else
00620         {
00621           uentry_free (ue);
00622         }
00623 
00624       checkChar (s, ',');
00625       c = **s;
00626       paramno++;
00627     }
00628 
00629   checkChar (s, ')');
00630   return pn;
00631 }
00632 
00633 void 
00634 uentryList_reset (uentryList s)
00635 {
00636   if (uentryList_isUndefined (s)) return;
00637   s->current = 0;
00638 }
00639 
00640 bool
00641 uentryList_isFinished (uentryList s)
00642 {
00643   if (uentryList_isUndefined (s)) return TRUE;
00644   return (s->current > s->nelements - 1);
00645 }
00646 
00647 void 
00648 uentryList_advanceSafe (uentryList s)
00649 {
00650   if (uentryList_isUndefined (s)) return;
00651 
00652   s->current++;
00653 
00654   if (s->current > s->nelements)
00655     {
00656       s->current = s->nelements;
00657     }
00658 }
00659 
00660 int
00661 uentryList_size (uentryList s)
00662 {
00663   if (uentryList_isUndefined (s)) return 0;
00664 
00665   if (s->nelements == 1 && ctype_isVoid (uentry_getType (s->elements[0])))
00666     return 0;
00667   
00668   return s->nelements;
00669 }
00670 
00671 bool
00672 uentryList_isMissingParams (uentryList s)
00673 {
00674   return (uentryList_isUndefined (s) || s->nelements == 0);
00675 }
00676 
00677 bool uentryList_hasReturned (uentryList ul)
00678 {
00679   uentryList_elements (ul, current)
00680     {
00681       if (uentry_isReturned (current)) return TRUE;
00682     } end_uentryList_elements;
00683 
00684   return FALSE;
00685 }
00686 
00687 /*@exposed@*/ uentry 
00688 uentryList_lookupField (uentryList f, cstring name)
00689 {
00690   int i = uentryList_lookupDirectName (f, name);
00691 
00692   if (i >= 0)
00693     {
00694       return (uentryList_getN (f, i));
00695     }
00696   else
00697     {
00698       return uentry_undefined;
00699     }
00700 }
00701 
00702 /*@only@*/ uentryList
00703   uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
00704 {
00705   if (uentryList_isUndefined (f1))
00706     {
00707       return  (f2);
00708     }
00709 
00710   if (uentryList_isDefined (f2))
00711     {
00712       uentryList_elements (f2, current)
00713         {
00714           uentry old = uentryList_lookupField (f1, uentry_rawName (current));
00715           
00716           if (uentry_isValid (old))
00717             {
00718               voptgenerror
00719                 (FLG_SYNTAX,
00720                  message ("Field name reused: %s", uentry_rawName (current)),
00721                  uentry_whereDefined (current));
00722               llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
00723                         uentry_whereDefined (old));
00724             }
00725           
00726           /* okay to use exposed current since f2 is killed */
00727           /*@-exposetrans@*/ /*@-dependenttrans@*/
00728           f1 = uentryList_add (f1, current); 
00729           /*@=exposetrans@*/ /*@=dependenttrans@*/
00730 
00731         } end_uentryList_elements;
00732       
00733       sfree (f2->elements);
00734       sfree (f2);
00735     }
00736 
00737   return (f1);
00738 }
00739 
00740 void
00741 uentryList_showFieldDifference (uentryList p1, uentryList p2)
00742 {
00743   uentry cp1, cp2;
00744   int index;
00745 
00746   llassert (NOALIAS (p1, p2));
00747   llassert (uentryList_isDefined (p1));
00748   llassert (uentryList_isDefined (p2));
00749   
00750   for (index = 0; index < p1->nelements; index++)
00751     {
00752       cp1 = p1->elements[index];
00753 
00754       if (index == p2->nelements)
00755         {
00756           llgenindentmsg
00757             (message ("Field present in %s, missing in %rdeclaration: %q", 
00758                       uentry_specDeclName (cp1),
00759                       uentry_isDeclared (cp1),
00760                       uentry_unparse (cp1)),
00761              uentry_whereEither (cp1));
00762           return;
00763         }
00764           
00765       cp2 = p2->elements[index];
00766 
00767       if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
00768         {
00769           llgenindentmsg 
00770             (message ("Field %s in %s corresponds to %s in %rdeclaration", 
00771                       uentry_rawName (cp1),
00772                       uentry_specOrDefName (cp1),
00773                       uentry_rawName (cp2),
00774                       uentry_isCodeDefined (cp1)),
00775              uentry_whereDefined (cp2));
00776           uentry_showWhereLastPlain (cp1);
00777           return;
00778         }
00779       else 
00780         {
00781           /* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
00782           if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
00783             {
00784               llgenindentmsg 
00785                 (message ("Field %s %rdeclared as %s, %s as %s",
00786                           uentry_rawName (cp2),
00787                           uentry_isCodeDefined (cp1),
00788                           ctype_unparse (uentry_getType (cp1)),
00789                           uentry_specOrDefName (cp2),
00790                           ctype_unparse (uentry_getType (cp2))),
00791                  uentry_whereDefined (cp2));
00792               uentry_showWhereLastPlain (cp1);
00793               return;
00794             }
00795         }
00796     }
00797 
00798   if (index != p2->nelements)
00799     {
00800       cp2 = p2->elements[index];
00801 
00802       llgenindentmsg 
00803         (message ("Extra field in new declaration: %q",
00804                   uentry_unparse (cp2)),
00805          uentry_whereEither (cp2));
00806 
00807       return;
00808     }
00809 
00810   llbug (message ("uentryList_showFieldDifference: match: %q / %q",
00811                   uentryList_unparse (p1), uentryList_unparse (p2)));
00812 }
00813 
00814 bool
00815 uentryList_matchFields (uentryList p1, uentryList p2)
00816 {
00817   int index;
00818   uentry cp1, cp2;
00819 
00820   if (p1 == p2) 
00821     {
00822       return (TRUE);
00823     }
00824 
00825   if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
00826     {
00827       return (TRUE);
00828     }
00829 
00830   if (uentryList_size (p1) != uentryList_size (p2))
00831     {
00832       return FALSE;
00833     }
00834 
00835   for (index = 0; index < p1->nelements; index++)
00836     {
00837       cp1 = p1->elements[index];
00838       cp2 = p2->elements[index];
00839 
00840       if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
00841             && (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))
00842         {     /* was ctype_match! */
00843           return FALSE;
00844         }
00845     }
00846 
00847   return TRUE;
00848 }
00849 

Generated at Fri Nov 3 18:57:45 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000