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