Handle possible null character inside string literal
[splint-patched.git] / src / flagMarkerList.c
blob64d8ee79f6c3d5745e293c32cc174edd37c8b723
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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
25 ** flagMarkerList.c
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"
35 # include "basic.h"
37 /*@constant int flagMarkerListBASESIZE;@*/
38 # define flagMarkerListBASESIZE SMALLBASESIZE
40 static int flagMarkerList_lastBeforeLoc (flagMarkerList p_s, fileloc p_loc) /*@*/ ;
41 static /*@only@*/ cstring flagMarkerList_unparse (flagMarkerList p_s) /*@*/ ;
43 static bool
44 flagMarkerList_contains (flagMarkerList p_s, flagMarker p_fm) /*@*/ ;
46 flagMarkerList
47 flagMarkerList_new (void)
49 flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
51 s->nelements = 0;
52 s->nspace = flagMarkerListBASESIZE;
53 s->elements = (flagMarker *)
54 dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
56 return (s);
59 static void
60 flagMarkerList_grow (flagMarkerList s)
62 int i;
63 flagMarker *newelements;
65 s->nspace += flagMarkerListBASESIZE;
67 newelements = (flagMarker *) dmalloc (sizeof (*newelements)
68 * (s->nelements + s->nspace));
70 for (i = 0; i < s->nelements; i++)
72 newelements[i] = s->elements[i];
75 sfree (s->elements);
76 s->elements = newelements;
79 bool flagMarkerList_add (flagMarkerList s, flagMarker fm)
81 int i = s->nelements - 1;
82 int lastloc;
84 DPRINTF (("Add: %s", flagMarker_unparse (fm)));
86 if (flagMarkerList_contains (s, fm))
88 flagMarker_free (fm);
89 DPRINTF (("List contains: %s", flagMarkerList_unparse (s)));
90 return FALSE;
93 if (i > 0)
95 flagMarker last = s->elements[i];
97 if (flagMarker_isIgnoreCount (last))
99 if (!flagMarker_isIgnoreOff (fm))
101 if (flagMarker_isLocalSet (fm))
103 if (llforceerror
104 (FLG_WARNFLAGS,
105 cstring_makeLiteral ("Cannot set flag inside ignore "
106 "count region."),
107 flagMarker_getLoc (fm)))
109 llgenindentmsg
110 (cstring_makeLiteral ("Ignore count region starts"),
111 flagMarker_getLoc (last));
114 else
116 if (flagMarker_isIgnoreOn (fm))
118 if (llforceerror
119 (FLG_WARNFLAGS,
120 cstring_makeLiteral ("Cannot nest ignore regions."),
121 flagMarker_getLoc (fm)))
123 llgenindentmsg
124 (cstring_makeLiteral ("Previous ignore region starts"),
125 flagMarker_getLoc (last));
130 flagMarker_free (fm);
131 return FALSE;
134 else
136 if (flagMarker_isIgnoreOff (last))
138 flagMarker nlast = s->elements [i - 1];
140 if (flagMarker_isIgnoreCount (nlast))
142 if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
143 flagMarker_getLoc (nlast)))
145 if (flagMarker_isLocalSet (fm))
147 if (llforceerror
148 (FLG_WARNFLAGS,
149 cstring_makeLiteral
150 ("Cannot set flag inside ignore "
151 "count region."),
152 flagMarker_getLoc (fm)))
154 llgenindentmsg
155 (cstring_makeLiteral
156 ("Ignore count region starts"),
157 flagMarker_getLoc (nlast));
158 DPRINTF (("Last: %s / %s",
159 fileloc_unparse (flagMarker_getLoc (last)),
160 fileloc_unparse (flagMarker_getLoc (fm))));
164 else
166 if (flagMarker_isIgnoreOn (fm))
168 if (llforceerror
169 (FLG_WARNFLAGS,
170 cstring_makeLiteral ("Cannot nest ignore regions."),
171 flagMarker_getLoc (fm)))
173 llgenindentmsg
174 (cstring_makeLiteral ("Previous ignore region starts"),
175 flagMarker_getLoc (nlast));
180 flagMarker_free (fm);
181 return FALSE;
190 ** Need to insert this flag in the right place (after the last before loc flag)
193 lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
195 if (s->nspace <= 0)
197 flagMarkerList_grow (s);
200 s->nspace--;
202 if (lastloc == -1)
204 /* Add it to the end of the list */
205 s->elements[s->nelements] = fm;
207 else
209 DPRINTF (("Inserting: %s in %s",
210 flagMarker_unparse (fm),
211 flagMarkerList_unparse (s)));
213 /* Insert it at location lastloc + 1, push other flags down */
214 for (i = s->nelements; i > lastloc + 1; i--)
216 s->elements [i] = s->elements [i - 1];
219 s->elements [lastloc + 1] = fm;
223 s->nelements++;
224 return TRUE;
227 void flagMarkerList_checkSuppressCounts (flagMarkerList s)
229 int nexpected = 0;
230 int nsuppressed = 0;
231 fileloc loc = fileloc_undefined;
232 bool inCount = FALSE;
233 int i;
235 for (i = 0; i < s->nelements; i++)
237 flagMarker current = s->elements[i];
238 DPRINTF (("flagMarker: %s / %s",
239 flagMarker_unparse (current),
240 bool_unparse (inCount)));
242 if (flagMarker_isIgnoreCount (current))
244 llassert (!inCount);
245 inCount = TRUE;
246 nexpected = flagMarker_getCount (current);
247 loc = flagMarker_getLoc (current);
248 nsuppressed = 0;
250 else if (flagMarker_isIgnoreOff (current))
252 if (inCount)
254 inCount = FALSE;
255 llassert (fileloc_isDefined (loc));
257 if (nexpected > 0 && nexpected != nsuppressed)
259 /* Must use forceerror to prevent self-suppression! */
260 llforceerror
261 (FLG_SUPCOUNTS,
262 message
263 ("Line expects to suppress %d error%&, found %d error%&",
264 nexpected, nsuppressed),
265 loc);
269 else if (flagMarker_isSuppress (current))
271 nsuppressed++;
273 else
279 llassert (!inCount);
282 static void flagMarkerList_splice (flagMarkerList s,
283 int index,
284 /*@keep@*/ flagMarker fm)
286 fileloc loc = flagMarker_getLoc (fm);
287 fileloc beforeloc, afterloc;
288 int i;
290 llassert (index >= 0 && (index + 1 < s->nelements));
292 beforeloc = flagMarker_getLoc (s->elements[index]);
293 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
295 llassert (fileloc_sameFile (beforeloc, loc));
296 llassert (fileloc_sameFile (afterloc, loc));
298 if (s->nspace <= 0)
300 flagMarkerList_grow (s);
303 for (i = s->nelements; i > index + 1; i--)
305 s->elements[i] = s->elements[i - 1];
308 s->elements[index + 1] = fm;
309 s->nelements++;
310 s->nspace--;
314 static /*@only@*/ cstring
315 flagMarkerList_unparse (flagMarkerList s)
317 int i;
318 cstring st = cstring_makeLiteral ("[");
320 for (i = 0; i < s->nelements; i++)
322 if (i == 0)
324 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
326 else
327 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
330 st = message ("%q ]", st);
331 return st;
334 void
335 flagMarkerList_free (flagMarkerList s)
337 int i;
338 for (i = 0; i < s->nelements; i++)
340 flagMarker_free (s->elements[i]);
343 sfree (s->elements);
344 sfree (s);
347 static int
348 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
350 int i;
352 for (i = s->nelements - 1; i >= 0; i--)
354 flagMarker current = s->elements[i];
356 if (fileloc_sameFile (current->loc, loc)
357 && (!flagMarker_beforeMarker (current, loc)))
359 return i;
363 return -1;
366 static bool
367 flagMarkerList_contains (flagMarkerList s, flagMarker fm)
369 int i;
371 for (i = s->nelements - 1; i >= 0; i--)
373 flagMarker current = s->elements[i];
375 if (flagMarker_equal (current, fm))
377 return TRUE;
381 return FALSE;
385 ** returns YES iff
386 ** > in ignore region (there is an ignore ON marker not followed by OFF)
387 ** > code is OFF (-)
389 ** returns NO iff
390 ** > not in ignore region
391 ** > code is ON (+)
393 ** returns MAYBE iff
394 ** > not in ignore region
395 ** > code is unset or =
397 ** requires: invariant for flagMarkerList:
398 ** flagMarker's are sorted by line and col
402 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
404 int i;
405 bool ignoreOff = FALSE;
406 bool nameChecksOff = FALSE;
407 bool flagOff = FALSE;
408 ynm flagSet = MAYBE;
409 bool islib = FALSE;
410 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
412 if (fileloc_isLib (loc))
414 i = s->nelements - 1;
415 islib = TRUE;
417 else
419 i = flagMarkerList_lastBeforeLoc (s, loc);
422 if (i < 0)
424 DPRINTF (("RETURNING!"));
425 return MAYBE;
429 ** Go backwards through the remaining flagMarkers in this file.
432 for (; i >= 0; i--)
434 flagMarker current = s->elements[i];
436 DPRINTF (("Check current: %s", flagMarker_unparse (current)));
438 if (!islib && !flagMarker_sameFile (current, loc))
440 DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
441 break;
444 if (flagMarker_isIgnoreOff (current))
446 ignoreOff = TRUE;
448 else if (flagMarker_isIgnoreOn (current))
450 if (!ignoreOff)
452 return YES;
455 else if (flagMarker_isIgnoreCount (current))
457 if (!ignoreOff)
459 flagMarkerList_splice (s, i,
460 flagMarker_createSuppress (code, loc));
461 return YES;
464 else if (flagMarker_isLocalSet (current))
467 if (!flagOff && flagMarker_getCode (current) == code)
469 ynm set = flagMarker_getSet (current);
471 if (ynm_isOff (set))
473 return YES;
475 else
477 if (ynm_isOn (set))
479 flagOff = TRUE;
480 flagSet = NO;
482 else
484 flagOff = TRUE;
485 flagSet = MAYBE;
488 if (ignoreOff)
490 if (isNameChecksFlag && !nameChecksOff)
494 else
496 return flagSet;
502 if (flagMarker_getCode (current) == FLG_NAMECHECKS
503 && !nameChecksOff && isNameChecksFlag)
505 ynm set = flagMarker_getSet (current);
507 if (ynm_isOff (set))
509 return YES;
511 else
513 if (ynm_isOn (set))
515 nameChecksOff = TRUE;
516 flagSet = NO;
518 else
520 nameChecksOff = TRUE;
521 flagSet = MAYBE;
524 if (ignoreOff && flagOff)
526 return flagSet;
531 else
533 llassert (flagMarker_isSuppress (current));
537 return flagSet;
540 bool
541 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
543 int i;
545 if (fileloc_isLib (loc))
547 return FALSE;
550 i = flagMarkerList_lastBeforeLoc (s, loc);
553 ** Go backwards through the remaining flagMarkers in this file.
556 for (; i >= 0; i--)
558 flagMarker current = s->elements[i];
560 if (!flagMarker_sameFile (current, loc))
562 break;
565 if (flagMarker_isIgnoreOff (current))
567 return FALSE;;
569 else if (flagMarker_isIgnoreOn (current))
571 return TRUE;
573 else if (flagMarker_isIgnoreCount (current))
575 flagMarkerList_splice (s, i,
576 flagMarker_createSuppress (SKIP_FLAG, loc));
577 return TRUE;
579 else
581 llassert (flagMarker_isLocalSet (current)
582 || flagMarker_isSuppress (current));
586 return FALSE;