2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
27 ** based on list_template.c
29 ** where T has T_equal (or change this) and T_unparse
31 ** invariant: flagMarker's are listed in order
34 # include "lclintMacros.nf"
40 flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
43 s->nspace = flagMarkerListBASESIZE;
44 s->elements = (flagMarker *)
45 dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
51 flagMarkerList_grow (flagMarkerList s)
54 flagMarker *newelements;
56 s->nspace += flagMarkerListBASESIZE;
58 newelements = (flagMarker *) dmalloc (sizeof (*newelements)
59 * (s->nelements + s->nspace));
61 for (i = 0; i < s->nelements; i++)
63 newelements[i] = s->elements[i];
67 s->elements = newelements;
70 void flagMarkerList_add (flagMarkerList s, flagMarker fm)
72 int i = s->nelements - 1;
77 flagMarker last = s->elements[i];
80 if (flagMarker_isIgnoreCount (last))
82 if (!flagMarker_isIgnoreOff (fm))
84 if (flagMarker_isLocalSet (fm))
88 cstring_makeLiteral ("Cannot set flag inside ignore "
90 flagMarker_getLoc (fm));
92 (cstring_makeLiteral ("Ignore count region starts"),
93 flagMarker_getLoc (last));
98 if (flagMarker_isIgnoreOn (fm))
102 cstring_makeLiteral ("Cannot nest ignore regions."),
103 flagMarker_getLoc (fm));
105 (cstring_makeLiteral ("Previous ignore region starts"),
106 flagMarker_getLoc (last));
110 flagMarker_free (fm);
116 if (flagMarker_isIgnoreOff (last))
118 flagMarker nlast = s->elements [i - 1];
120 if (flagMarker_isIgnoreCount (nlast))
122 if (fileloc_sameFile (flagMarker_getLoc (fm),
123 flagMarker_getLoc (last))
124 && fileloc_notAfter (flagMarker_getLoc (fm),
125 flagMarker_getLoc (last)))
127 if (flagMarker_isLocalSet (fm))
131 cstring_makeLiteral ("Cannot set flag inside ignore "
133 flagMarker_getLoc (fm));
135 (cstring_makeLiteral ("Ignore count region starts"),
136 flagMarker_getLoc (nlast));
141 if (flagMarker_isIgnoreOn (fm))
145 cstring_makeLiteral ("Cannot nest ignore regions."),
146 flagMarker_getLoc (fm));
148 (cstring_makeLiteral ("Previous ignore region starts"),
149 flagMarker_getLoc (nlast));
153 flagMarker_free (fm);
163 ** all this code is necessary to check the invariant is preserved
167 && !flagMarker_sameFile (s->elements[i],
168 flagMarker_getLoc (fm)))
174 ** reprocessing header file, okay to be out of order
177 if (i >= 0 && !fileloc_isHeader (flagMarker_getLoc (fm)))
181 llassert (!flagMarker_beforeMarker (s->elements[i],
182 flagMarker_getLoc (fm)));
188 flagMarkerList_grow (s);
192 s->elements[s->nelements] = fm;
196 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
200 fileloc loc = fileloc_undefined;
201 bool inCount = FALSE;
205 for (i = 0; i < s->nelements; i++)
207 flagMarker current = s->elements[i];
209 if (flagMarker_isIgnoreCount (current))
213 nexpected = flagMarker_getCount (current);
214 loc = flagMarker_getLoc (current);
217 else if (flagMarker_isIgnoreOff (current))
222 llassert (fileloc_isDefined (loc));
224 if (nexpected > 0 && nexpected != nsuppressed)
229 ("Line expects to suppress %d error%p, found %d error%p",
230 nexpected, nsuppressed),
235 else if (flagMarker_isSuppress (current))
248 static void flagMarkerList_splice (flagMarkerList s,
250 /*@keep@*/ flagMarker fm)
252 fileloc loc = flagMarker_getLoc (fm);
253 fileloc beforeloc, afterloc;
256 llassert (index >= 0 && (index + 1 < s->nelements));
258 beforeloc = flagMarker_getLoc (s->elements[index]);
259 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
261 llassert (fileloc_sameFile (beforeloc, loc));
262 llassert (fileloc_sameFile (afterloc, loc));
266 flagMarkerList_grow (s);
269 for (i = s->nelements; i > index + 1; i--)
271 s->elements[i] = s->elements[i - 1];
274 s->elements[index + 1] = fm;
281 flagMarkerList_unparse (flagMarkerList s)
284 cstring st = cstring_makeLiteral ("[");
286 for (i = 0; i < s->nelements; i++)
290 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
293 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
296 st = message ("%q ]", st);
301 flagMarkerList_free (flagMarkerList s)
304 for (i = 0; i < s->nelements; i++)
306 flagMarker_free (s->elements[i]);
315 ** > in ignore region (there is an ignore ON marker not followed by OFF)
319 ** > not in ignore region
323 ** > not in ignore region
324 ** > code is unset or =
326 ** requires: invariant for flagMarkerList:
327 ** flagMarker's are sorted by line and col
331 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
335 for (i = s->nelements - 1; i >= 0; i--)
337 flagMarker current = s->elements[i];
339 if (fileloc_sameFile (current->loc, loc)
340 && (!flagMarker_beforeMarker (current, loc)))
345 if (flagMarker_sameFile (current, loc)
346 && (!flagMarker_beforeMarker (current, loc)))
357 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
360 bool ignoreOff = FALSE;
361 bool nameChecksOff = FALSE;
362 bool flagOff = FALSE;
365 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
367 if (fileloc_isLib (loc))
369 i = s->nelements - 1;
374 i = flagMarkerList_lastBeforeLoc (s, loc);
384 ** Go backwards through the remaining flagMarkers in this file.
389 flagMarker current = s->elements[i];
392 if (!islib && !flagMarker_sameFile (current, loc))
397 if (flagMarker_isIgnoreOff (current))
401 else if (flagMarker_isIgnoreOn (current))
408 else if (flagMarker_isIgnoreCount (current))
412 flagMarkerList_splice (s, i,
413 flagMarker_createSuppress (code, loc));
417 else if (flagMarker_isLocalSet (current))
420 if (!flagOff && flagMarker_getCode (current) == code)
422 ynm set = flagMarker_getSet (current);
443 if (isNameChecksFlag && !nameChecksOff)
455 if (flagMarker_getCode (current) == FLG_NAMECHECKS
456 && !nameChecksOff && isNameChecksFlag)
458 ynm set = flagMarker_getSet (current);
468 nameChecksOff = TRUE;
473 nameChecksOff = TRUE;
477 if (ignoreOff && flagOff)
486 llassert (flagMarker_isSuppress (current));
494 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
498 if (fileloc_isLib (loc))
503 i = flagMarkerList_lastBeforeLoc (s, loc);
506 ** Go backwards through the remaining flagMarkers in this file.
511 flagMarker current = s->elements[i];
513 if (!flagMarker_sameFile (current, loc))
518 if (flagMarker_isIgnoreOff (current))
522 else if (flagMarker_isIgnoreOn (current))
526 else if (flagMarker_isIgnoreCount (current))
528 flagMarkerList_splice (s, i,
529 flagMarker_createSuppress (SKIP_FLAG, loc));
534 llassert (flagMarker_isLocalSet (current)
535 || flagMarker_isSuppress (current));