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"
37 static int flagMarkerList_lastBeforeLoc (flagMarkerList p_s, fileloc p_loc) /*@*/ ;
42 flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
45 s->nspace = flagMarkerListBASESIZE;
46 s->elements = (flagMarker *)
47 dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
53 flagMarkerList_grow (flagMarkerList s)
56 flagMarker *newelements;
58 s->nspace += flagMarkerListBASESIZE;
60 newelements = (flagMarker *) dmalloc (sizeof (*newelements)
61 * (s->nelements + s->nspace));
63 for (i = 0; i < s->nelements; i++)
65 newelements[i] = s->elements[i];
69 s->elements = newelements;
72 void flagMarkerList_add (flagMarkerList s, flagMarker fm)
74 int i = s->nelements - 1;
77 DPRINTF (("Flag marker: %s", flagMarker_unparse (fm)));
81 flagMarker last = s->elements[i];
83 if (flagMarker_isIgnoreCount (last))
85 if (!flagMarker_isIgnoreOff (fm))
87 if (flagMarker_isLocalSet (fm))
91 cstring_makeLiteral ("Cannot set flag inside ignore "
93 flagMarker_getLoc (fm)))
96 (cstring_makeLiteral ("Ignore count region starts"),
97 flagMarker_getLoc (last));
102 if (flagMarker_isIgnoreOn (fm))
106 cstring_makeLiteral ("Cannot nest ignore regions."),
107 flagMarker_getLoc (fm)))
110 (cstring_makeLiteral ("Previous ignore region starts"),
111 flagMarker_getLoc (last));
116 flagMarker_free (fm);
122 if (flagMarker_isIgnoreOff (last))
124 flagMarker nlast = s->elements [i - 1];
126 if (flagMarker_isIgnoreCount (nlast))
128 if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
129 flagMarker_getLoc (nlast)))
131 if (flagMarker_isLocalSet (fm))
135 cstring_makeLiteral ("Cannot set flag inside ignore "
137 flagMarker_getLoc (fm)))
140 (cstring_makeLiteral ("Ignore count region starts"),
141 flagMarker_getLoc (nlast));
142 DPRINTF (("Last: %s / %s",
143 fileloc_unparse (flagMarker_getLoc (last)),
144 fileloc_unparse (flagMarker_getLoc (fm))));
150 if (flagMarker_isIgnoreOn (fm))
154 cstring_makeLiteral ("Cannot nest ignore regions."),
155 flagMarker_getLoc (fm)))
158 (cstring_makeLiteral ("Previous ignore region starts"),
159 flagMarker_getLoc (nlast));
164 flagMarker_free (fm);
174 ** Need to insert this flag in the right place (after the last before loc flag)
177 lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
181 flagMarkerList_grow (s);
188 /* Add it to the end of the list */
189 s->elements[s->nelements] = fm;
193 DPRINTF (("Inserting: %s in %s",
194 flagMarker_unparse (fm),
195 flagMarkerList_unparse (s)));
197 /* Insert it at location lastloc + 1, push other flags down */
198 for (i = s->nelements; i > lastloc + 1; i--)
200 s->elements [i] = s->elements [i - 1];
203 s->elements [lastloc + 1] = fm;
208 DPRINTF (("Add flag ==> %s", flagMarkerList_unparse (s)));
211 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
215 fileloc loc = fileloc_undefined;
216 bool inCount = FALSE;
220 for (i = 0; i < s->nelements; i++)
222 flagMarker current = s->elements[i];
224 if (flagMarker_isIgnoreCount (current))
228 nexpected = flagMarker_getCount (current);
229 loc = flagMarker_getLoc (current);
232 else if (flagMarker_isIgnoreOff (current))
237 llassert (fileloc_isDefined (loc));
239 if (nexpected > 0 && nexpected != nsuppressed)
241 /* Must use forceerror to prevent self-suppression! */
245 ("Line expects to suppress %d error%&, found %d error%&",
246 nexpected, nsuppressed),
251 else if (flagMarker_isSuppress (current))
264 static void flagMarkerList_splice (flagMarkerList s,
266 /*@keep@*/ flagMarker fm)
268 fileloc loc = flagMarker_getLoc (fm);
269 fileloc beforeloc, afterloc;
272 llassert (index >= 0 && (index + 1 < s->nelements));
274 beforeloc = flagMarker_getLoc (s->elements[index]);
275 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
277 llassert (fileloc_sameFile (beforeloc, loc));
278 llassert (fileloc_sameFile (afterloc, loc));
282 flagMarkerList_grow (s);
285 for (i = s->nelements; i > index + 1; i--)
287 s->elements[i] = s->elements[i - 1];
290 s->elements[index + 1] = fm;
297 flagMarkerList_unparse (flagMarkerList s)
300 cstring st = cstring_makeLiteral ("[");
302 for (i = 0; i < s->nelements; i++)
306 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
309 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
312 st = message ("%q ]", st);
317 flagMarkerList_free (flagMarkerList s)
320 for (i = 0; i < s->nelements; i++)
322 flagMarker_free (s->elements[i]);
331 ** > in ignore region (there is an ignore ON marker not followed by OFF)
335 ** > not in ignore region
339 ** > not in ignore region
340 ** > code is unset or =
342 ** requires: invariant for flagMarkerList:
343 ** flagMarker's are sorted by line and col
347 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
351 for (i = s->nelements - 1; i >= 0; i--)
353 flagMarker current = s->elements[i];
355 if (fileloc_sameFile (current->loc, loc)
356 && (!flagMarker_beforeMarker (current, loc)))
366 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
369 bool ignoreOff = FALSE;
370 bool nameChecksOff = FALSE;
371 bool flagOff = FALSE;
374 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
376 if (fileloc_isLib (loc))
378 i = s->nelements - 1;
383 i = flagMarkerList_lastBeforeLoc (s, loc);
388 DPRINTF (("RETURNING!"));
393 ** Go backwards through the remaining flagMarkers in this file.
398 flagMarker current = s->elements[i];
400 DPRINTF (("Check current: %s", flagMarker_unparse (current)));
402 if (!islib && !flagMarker_sameFile (current, loc))
404 DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
408 if (flagMarker_isIgnoreOff (current))
412 else if (flagMarker_isIgnoreOn (current))
419 else if (flagMarker_isIgnoreCount (current))
423 flagMarkerList_splice (s, i,
424 flagMarker_createSuppress (code, loc));
428 else if (flagMarker_isLocalSet (current))
431 if (!flagOff && flagMarker_getCode (current) == code)
433 ynm set = flagMarker_getSet (current);
454 if (isNameChecksFlag && !nameChecksOff)
466 if (flagMarker_getCode (current) == FLG_NAMECHECKS
467 && !nameChecksOff && isNameChecksFlag)
469 ynm set = flagMarker_getSet (current);
479 nameChecksOff = TRUE;
484 nameChecksOff = TRUE;
488 if (ignoreOff && flagOff)
497 llassert (flagMarker_isSuppress (current));
505 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
509 if (fileloc_isLib (loc))
514 i = flagMarkerList_lastBeforeLoc (s, loc);
517 ** Go backwards through the remaining flagMarkers in this file.
522 flagMarker current = s->elements[i];
524 if (!flagMarker_sameFile (current, loc))
529 if (flagMarker_isIgnoreOff (current))
533 else if (flagMarker_isIgnoreOn (current))
537 else if (flagMarker_isIgnoreCount (current))
539 flagMarkerList_splice (s, i,
540 flagMarker_createSuppress (SKIP_FLAG, loc));
545 llassert (flagMarker_isLocalSet (current)
546 || flagMarker_isSuppress (current));