2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
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"
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
) /*@*/ ;
44 flagMarkerList_contains (flagMarkerList p_s
, flagMarker p_fm
) /*@*/ ;
47 flagMarkerList_new (void)
49 flagMarkerList s
= (flagMarkerList
) dmalloc (sizeof (*s
));
52 s
->nspace
= flagMarkerListBASESIZE
;
53 s
->elements
= (flagMarker
*)
54 dmalloc (sizeof (*s
->elements
) * flagMarkerListBASESIZE
);
60 flagMarkerList_grow (flagMarkerList s
)
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
];
76 s
->elements
= newelements
;
79 bool flagMarkerList_add (flagMarkerList s
, flagMarker fm
)
81 int i
= s
->nelements
- 1;
84 DPRINTF (("Add: %s", flagMarker_unparse (fm
)));
86 if (flagMarkerList_contains (s
, fm
))
89 DPRINTF (("List contains: %s", flagMarkerList_unparse (s
)));
95 flagMarker last
= s
->elements
[i
];
97 if (flagMarker_isIgnoreCount (last
))
99 if (!flagMarker_isIgnoreOff (fm
))
101 if (flagMarker_isLocalSet (fm
))
105 cstring_makeLiteral ("Cannot set flag inside ignore "
107 flagMarker_getLoc (fm
)))
110 (cstring_makeLiteral ("Ignore count region starts"),
111 flagMarker_getLoc (last
));
116 if (flagMarker_isIgnoreOn (fm
))
120 cstring_makeLiteral ("Cannot nest ignore regions."),
121 flagMarker_getLoc (fm
)))
124 (cstring_makeLiteral ("Previous ignore region starts"),
125 flagMarker_getLoc (last
));
130 flagMarker_free (fm
);
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
))
150 ("Cannot set flag inside ignore "
152 flagMarker_getLoc (fm
)))
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
))));
166 if (flagMarker_isIgnoreOn (fm
))
170 cstring_makeLiteral ("Cannot nest ignore regions."),
171 flagMarker_getLoc (fm
)))
174 (cstring_makeLiteral ("Previous ignore region starts"),
175 flagMarker_getLoc (nlast
));
180 flagMarker_free (fm
);
190 ** Need to insert this flag in the right place (after the last before loc flag)
193 lastloc
= flagMarkerList_lastBeforeLoc (s
, flagMarker_getLoc (fm
));
197 flagMarkerList_grow (s
);
204 /* Add it to the end of the list */
205 s
->elements
[s
->nelements
] = fm
;
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
;
227 void flagMarkerList_checkSuppressCounts (flagMarkerList s
)
231 fileloc loc
= fileloc_undefined
;
232 bool inCount
= FALSE
;
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
))
246 nexpected
= flagMarker_getCount (current
);
247 loc
= flagMarker_getLoc (current
);
250 else if (flagMarker_isIgnoreOff (current
))
255 llassert (fileloc_isDefined (loc
));
257 if (nexpected
> 0 && nexpected
!= nsuppressed
)
259 /* Must use forceerror to prevent self-suppression! */
263 ("Line expects to suppress %d error%&, found %d error%&",
264 nexpected
, nsuppressed
),
269 else if (flagMarker_isSuppress (current
))
282 static void flagMarkerList_splice (flagMarkerList s
,
284 /*@keep@*/ flagMarker fm
)
286 fileloc loc
= flagMarker_getLoc (fm
);
287 fileloc beforeloc
, afterloc
;
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
));
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
;
314 static /*@only@*/ cstring
315 flagMarkerList_unparse (flagMarkerList s
)
318 cstring st
= cstring_makeLiteral ("[");
320 for (i
= 0; i
< s
->nelements
; i
++)
324 st
= message ("%q %q", st
, flagMarker_unparse (s
->elements
[i
]));
327 st
= message ("%q, %q", st
, flagMarker_unparse (s
->elements
[i
]));
330 st
= message ("%q ]", st
);
335 flagMarkerList_free (flagMarkerList s
)
338 for (i
= 0; i
< s
->nelements
; i
++)
340 flagMarker_free (s
->elements
[i
]);
348 flagMarkerList_lastBeforeLoc (flagMarkerList s
, fileloc loc
)
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
)))
367 flagMarkerList_contains (flagMarkerList s
, flagMarker fm
)
371 for (i
= s
->nelements
- 1; i
>= 0; i
--)
373 flagMarker current
= s
->elements
[i
];
375 if (flagMarker_equal (current
, fm
))
386 ** > in ignore region (there is an ignore ON marker not followed by OFF)
390 ** > not in ignore region
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
)
405 bool ignoreOff
= FALSE
;
406 bool nameChecksOff
= FALSE
;
407 bool flagOff
= FALSE
;
410 bool isNameChecksFlag
= flagcode_isNameChecksFlag (code
);
412 if (fileloc_isLib (loc
))
414 i
= s
->nelements
- 1;
419 i
= flagMarkerList_lastBeforeLoc (s
, loc
);
424 DPRINTF (("RETURNING!"));
429 ** Go backwards through the remaining flagMarkers in this file.
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
)));
444 if (flagMarker_isIgnoreOff (current
))
448 else if (flagMarker_isIgnoreOn (current
))
455 else if (flagMarker_isIgnoreCount (current
))
459 flagMarkerList_splice (s
, i
,
460 flagMarker_createSuppress (code
, loc
));
464 else if (flagMarker_isLocalSet (current
))
467 if (!flagOff
&& flagMarker_getCode (current
) == code
)
469 ynm set
= flagMarker_getSet (current
);
490 if (isNameChecksFlag
&& !nameChecksOff
)
502 if (flagMarker_getCode (current
) == FLG_NAMECHECKS
503 && !nameChecksOff
&& isNameChecksFlag
)
505 ynm set
= flagMarker_getSet (current
);
515 nameChecksOff
= TRUE
;
520 nameChecksOff
= TRUE
;
524 if (ignoreOff
&& flagOff
)
533 llassert (flagMarker_isSuppress (current
));
541 flagMarkerList_inIgnore (flagMarkerList s
, fileloc loc
)
545 if (fileloc_isLib (loc
))
550 i
= flagMarkerList_lastBeforeLoc (s
, loc
);
553 ** Go backwards through the remaining flagMarkers in this file.
558 flagMarker current
= s
->elements
[i
];
560 if (!flagMarker_sameFile (current
, loc
))
565 if (flagMarker_isIgnoreOff (current
))
569 else if (flagMarker_isIgnoreOn (current
))
573 else if (flagMarker_isIgnoreCount (current
))
575 flagMarkerList_splice (s
, i
,
576 flagMarker_createSuppress (SKIP_FLAG
, loc
));
581 llassert (flagMarker_isLocalSet (current
)
582 || flagMarker_isSuppress (current
));