2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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;
76 flagMarker last = s->elements[i];
78 if (flagMarker_isIgnoreCount (last))
80 if (!flagMarker_isIgnoreOff (fm))
82 if (flagMarker_isLocalSet (fm))
86 cstring_makeLiteral ("Cannot set flag inside ignore "
88 flagMarker_getLoc (fm)))
91 (cstring_makeLiteral ("Ignore count region starts"),
92 flagMarker_getLoc (last));
97 if (flagMarker_isIgnoreOn (fm))
101 cstring_makeLiteral ("Cannot nest ignore regions."),
102 flagMarker_getLoc (fm)))
105 (cstring_makeLiteral ("Previous ignore region starts"),
106 flagMarker_getLoc (last));
111 flagMarker_free (fm);
117 if (flagMarker_isIgnoreOff (last))
119 flagMarker nlast = s->elements [i - 1];
121 if (flagMarker_isIgnoreCount (nlast))
123 if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
124 flagMarker_getLoc (nlast)))
126 if (flagMarker_isLocalSet (fm))
130 cstring_makeLiteral ("Cannot set flag inside ignore "
132 flagMarker_getLoc (fm)))
135 (cstring_makeLiteral ("Ignore count region starts"),
136 flagMarker_getLoc (nlast));
137 DPRINTF (("Last: %s / %s",
138 fileloc_unparse (flagMarker_getLoc (last)),
139 fileloc_unparse (flagMarker_getLoc (fm))));
145 if (flagMarker_isIgnoreOn (fm))
149 cstring_makeLiteral ("Cannot nest ignore regions."),
150 flagMarker_getLoc (fm)))
153 (cstring_makeLiteral ("Previous ignore region starts"),
154 flagMarker_getLoc (nlast));
159 flagMarker_free (fm);
169 ** all this code is necessary to check the invariant is preserved
173 && !flagMarker_sameFile (s->elements[i],
174 flagMarker_getLoc (fm)))
180 ** reprocessing header file, okay to be out of order
183 if (i >= 0 && !fileloc_isHeader (flagMarker_getLoc (fm)))
187 llassert (!flagMarker_beforeMarker (s->elements[i],
188 flagMarker_getLoc (fm)));
194 flagMarkerList_grow (s);
198 s->elements[s->nelements] = fm;
202 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
206 fileloc loc = fileloc_undefined;
207 bool inCount = FALSE;
211 for (i = 0; i < s->nelements; i++)
213 flagMarker current = s->elements[i];
215 if (flagMarker_isIgnoreCount (current))
219 nexpected = flagMarker_getCount (current);
220 loc = flagMarker_getLoc (current);
223 else if (flagMarker_isIgnoreOff (current))
228 llassert (fileloc_isDefined (loc));
230 if (nexpected > 0 && nexpected != nsuppressed)
232 /* Must use forceerror to prevent self-suppression! */
236 ("Line expects to suppress %d error%&, found %d error%&",
237 nexpected, nsuppressed),
242 else if (flagMarker_isSuppress (current))
255 static void flagMarkerList_splice (flagMarkerList s,
257 /*@keep@*/ flagMarker fm)
259 fileloc loc = flagMarker_getLoc (fm);
260 fileloc beforeloc, afterloc;
263 llassert (index >= 0 && (index + 1 < s->nelements));
265 beforeloc = flagMarker_getLoc (s->elements[index]);
266 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
268 llassert (fileloc_sameFile (beforeloc, loc));
269 llassert (fileloc_sameFile (afterloc, loc));
273 flagMarkerList_grow (s);
276 for (i = s->nelements; i > index + 1; i--)
278 s->elements[i] = s->elements[i - 1];
281 s->elements[index + 1] = fm;
288 flagMarkerList_unparse (flagMarkerList s)
291 cstring st = cstring_makeLiteral ("[");
293 for (i = 0; i < s->nelements; i++)
297 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
300 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
303 st = message ("%q ]", st);
308 flagMarkerList_free (flagMarkerList s)
311 for (i = 0; i < s->nelements; i++)
313 flagMarker_free (s->elements[i]);
322 ** > in ignore region (there is an ignore ON marker not followed by OFF)
326 ** > not in ignore region
330 ** > not in ignore region
331 ** > code is unset or =
333 ** requires: invariant for flagMarkerList:
334 ** flagMarker's are sorted by line and col
338 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
342 for (i = s->nelements - 1; i >= 0; i--)
344 flagMarker current = s->elements[i];
346 if (fileloc_sameFile (current->loc, loc)
347 && (!flagMarker_beforeMarker (current, loc)))
352 if (flagMarker_sameFile (current, loc)
353 && (!flagMarker_beforeMarker (current, loc)))
364 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
367 bool ignoreOff = FALSE;
368 bool nameChecksOff = FALSE;
369 bool flagOff = FALSE;
372 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
374 if (fileloc_isLib (loc))
376 i = s->nelements - 1;
381 i = flagMarkerList_lastBeforeLoc (s, loc);
391 ** Go backwards through the remaining flagMarkers in this file.
396 flagMarker current = s->elements[i];
399 if (!islib && !flagMarker_sameFile (current, loc))
404 if (flagMarker_isIgnoreOff (current))
408 else if (flagMarker_isIgnoreOn (current))
415 else if (flagMarker_isIgnoreCount (current))
419 flagMarkerList_splice (s, i,
420 flagMarker_createSuppress (code, loc));
424 else if (flagMarker_isLocalSet (current))
427 if (!flagOff && flagMarker_getCode (current) == code)
429 ynm set = flagMarker_getSet (current);
450 if (isNameChecksFlag && !nameChecksOff)
462 if (flagMarker_getCode (current) == FLG_NAMECHECKS
463 && !nameChecksOff && isNameChecksFlag)
465 ynm set = flagMarker_getSet (current);
475 nameChecksOff = TRUE;
480 nameChecksOff = TRUE;
484 if (ignoreOff && flagOff)
493 llassert (flagMarker_isSuppress (current));
501 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
505 if (fileloc_isLib (loc))
510 i = flagMarkerList_lastBeforeLoc (s, loc);
513 ** Go backwards through the remaining flagMarkers in this file.
518 flagMarker current = s->elements[i];
520 if (!flagMarker_sameFile (current, loc))
525 if (flagMarker_isIgnoreOff (current))
529 else if (flagMarker_isIgnoreOn (current))
533 else if (flagMarker_isIgnoreCount (current))
535 flagMarkerList_splice (s, i,
536 flagMarker_createSuppress (SKIP_FLAG, loc));
541 llassert (flagMarker_isLocalSet (current)
542 || flagMarker_isSuppress (current));