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