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