2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
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 "splintMacros.nf"
37 static int flagMarkerList_lastBeforeLoc (flagMarkerList p_s, fileloc p_loc) /*@*/ ;
40 flagMarkerList_contains (flagMarkerList p_s, flagMarker p_fm) /*@*/ ;
45 flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
48 s->nspace = flagMarkerListBASESIZE;
49 s->elements = (flagMarker *)
50 dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
56 flagMarkerList_grow (flagMarkerList s)
59 flagMarker *newelements;
61 s->nspace += flagMarkerListBASESIZE;
63 newelements = (flagMarker *) dmalloc (sizeof (*newelements)
64 * (s->nelements + s->nspace));
66 for (i = 0; i < s->nelements; i++)
68 newelements[i] = s->elements[i];
72 s->elements = newelements;
75 bool flagMarkerList_add (flagMarkerList s, flagMarker fm)
77 int i = s->nelements - 1;
80 DPRINTF (("Add: %s", flagMarker_unparse (fm)));
82 if (flagMarkerList_contains (s, fm))
85 DPRINTF (("List contains: %s", flagMarkerList_unparse (s)));
91 flagMarker last = s->elements[i];
93 if (flagMarker_isIgnoreCount (last))
95 if (!flagMarker_isIgnoreOff (fm))
97 if (flagMarker_isLocalSet (fm))
101 cstring_makeLiteral ("Cannot set flag inside ignore "
103 flagMarker_getLoc (fm)))
106 (cstring_makeLiteral ("Ignore count region starts"),
107 flagMarker_getLoc (last));
112 if (flagMarker_isIgnoreOn (fm))
116 cstring_makeLiteral ("Cannot nest ignore regions."),
117 flagMarker_getLoc (fm)))
120 (cstring_makeLiteral ("Previous ignore region starts"),
121 flagMarker_getLoc (last));
126 flagMarker_free (fm);
132 if (flagMarker_isIgnoreOff (last))
134 flagMarker nlast = s->elements [i - 1];
136 if (flagMarker_isIgnoreCount (nlast))
138 if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
139 flagMarker_getLoc (nlast)))
141 if (flagMarker_isLocalSet (fm))
146 ("Cannot set flag inside ignore "
148 flagMarker_getLoc (fm)))
152 ("Ignore count region starts"),
153 flagMarker_getLoc (nlast));
154 DPRINTF (("Last: %s / %s",
155 fileloc_unparse (flagMarker_getLoc (last)),
156 fileloc_unparse (flagMarker_getLoc (fm))));
162 if (flagMarker_isIgnoreOn (fm))
166 cstring_makeLiteral ("Cannot nest ignore regions."),
167 flagMarker_getLoc (fm)))
170 (cstring_makeLiteral ("Previous ignore region starts"),
171 flagMarker_getLoc (nlast));
176 flagMarker_free (fm);
186 ** Need to insert this flag in the right place (after the last before loc flag)
189 lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
193 flagMarkerList_grow (s);
200 /* Add it to the end of the list */
201 s->elements[s->nelements] = fm;
205 DPRINTF (("Inserting: %s in %s",
206 flagMarker_unparse (fm),
207 flagMarkerList_unparse (s)));
209 /* Insert it at location lastloc + 1, push other flags down */
210 for (i = s->nelements; i > lastloc + 1; i--)
212 s->elements [i] = s->elements [i - 1];
215 s->elements [lastloc + 1] = fm;
223 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
227 fileloc loc = fileloc_undefined;
228 bool inCount = FALSE;
231 for (i = 0; i < s->nelements; i++)
233 flagMarker current = s->elements[i];
234 DPRINTF (("flagMarker: %s / %s",
235 flagMarker_unparse (current),
236 bool_unparse (inCount)));
238 if (flagMarker_isIgnoreCount (current))
242 nexpected = flagMarker_getCount (current);
243 loc = flagMarker_getLoc (current);
246 else if (flagMarker_isIgnoreOff (current))
251 llassert (fileloc_isDefined (loc));
253 if (nexpected > 0 && nexpected != nsuppressed)
255 /* Must use forceerror to prevent self-suppression! */
259 ("Line expects to suppress %d error%&, found %d error%&",
260 nexpected, nsuppressed),
265 else if (flagMarker_isSuppress (current))
278 static void flagMarkerList_splice (flagMarkerList s,
280 /*@keep@*/ flagMarker fm)
282 fileloc loc = flagMarker_getLoc (fm);
283 fileloc beforeloc, afterloc;
286 llassert (index >= 0 && (index + 1 < s->nelements));
288 beforeloc = flagMarker_getLoc (s->elements[index]);
289 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
291 llassert (fileloc_sameFile (beforeloc, loc));
292 llassert (fileloc_sameFile (afterloc, loc));
296 flagMarkerList_grow (s);
299 for (i = s->nelements; i > index + 1; i--)
301 s->elements[i] = s->elements[i - 1];
304 s->elements[index + 1] = fm;
311 flagMarkerList_unparse (flagMarkerList s)
314 cstring st = cstring_makeLiteral ("[");
316 for (i = 0; i < s->nelements; i++)
320 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
323 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
326 st = message ("%q ]", st);
331 flagMarkerList_free (flagMarkerList s)
334 for (i = 0; i < s->nelements; i++)
336 flagMarker_free (s->elements[i]);
344 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
348 for (i = s->nelements - 1; i >= 0; i--)
350 flagMarker current = s->elements[i];
352 if (fileloc_sameFile (current->loc, loc)
353 && (!flagMarker_beforeMarker (current, loc)))
363 flagMarkerList_contains (flagMarkerList s, flagMarker fm)
367 for (i = s->nelements - 1; i >= 0; i--)
369 flagMarker current = s->elements[i];
371 if (flagMarker_equal (current, fm))
382 ** > in ignore region (there is an ignore ON marker not followed by OFF)
386 ** > not in ignore region
390 ** > not in ignore region
391 ** > code is unset or =
393 ** requires: invariant for flagMarkerList:
394 ** flagMarker's are sorted by line and col
398 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
401 bool ignoreOff = FALSE;
402 bool nameChecksOff = FALSE;
403 bool flagOff = FALSE;
406 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
408 if (fileloc_isLib (loc))
410 i = s->nelements - 1;
415 i = flagMarkerList_lastBeforeLoc (s, loc);
420 DPRINTF (("RETURNING!"));
425 ** Go backwards through the remaining flagMarkers in this file.
430 flagMarker current = s->elements[i];
432 DPRINTF (("Check current: %s", flagMarker_unparse (current)));
434 if (!islib && !flagMarker_sameFile (current, loc))
436 DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
440 if (flagMarker_isIgnoreOff (current))
444 else if (flagMarker_isIgnoreOn (current))
451 else if (flagMarker_isIgnoreCount (current))
455 flagMarkerList_splice (s, i,
456 flagMarker_createSuppress (code, loc));
460 else if (flagMarker_isLocalSet (current))
463 if (!flagOff && flagMarker_getCode (current) == code)
465 ynm set = flagMarker_getSet (current);
486 if (isNameChecksFlag && !nameChecksOff)
498 if (flagMarker_getCode (current) == FLG_NAMECHECKS
499 && !nameChecksOff && isNameChecksFlag)
501 ynm set = flagMarker_getSet (current);
511 nameChecksOff = TRUE;
516 nameChecksOff = TRUE;
520 if (ignoreOff && flagOff)
529 llassert (flagMarker_isSuppress (current));
537 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
541 if (fileloc_isLib (loc))
546 i = flagMarkerList_lastBeforeLoc (s, loc);
549 ** Go backwards through the remaining flagMarkers in this file.
554 flagMarker current = s->elements[i];
556 if (!flagMarker_sameFile (current, loc))
561 if (flagMarker_isIgnoreOff (current))
565 else if (flagMarker_isIgnoreOn (current))
569 else if (flagMarker_isIgnoreCount (current))
571 flagMarkerList_splice (s, i,
572 flagMarker_createSuppress (SKIP_FLAG, loc));
577 llassert (flagMarker_isLocalSet (current)
578 || flagMarker_isSuppress (current));