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

flagMarkerList.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 ** flagMarkerList.c
00026 **
00027 ** based on list_template.c
00028 **
00029 ** where T has T_equal (or change this) and T_unparse
00030 **
00031 ** invariant: flagMarker's are listed in order
00032 */
00033 
00034 # include "lclintMacros.nf"
00035 # include "basic.h"
00036 
00037 flagMarkerList
00038   flagMarkerList_new ()
00039 {
00040   flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
00041   
00042   s->nelements = 0;
00043   s->nspace = flagMarkerListBASESIZE; 
00044   s->elements = (flagMarker *)
00045     dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
00046 
00047   return (s);
00048 }
00049 
00050 static void
00051 flagMarkerList_grow (flagMarkerList s)
00052 {
00053   int i;
00054   flagMarker *newelements;
00055   
00056   s->nspace += flagMarkerListBASESIZE; 
00057 
00058   newelements = (flagMarker *) dmalloc (sizeof (*newelements) 
00059                                         * (s->nelements + s->nspace));
00060 
00061   for (i = 0; i < s->nelements; i++)
00062     {
00063       newelements[i] = s->elements[i];
00064     }
00065   
00066   sfree (s->elements);
00067   s->elements = newelements;
00068 }
00069 
00070 void flagMarkerList_add (flagMarkerList s, flagMarker fm)
00071 {
00072   int i = s->nelements - 1;
00073 
00074   
00075   if (i > 0)
00076     {
00077       flagMarker last = s->elements[i];
00078 
00079       
00080       if (flagMarker_isIgnoreCount (last))
00081         {
00082           if (!flagMarker_isIgnoreOff (fm))
00083             {
00084               if (flagMarker_isLocalSet (fm))
00085                 {
00086                   llforceerror 
00087                     (FLG_WARNFLAGS,
00088                      cstring_makeLiteral ("Cannot set flag inside ignore "
00089                                           "count region."),
00090                      flagMarker_getLoc (fm));
00091                   llgenindentmsg 
00092                     (cstring_makeLiteral ("Ignore count region starts"),
00093                      flagMarker_getLoc (last));
00094 
00095                 }
00096               else 
00097                 {
00098                   if (flagMarker_isIgnoreOn (fm)) 
00099                     {
00100                       llforceerror 
00101                         (FLG_WARNFLAGS,
00102                          cstring_makeLiteral ("Cannot nest ignore regions."),
00103                          flagMarker_getLoc (fm));
00104                       llgenindentmsg 
00105                         (cstring_makeLiteral ("Previous ignore region starts"),
00106                          flagMarker_getLoc (last));
00107                     }
00108                 }
00109 
00110               flagMarker_free (fm);
00111               return;
00112             }
00113         }
00114       else 
00115         {
00116           if (flagMarker_isIgnoreOff (last))
00117             {
00118               flagMarker nlast = s->elements [i - 1];
00119               
00120               if (flagMarker_isIgnoreCount (nlast))
00121                 {
00122                   if (fileloc_sameFile (flagMarker_getLoc (fm),
00123                                         flagMarker_getLoc (last))
00124                       && fileloc_notAfter (flagMarker_getLoc (fm), 
00125                                            flagMarker_getLoc (last)))
00126                     {
00127                       if (flagMarker_isLocalSet (fm))
00128                         {
00129                           llforceerror 
00130                             (FLG_WARNFLAGS,
00131                              cstring_makeLiteral ("Cannot set flag inside ignore "
00132                                                   "count region."),
00133                              flagMarker_getLoc (fm));
00134                           llgenindentmsg 
00135                             (cstring_makeLiteral ("Ignore count region starts"),
00136                              flagMarker_getLoc (nlast));
00137                           
00138                         }
00139                       else 
00140                         {
00141                           if (flagMarker_isIgnoreOn (fm)) 
00142                             {
00143                               llforceerror 
00144                                 (FLG_WARNFLAGS,
00145                                  cstring_makeLiteral ("Cannot nest ignore regions."),
00146                                  flagMarker_getLoc (fm));
00147                               llgenindentmsg 
00148                                 (cstring_makeLiteral ("Previous ignore region starts"),
00149                                  flagMarker_getLoc (nlast));
00150                             }
00151                         }
00152                       
00153                       flagMarker_free (fm);
00154                       return;
00155                     }
00156                 }
00157             }
00158         }
00159     }
00160 
00161   
00162   /*
00163   ** all this code is necessary to check the invariant is preserved
00164   */
00165 
00166   while (i > 0
00167          && !flagMarker_sameFile (s->elements[i],
00168                                   flagMarker_getLoc (fm))) 
00169     {
00170       i--;
00171     }
00172 
00173   /*
00174   ** reprocessing header file, okay to be out of order
00175   */
00176 
00177   if (i >= 0 && !fileloc_isHeader (flagMarker_getLoc (fm)))
00178     {
00179                   
00180       /*
00181       llassert (!flagMarker_beforeMarker (s->elements[i], 
00182                                           flagMarker_getLoc (fm)));
00183                                           */
00184     }
00185 
00186   if (s->nspace <= 0)
00187     {
00188       flagMarkerList_grow (s);
00189     }
00190   
00191   s->nspace--;
00192   s->elements[s->nelements] = fm;
00193   s->nelements++;
00194   }
00195 
00196 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
00197 {
00198   int nexpected = 0;
00199   int nsuppressed = 0;
00200   fileloc loc = fileloc_undefined;
00201   bool inCount = FALSE;
00202   int i;
00203 
00204   
00205   for (i = 0; i < s->nelements; i++)
00206     {
00207       flagMarker current = s->elements[i];
00208 
00209       if (flagMarker_isIgnoreCount (current))
00210         {
00211           llassert (!inCount);
00212           inCount = TRUE;
00213           nexpected = flagMarker_getCount (current);
00214           loc = flagMarker_getLoc (current);
00215           nsuppressed = 0;
00216                 }
00217       else if (flagMarker_isIgnoreOff (current))
00218         {
00219           if (inCount)
00220             {
00221               inCount = FALSE;
00222               llassert (fileloc_isDefined (loc));
00223 
00224               if (nexpected > 0 && nexpected != nsuppressed)
00225                 {
00226                   llforceerror 
00227                     (FLG_SUPCOUNTS,
00228                      message 
00229                      ("Line expects to suppress %d error%p, found %d error%p",
00230                       nexpected, nsuppressed),
00231                      loc);
00232                 }
00233             }
00234         }
00235       else if (flagMarker_isSuppress (current))
00236         {
00237           nsuppressed++;
00238         }
00239       else
00240         {
00241           ;
00242         }
00243     }
00244 
00245   llassert (!inCount);
00246 }
00247 
00248 static void flagMarkerList_splice (flagMarkerList s, 
00249                                    int index,
00250                                    /*@keep@*/ flagMarker fm)
00251 {
00252   fileloc loc = flagMarker_getLoc (fm);
00253   fileloc beforeloc, afterloc;
00254   int i;
00255 
00256   llassert (index >= 0 && (index + 1 < s->nelements));
00257   
00258   beforeloc = flagMarker_getLoc (s->elements[index]);
00259   afterloc = flagMarker_getLoc (s->elements[index + 1]);;
00260   
00261   llassert (fileloc_sameFile (beforeloc, loc));
00262   llassert (fileloc_sameFile (afterloc, loc));
00263 
00264   if (s->nspace <= 0)
00265     {
00266       flagMarkerList_grow (s);
00267     }
00268   
00269   for (i = s->nelements; i > index + 1; i--)
00270     {
00271       s->elements[i] = s->elements[i - 1];
00272     }
00273 
00274   s->elements[index + 1] = fm;
00275   s->nelements++;
00276   s->nspace--;
00277 
00278   }
00279 
00280 /*@only@*/ cstring
00281 flagMarkerList_unparse (flagMarkerList s)
00282 {
00283    int i;
00284    cstring st = cstring_makeLiteral ("[");
00285 
00286    for (i = 0; i < s->nelements; i++)
00287      {
00288        if (i == 0)
00289          {
00290            st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
00291          }
00292        else
00293          st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
00294      }
00295    
00296    st = message ("%q ]", st);
00297    return st;
00298 }
00299 
00300 void
00301 flagMarkerList_free (flagMarkerList s)
00302 {
00303   int i;
00304   for (i = 0; i < s->nelements; i++)
00305     {
00306       flagMarker_free (s->elements[i]);
00307     }
00308   
00309   sfree (s->elements); 
00310   sfree (s);
00311 }
00312 
00313 /*
00314 ** returns YES iff
00315 **    > in ignore region (there is an ignore ON marker not followed by OFF)
00316 **    > code is OFF (-)
00317 **
00318 ** returns NO iff
00319 **    > not in ignore region
00320 **    > code is ON (+)
00321 **
00322 ** returns MAYBE iff
00323 **    > not in ignore region
00324 **    > code is unset or =
00325 **
00326 ** requires: invariant for flagMarkerList:
00327 **    flagMarker's are sorted by line and col
00328 */
00329 
00330 static int
00331 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
00332 {
00333   int i;
00334 
00335   for (i = s->nelements - 1; i >= 0; i--) 
00336     {
00337       flagMarker current = s->elements[i];
00338       
00339       if (fileloc_sameFile (current->loc, loc) 
00340           && (!flagMarker_beforeMarker (current, loc)))
00341         {
00342           return i;
00343         }
00344 /*
00345       if (flagMarker_sameFile (current, loc) 
00346           && (!flagMarker_beforeMarker (current, loc)))
00347         {
00348           return i;
00349         }
00350 */
00351     }
00352 
00353   return -1;
00354 }
00355           
00356 ynm
00357 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
00358 {
00359   int i;
00360   bool ignoreOff = FALSE;
00361   bool nameChecksOff = FALSE;
00362   bool flagOff = FALSE;
00363   ynm flagSet = MAYBE;
00364   bool islib = FALSE;
00365   bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
00366 
00367   if (fileloc_isLib (loc))
00368     {
00369       i = s->nelements - 1;
00370       islib = TRUE;
00371     }
00372   else
00373     {
00374       i = flagMarkerList_lastBeforeLoc (s, loc);
00375     }
00376 
00377   
00378   if (i < 0)
00379     {
00380       return MAYBE;
00381     }
00382   
00383   /*
00384   ** Go backwards through the remaining flagMarkers in this file.
00385   */
00386 
00387   for (; i >= 0; i--) 
00388     {
00389       flagMarker current = s->elements[i];
00390 
00391       
00392       if (!islib && !flagMarker_sameFile (current, loc))
00393         {
00394           break;
00395         }
00396 
00397       if (flagMarker_isIgnoreOff (current))
00398         {
00399           ignoreOff = TRUE;
00400         }
00401       else if (flagMarker_isIgnoreOn (current))
00402         {
00403           if (!ignoreOff)
00404             {
00405               return YES;
00406             }
00407         }
00408       else if (flagMarker_isIgnoreCount (current))
00409         {
00410           if (!ignoreOff)
00411             {
00412               flagMarkerList_splice (s, i,
00413                                      flagMarker_createSuppress (code, loc));
00414               return YES;
00415             }
00416         }
00417       else if (flagMarker_isLocalSet (current))
00418         {
00419           
00420           if (!flagOff && flagMarker_getCode (current) == code)
00421             {
00422               ynm set  = flagMarker_getSet (current);
00423               
00424               if (ynm_isOff (set))
00425                 {
00426                   return YES;
00427                 }
00428               else
00429                 {
00430                   if (ynm_isOn (set))
00431                     {
00432                       flagOff = TRUE;
00433                       flagSet = NO;
00434                     }
00435                   else
00436                     {
00437                                       flagOff = TRUE;
00438                       flagSet = MAYBE;
00439                     }
00440                   
00441                   if (ignoreOff)
00442                     {
00443                       if (isNameChecksFlag && !nameChecksOff)
00444                         {
00445                           ;
00446                         }
00447                       else
00448                         {
00449                           return flagSet;
00450                         }
00451                     }
00452                 }
00453             }
00454           
00455           if (flagMarker_getCode (current) == FLG_NAMECHECKS
00456               && !nameChecksOff && isNameChecksFlag)
00457             {
00458               ynm set  = flagMarker_getSet (current);
00459               
00460               if (ynm_isOff (set))
00461                 {
00462                   return YES;
00463                 }
00464               else
00465                 {
00466                   if (ynm_isOn (set))
00467                     {
00468                       nameChecksOff = TRUE;
00469                       flagSet = NO;
00470                     }
00471                   else
00472                     {
00473                                       nameChecksOff = TRUE;
00474                       flagSet = MAYBE;
00475                     }
00476                   
00477                   if (ignoreOff && flagOff)
00478                     {
00479                       return flagSet;
00480                     }
00481                 }
00482             }
00483         }
00484       else
00485         {
00486           llassert (flagMarker_isSuppress (current));
00487         }
00488     }
00489   
00490   return flagSet;
00491 }
00492 
00493 bool
00494 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
00495 {
00496   int i;
00497 
00498   if (fileloc_isLib (loc))
00499     {
00500       return FALSE;
00501     }
00502 
00503   i = flagMarkerList_lastBeforeLoc (s, loc);
00504   
00505   /*
00506   ** Go backwards through the remaining flagMarkers in this file.
00507   */
00508 
00509   for (; i >= 0; i--) 
00510     {
00511       flagMarker current = s->elements[i];
00512       
00513       if (!flagMarker_sameFile (current, loc))
00514         {
00515           break;
00516         }
00517 
00518       if (flagMarker_isIgnoreOff (current))
00519         {
00520           return FALSE;;
00521         }
00522       else if (flagMarker_isIgnoreOn (current))
00523         {
00524           return TRUE;
00525         }
00526       else if (flagMarker_isIgnoreCount (current))
00527         {
00528           flagMarkerList_splice (s, i,
00529                                  flagMarker_createSuppress (SKIP_FLAG, loc));
00530           return TRUE;
00531         }
00532       else
00533         {
00534           llassert (flagMarker_isLocalSet (current)
00535                     || flagMarker_isSuppress (current));
00536         }
00537     }
00538   
00539   return FALSE;
00540 }
00541 

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