]> andersk Git - splint.git/blame - src/flagMarkerList.c
noexpand always false.
[splint.git] / src / flagMarkerList.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
616915dd 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.
19**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** flagMarkerList.c
26**
27** based on list_template.c
28**
29** where T has T_equal (or change this) and T_unparse
30**
31** invariant: flagMarker's are listed in order
32*/
33
1b8ae690 34# include "splintMacros.nf"
616915dd 35# include "basic.h"
36
60eced23 37static int flagMarkerList_lastBeforeLoc (flagMarkerList p_s, fileloc p_loc) /*@*/ ;
38
abd7f895 39static bool
40flagMarkerList_contains (flagMarkerList p_s, flagMarker p_fm) /*@*/ ;
41
616915dd 42flagMarkerList
43 flagMarkerList_new ()
44{
45 flagMarkerList s = (flagMarkerList) dmalloc (sizeof (*s));
46
47 s->nelements = 0;
48 s->nspace = flagMarkerListBASESIZE;
49 s->elements = (flagMarker *)
50 dmalloc (sizeof (*s->elements) * flagMarkerListBASESIZE);
51
52 return (s);
53}
54
55static void
56flagMarkerList_grow (flagMarkerList s)
57{
58 int i;
59 flagMarker *newelements;
60
61 s->nspace += flagMarkerListBASESIZE;
62
63 newelements = (flagMarker *) dmalloc (sizeof (*newelements)
64 * (s->nelements + s->nspace));
65
66 for (i = 0; i < s->nelements; i++)
67 {
68 newelements[i] = s->elements[i];
69 }
70
71 sfree (s->elements);
72 s->elements = newelements;
73}
74
abd7f895 75bool flagMarkerList_add (flagMarkerList s, flagMarker fm)
616915dd 76{
77 int i = s->nelements - 1;
60eced23 78 int lastloc;
79
abd7f895 80 DPRINTF (("Add: %s", flagMarker_unparse (fm)));
81
82 if (flagMarkerList_contains (s, fm))
83 {
84 flagMarker_free (fm);
85 DPRINTF (("List contains: %s", flagMarkerList_unparse (s)));
86 return FALSE;
87 }
616915dd 88
616915dd 89 if (i > 0)
90 {
91 flagMarker last = s->elements[i];
92
616915dd 93 if (flagMarker_isIgnoreCount (last))
94 {
95 if (!flagMarker_isIgnoreOff (fm))
96 {
97 if (flagMarker_isLocalSet (fm))
98 {
28bf4b0b 99 if (llforceerror
100 (FLG_WARNFLAGS,
101 cstring_makeLiteral ("Cannot set flag inside ignore "
102 "count region."),
103 flagMarker_getLoc (fm)))
104 {
105 llgenindentmsg
106 (cstring_makeLiteral ("Ignore count region starts"),
107 flagMarker_getLoc (last));
108 }
616915dd 109 }
110 else
111 {
112 if (flagMarker_isIgnoreOn (fm))
113 {
28bf4b0b 114 if (llforceerror
115 (FLG_WARNFLAGS,
116 cstring_makeLiteral ("Cannot nest ignore regions."),
117 flagMarker_getLoc (fm)))
118 {
119 llgenindentmsg
120 (cstring_makeLiteral ("Previous ignore region starts"),
121 flagMarker_getLoc (last));
122 }
616915dd 123 }
124 }
125
126 flagMarker_free (fm);
abd7f895 127 return FALSE;
616915dd 128 }
129 }
130 else
131 {
132 if (flagMarker_isIgnoreOff (last))
133 {
134 flagMarker nlast = s->elements [i - 1];
28bf4b0b 135
616915dd 136 if (flagMarker_isIgnoreCount (nlast))
137 {
28bf4b0b 138 if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
139 flagMarker_getLoc (nlast)))
616915dd 140 {
141 if (flagMarker_isLocalSet (fm))
142 {
28bf4b0b 143 if (llforceerror
144 (FLG_WARNFLAGS,
abd7f895 145 cstring_makeLiteral
146 ("Cannot set flag inside ignore "
147 "count region."),
28bf4b0b 148 flagMarker_getLoc (fm)))
149 {
150 llgenindentmsg
abd7f895 151 (cstring_makeLiteral
152 ("Ignore count region starts"),
28bf4b0b 153 flagMarker_getLoc (nlast));
154 DPRINTF (("Last: %s / %s",
155 fileloc_unparse (flagMarker_getLoc (last)),
156 fileloc_unparse (flagMarker_getLoc (fm))));
157
158 }
616915dd 159 }
160 else
161 {
162 if (flagMarker_isIgnoreOn (fm))
163 {
28bf4b0b 164 if (llforceerror
165 (FLG_WARNFLAGS,
166 cstring_makeLiteral ("Cannot nest ignore regions."),
167 flagMarker_getLoc (fm)))
168 {
169 llgenindentmsg
170 (cstring_makeLiteral ("Previous ignore region starts"),
171 flagMarker_getLoc (nlast));
172 }
616915dd 173 }
174 }
175
176 flagMarker_free (fm);
abd7f895 177 return FALSE;
616915dd 178 }
179 }
180 }
181 }
182 }
183
616915dd 184
185 /*
60eced23 186 ** Need to insert this flag in the right place (after the last before loc flag)
616915dd 187 */
188
60eced23 189 lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
616915dd 190
191 if (s->nspace <= 0)
192 {
193 flagMarkerList_grow (s);
194 }
195
196 s->nspace--;
60eced23 197
198 if (lastloc == -1)
199 {
200 /* Add it to the end of the list */
201 s->elements[s->nelements] = fm;
202 }
203 else
204 {
205 DPRINTF (("Inserting: %s in %s",
206 flagMarker_unparse (fm),
207 flagMarkerList_unparse (s)));
208
209 /* Insert it at location lastloc + 1, push other flags down */
210 for (i = s->nelements; i > lastloc + 1; i--)
211 {
212 s->elements [i] = s->elements [i - 1];
213 }
214
215 s->elements [lastloc + 1] = fm;
216
217 }
218
616915dd 219 s->nelements++;
abd7f895 220 return TRUE;
60eced23 221}
616915dd 222
223void flagMarkerList_checkSuppressCounts (flagMarkerList s)
224{
225 int nexpected = 0;
226 int nsuppressed = 0;
227 fileloc loc = fileloc_undefined;
228 bool inCount = FALSE;
229 int i;
616915dd 230
231 for (i = 0; i < s->nelements; i++)
232 {
233 flagMarker current = s->elements[i];
ccf0a4a8 234 DPRINTF (("flagMarker: %s / %s",
235 flagMarker_unparse (current),
236 bool_unparse (inCount)));
abd7f895 237
616915dd 238 if (flagMarker_isIgnoreCount (current))
239 {
240 llassert (!inCount);
241 inCount = TRUE;
242 nexpected = flagMarker_getCount (current);
243 loc = flagMarker_getLoc (current);
244 nsuppressed = 0;
ccf0a4a8 245 }
616915dd 246 else if (flagMarker_isIgnoreOff (current))
247 {
248 if (inCount)
249 {
250 inCount = FALSE;
251 llassert (fileloc_isDefined (loc));
252
253 if (nexpected > 0 && nexpected != nsuppressed)
254 {
28bf4b0b 255 /* Must use forceerror to prevent self-suppression! */
256 llforceerror
616915dd 257 (FLG_SUPCOUNTS,
258 message
28bf4b0b 259 ("Line expects to suppress %d error%&, found %d error%&",
616915dd 260 nexpected, nsuppressed),
261 loc);
262 }
263 }
264 }
265 else if (flagMarker_isSuppress (current))
266 {
267 nsuppressed++;
268 }
269 else
270 {
271 ;
272 }
273 }
274
275 llassert (!inCount);
276}
277
278static void flagMarkerList_splice (flagMarkerList s,
279 int index,
280 /*@keep@*/ flagMarker fm)
281{
282 fileloc loc = flagMarker_getLoc (fm);
283 fileloc beforeloc, afterloc;
284 int i;
285
286 llassert (index >= 0 && (index + 1 < s->nelements));
287
288 beforeloc = flagMarker_getLoc (s->elements[index]);
289 afterloc = flagMarker_getLoc (s->elements[index + 1]);;
290
291 llassert (fileloc_sameFile (beforeloc, loc));
292 llassert (fileloc_sameFile (afterloc, loc));
293
294 if (s->nspace <= 0)
295 {
296 flagMarkerList_grow (s);
297 }
298
299 for (i = s->nelements; i > index + 1; i--)
300 {
301 s->elements[i] = s->elements[i - 1];
302 }
303
304 s->elements[index + 1] = fm;
305 s->nelements++;
306 s->nspace--;
307
308 }
309
310/*@only@*/ cstring
311flagMarkerList_unparse (flagMarkerList s)
312{
313 int i;
314 cstring st = cstring_makeLiteral ("[");
315
316 for (i = 0; i < s->nelements; i++)
317 {
318 if (i == 0)
319 {
320 st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
321 }
322 else
323 st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
324 }
325
326 st = message ("%q ]", st);
327 return st;
328}
329
330void
331flagMarkerList_free (flagMarkerList s)
332{
333 int i;
334 for (i = 0; i < s->nelements; i++)
335 {
336 flagMarker_free (s->elements[i]);
337 }
338
339 sfree (s->elements);
340 sfree (s);
341}
342
616915dd 343static int
344flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
345{
346 int i;
347
348 for (i = s->nelements - 1; i >= 0; i--)
349 {
350 flagMarker current = s->elements[i];
351
352 if (fileloc_sameFile (current->loc, loc)
353 && (!flagMarker_beforeMarker (current, loc)))
354 {
355 return i;
356 }
616915dd 357 }
358
359 return -1;
360}
abd7f895 361
362static bool
363flagMarkerList_contains (flagMarkerList s, flagMarker fm)
364{
365 int i;
366
367 for (i = s->nelements - 1; i >= 0; i--)
368 {
369 flagMarker current = s->elements[i];
370
371 if (flagMarker_equal (current, fm))
372 {
373 return TRUE;
374 }
375 }
376
377 return FALSE;
378}
379
380/*
381** returns YES iff
382** > in ignore region (there is an ignore ON marker not followed by OFF)
383** > code is OFF (-)
384**
385** returns NO iff
386** > not in ignore region
387** > code is ON (+)
388**
389** returns MAYBE iff
390** > not in ignore region
391** > code is unset or =
392**
393** requires: invariant for flagMarkerList:
394** flagMarker's are sorted by line and col
395*/
616915dd 396
397ynm
398flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
399{
400 int i;
401 bool ignoreOff = FALSE;
402 bool nameChecksOff = FALSE;
403 bool flagOff = FALSE;
404 ynm flagSet = MAYBE;
405 bool islib = FALSE;
406 bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
407
408 if (fileloc_isLib (loc))
409 {
410 i = s->nelements - 1;
411 islib = TRUE;
412 }
413 else
414 {
415 i = flagMarkerList_lastBeforeLoc (s, loc);
416 }
616915dd 417
418 if (i < 0)
419 {
60eced23 420 DPRINTF (("RETURNING!"));
616915dd 421 return MAYBE;
422 }
423
424 /*
425 ** Go backwards through the remaining flagMarkers in this file.
426 */
427
428 for (; i >= 0; i--)
429 {
430 flagMarker current = s->elements[i];
616915dd 431
60eced23 432 DPRINTF (("Check current: %s", flagMarker_unparse (current)));
433
616915dd 434 if (!islib && !flagMarker_sameFile (current, loc))
435 {
60eced23 436 DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
616915dd 437 break;
438 }
439
440 if (flagMarker_isIgnoreOff (current))
441 {
442 ignoreOff = TRUE;
443 }
444 else if (flagMarker_isIgnoreOn (current))
445 {
446 if (!ignoreOff)
447 {
448 return YES;
449 }
450 }
451 else if (flagMarker_isIgnoreCount (current))
452 {
453 if (!ignoreOff)
454 {
455 flagMarkerList_splice (s, i,
456 flagMarker_createSuppress (code, loc));
457 return YES;
458 }
459 }
460 else if (flagMarker_isLocalSet (current))
461 {
462
463 if (!flagOff && flagMarker_getCode (current) == code)
464 {
465 ynm set = flagMarker_getSet (current);
466
467 if (ynm_isOff (set))
468 {
469 return YES;
470 }
471 else
472 {
473 if (ynm_isOn (set))
474 {
475 flagOff = TRUE;
476 flagSet = NO;
477 }
478 else
479 {
60eced23 480 flagOff = TRUE;
616915dd 481 flagSet = MAYBE;
482 }
483
484 if (ignoreOff)
485 {
486 if (isNameChecksFlag && !nameChecksOff)
487 {
488 ;
489 }
490 else
491 {
492 return flagSet;
493 }
494 }
495 }
496 }
497
498 if (flagMarker_getCode (current) == FLG_NAMECHECKS
499 && !nameChecksOff && isNameChecksFlag)
500 {
501 ynm set = flagMarker_getSet (current);
502
503 if (ynm_isOff (set))
504 {
505 return YES;
506 }
507 else
508 {
509 if (ynm_isOn (set))
510 {
511 nameChecksOff = TRUE;
512 flagSet = NO;
513 }
514 else
515 {
60eced23 516 nameChecksOff = TRUE;
616915dd 517 flagSet = MAYBE;
518 }
519
520 if (ignoreOff && flagOff)
521 {
522 return flagSet;
523 }
524 }
525 }
526 }
527 else
528 {
529 llassert (flagMarker_isSuppress (current));
530 }
531 }
532
533 return flagSet;
534}
535
536bool
537flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
538{
539 int i;
540
541 if (fileloc_isLib (loc))
542 {
543 return FALSE;
544 }
545
546 i = flagMarkerList_lastBeforeLoc (s, loc);
547
548 /*
549 ** Go backwards through the remaining flagMarkers in this file.
550 */
551
552 for (; i >= 0; i--)
553 {
554 flagMarker current = s->elements[i];
555
556 if (!flagMarker_sameFile (current, loc))
557 {
558 break;
559 }
560
561 if (flagMarker_isIgnoreOff (current))
562 {
563 return FALSE;;
564 }
565 else if (flagMarker_isIgnoreOn (current))
566 {
567 return TRUE;
568 }
569 else if (flagMarker_isIgnoreCount (current))
570 {
571 flagMarkerList_splice (s, i,
572 flagMarker_createSuppress (SKIP_FLAG, loc));
573 return TRUE;
574 }
575 else
576 {
577 llassert (flagMarker_isLocalSet (current)
578 || flagMarker_isSuppress (current));
579 }
580 }
581
582 return FALSE;
583}
584
This page took 0.138831 seconds and 5 git commands to generate.