]> andersk Git - splint.git/blob - src/flagMarkerList.c
noexpand always false.
[splint.git] / src / flagMarkerList.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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: info@splint.org
21 ** To report a bug: splint-bug@splint.org
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 static bool
40 flagMarkerList_contains (flagMarkerList p_s, flagMarker p_fm) /*@*/ ;
41
42 flagMarkerList
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
55 static void
56 flagMarkerList_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
75 bool flagMarkerList_add (flagMarkerList s, flagMarker fm)
76 {
77   int i = s->nelements - 1;
78   int lastloc;
79
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     }
88
89   if (i > 0)
90     {
91       flagMarker last = s->elements[i];
92
93       if (flagMarker_isIgnoreCount (last))
94         {
95           if (!flagMarker_isIgnoreOff (fm))
96             {
97               if (flagMarker_isLocalSet (fm))
98                 {
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                     }
109                 }
110               else 
111                 {
112                   if (flagMarker_isIgnoreOn (fm)) 
113                     {
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                         }
123                     }
124                 }
125
126               flagMarker_free (fm);
127               return FALSE;
128             }
129         }
130       else 
131         {
132           if (flagMarker_isIgnoreOff (last))
133             {
134               flagMarker nlast = s->elements [i - 1];
135
136               if (flagMarker_isIgnoreCount (nlast))
137                 {
138                   if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
139                                                flagMarker_getLoc (nlast)))
140                     {
141                       if (flagMarker_isLocalSet (fm))
142                         {
143                           if (llforceerror 
144                               (FLG_WARNFLAGS,
145                                cstring_makeLiteral
146                                ("Cannot set flag inside ignore "
147                                 "count region."),
148                                flagMarker_getLoc (fm))) 
149                             {
150                               llgenindentmsg 
151                                 (cstring_makeLiteral 
152                                  ("Ignore count region starts"),
153                                  flagMarker_getLoc (nlast));
154                               DPRINTF (("Last: %s / %s",
155                                         fileloc_unparse (flagMarker_getLoc (last)),
156                                         fileloc_unparse (flagMarker_getLoc (fm))));
157                               
158                             }
159                         }
160                       else 
161                         {
162                           if (flagMarker_isIgnoreOn (fm)) 
163                             {
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                                 }
173                             }
174                         }
175                       
176                       flagMarker_free (fm);
177                       return FALSE;
178                     }
179                 }
180             }
181         }
182     }
183
184
185   /*
186   ** Need to insert this flag in the right place (after the last before loc flag)
187   */
188
189   lastloc = flagMarkerList_lastBeforeLoc (s, flagMarker_getLoc (fm));
190
191   if (s->nspace <= 0)
192     {
193       flagMarkerList_grow (s);
194     }
195   
196   s->nspace--;
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
219   s->nelements++;
220   return TRUE;
221 }
222
223 void 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;
230   
231   for (i = 0; i < s->nelements; i++)
232     {
233       flagMarker current = s->elements[i];
234       DPRINTF (("flagMarker: %s / %s",
235                 flagMarker_unparse (current),
236                 bool_unparse (inCount)));
237       
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;
245         }
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                 {
255                   /* Must use forceerror to prevent self-suppression! */
256                   llforceerror
257                     (FLG_SUPCOUNTS,
258                      message 
259                      ("Line expects to suppress %d error%&, found %d error%&",
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
278 static 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
311 flagMarkerList_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
330 void
331 flagMarkerList_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
343 static int
344 flagMarkerList_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         }
357     }
358
359   return -1;
360 }
361
362 static bool
363 flagMarkerList_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 */
396           
397 ynm
398 flagMarkerList_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     }
417   
418   if (i < 0)
419     {
420       DPRINTF (("RETURNING!"));
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];
431       
432       DPRINTF (("Check current: %s", flagMarker_unparse (current)));
433
434       if (!islib && !flagMarker_sameFile (current, loc))
435         {
436           DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
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                     {
480                       flagOff = TRUE;
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                     {
516                       nameChecksOff = TRUE;
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
536 bool
537 flagMarkerList_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.62061 seconds and 5 git commands to generate.