]> andersk Git - splint.git/blob - src/flagMarkerList.c
Renamed lclintMacros.nf splintMacros.nf
[splint.git] / src / flagMarkerList.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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.
19 **
20 ** For information on splint: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
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 "splintMacros.nf"
35 # include "basic.h"
36
37 static int flagMarkerList_lastBeforeLoc (flagMarkerList p_s, fileloc p_loc) /*@*/ ;
38
39 flagMarkerList
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
52 static void
53 flagMarkerList_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
72 void flagMarkerList_add (flagMarkerList s, flagMarker fm)
73 {
74   int i = s->nelements - 1;
75   int lastloc;
76
77   DPRINTF (("Flag marker: %s", flagMarker_unparse (fm)));
78
79   if (i > 0)
80     {
81       flagMarker last = s->elements[i];
82
83       if (flagMarker_isIgnoreCount (last))
84         {
85           if (!flagMarker_isIgnoreOff (fm))
86             {
87               if (flagMarker_isLocalSet (fm))
88                 {
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                     }
99                 }
100               else 
101                 {
102                   if (flagMarker_isIgnoreOn (fm)) 
103                     {
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                         }
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];
125
126               if (flagMarker_isIgnoreCount (nlast))
127                 {
128                   if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
129                                                flagMarker_getLoc (nlast)))
130                     {
131                       if (flagMarker_isLocalSet (fm))
132                         {
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                             }
147                         }
148                       else 
149                         {
150                           if (flagMarker_isIgnoreOn (fm)) 
151                             {
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                                 }
161                             }
162                         }
163                       
164                       flagMarker_free (fm);
165                       return;
166                     }
167                 }
168             }
169         }
170     }
171
172
173   /*
174   ** Need to insert this flag in the right place (after the last before loc flag)
175   */
176
177   lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
178
179   if (s->nspace <= 0)
180     {
181       flagMarkerList_grow (s);
182     }
183   
184   s->nspace--;
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
207   s->nelements++;
208   DPRINTF (("Add flag ==> %s", flagMarkerList_unparse (s)));
209 }
210
211 void 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;
218   
219   for (i = 0; i < s->nelements; i++)
220     {
221       flagMarker current = s->elements[i];
222       DPRINTF (("flagMarker: %s / %s",
223                 flagMarker_unparse (current),
224                 bool_unparse (inCount)));
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;
233         }
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                 {
243                   /* Must use forceerror to prevent self-suppression! */
244                   llforceerror
245                     (FLG_SUPCOUNTS,
246                      message 
247                      ("Line expects to suppress %d error%&, found %d error%&",
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
266 static 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
299 flagMarkerList_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
318 void
319 flagMarkerList_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
348 static int
349 flagMarkerList_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         }
362     }
363
364   return -1;
365 }
366           
367 ynm
368 flagMarkerList_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     }
387   
388   if (i < 0)
389     {
390       DPRINTF (("RETURNING!"));
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];
401       
402       DPRINTF (("Check current: %s", flagMarker_unparse (current)));
403
404       if (!islib && !flagMarker_sameFile (current, loc))
405         {
406           DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
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                     {
450                       flagOff = TRUE;
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                     {
486                       nameChecksOff = TRUE;
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
506 bool
507 flagMarkerList_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.365488 seconds and 5 git commands to generate.