]> andersk Git - splint.git/blob - src/flagMarkerList.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[splint.git] / src / flagMarkerList.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 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
37 flagMarkerList
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
50 static void
51 flagMarkerList_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
70 void flagMarkerList_add (flagMarkerList s, flagMarker fm)
71 {
72   int i = s->nelements - 1;
73
74   if (i > 0)
75     {
76       flagMarker last = s->elements[i];
77
78       if (flagMarker_isIgnoreCount (last))
79         {
80           if (!flagMarker_isIgnoreOff (fm))
81             {
82               if (flagMarker_isLocalSet (fm))
83                 {
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                     }
94                 }
95               else 
96                 {
97                   if (flagMarker_isIgnoreOn (fm)) 
98                     {
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                         }
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];
120
121               if (flagMarker_isIgnoreCount (nlast))
122                 {
123                   if (fileloc_sameFileAndLine (flagMarker_getLoc (fm),
124                                                flagMarker_getLoc (nlast)))
125                     {
126                       if (flagMarker_isLocalSet (fm))
127                         {
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                             }
142                         }
143                       else 
144                         {
145                           if (flagMarker_isIgnoreOn (fm)) 
146                             {
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                                 }
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
202 void 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                 {
232                   /* Must use forceerror to prevent self-suppression! */
233                   llforceerror
234                     (FLG_SUPCOUNTS,
235                      message 
236                      ("Line expects to suppress %d error%&, found %d error%&",
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
255 static 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
288 flagMarkerList_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
307 void
308 flagMarkerList_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
337 static int
338 flagMarkerList_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           
363 ynm
364 flagMarkerList_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
500 bool
501 flagMarkerList_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.083582 seconds and 5 git commands to generate.