]> andersk Git - splint.git/blob - src/flagMarkerList.c
*** empty log message ***
[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 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   
220   for (i = 0; i < s->nelements; i++)
221     {
222       flagMarker current = s->elements[i];
223
224       if (flagMarker_isIgnoreCount (current))
225         {
226           llassert (!inCount);
227           inCount = TRUE;
228           nexpected = flagMarker_getCount (current);
229           loc = flagMarker_getLoc (current);
230           nsuppressed = 0;
231                 }
232       else if (flagMarker_isIgnoreOff (current))
233         {
234           if (inCount)
235             {
236               inCount = FALSE;
237               llassert (fileloc_isDefined (loc));
238
239               if (nexpected > 0 && nexpected != nsuppressed)
240                 {
241                   /* Must use forceerror to prevent self-suppression! */
242                   llforceerror
243                     (FLG_SUPCOUNTS,
244                      message 
245                      ("Line expects to suppress %d error%&, found %d error%&",
246                       nexpected, nsuppressed),
247                      loc);
248                 }
249             }
250         }
251       else if (flagMarker_isSuppress (current))
252         {
253           nsuppressed++;
254         }
255       else
256         {
257           ;
258         }
259     }
260
261   llassert (!inCount);
262 }
263
264 static void flagMarkerList_splice (flagMarkerList s, 
265                                    int index,
266                                    /*@keep@*/ flagMarker fm)
267 {
268   fileloc loc = flagMarker_getLoc (fm);
269   fileloc beforeloc, afterloc;
270   int i;
271
272   llassert (index >= 0 && (index + 1 < s->nelements));
273   
274   beforeloc = flagMarker_getLoc (s->elements[index]);
275   afterloc = flagMarker_getLoc (s->elements[index + 1]);;
276   
277   llassert (fileloc_sameFile (beforeloc, loc));
278   llassert (fileloc_sameFile (afterloc, loc));
279
280   if (s->nspace <= 0)
281     {
282       flagMarkerList_grow (s);
283     }
284   
285   for (i = s->nelements; i > index + 1; i--)
286     {
287       s->elements[i] = s->elements[i - 1];
288     }
289
290   s->elements[index + 1] = fm;
291   s->nelements++;
292   s->nspace--;
293
294   }
295
296 /*@only@*/ cstring
297 flagMarkerList_unparse (flagMarkerList s)
298 {
299    int i;
300    cstring st = cstring_makeLiteral ("[");
301
302    for (i = 0; i < s->nelements; i++)
303      {
304        if (i == 0)
305          {
306            st = message ("%q %q", st, flagMarker_unparse (s->elements[i]));
307          }
308        else
309          st = message ("%q, %q", st, flagMarker_unparse (s->elements[i]));
310      }
311    
312    st = message ("%q ]", st);
313    return st;
314 }
315
316 void
317 flagMarkerList_free (flagMarkerList s)
318 {
319   int i;
320   for (i = 0; i < s->nelements; i++)
321     {
322       flagMarker_free (s->elements[i]);
323     }
324   
325   sfree (s->elements); 
326   sfree (s);
327 }
328
329 /*
330 ** returns YES iff
331 **    > in ignore region (there is an ignore ON marker not followed by OFF)
332 **    > code is OFF (-)
333 **
334 ** returns NO iff
335 **    > not in ignore region
336 **    > code is ON (+)
337 **
338 ** returns MAYBE iff
339 **    > not in ignore region
340 **    > code is unset or =
341 **
342 ** requires: invariant for flagMarkerList:
343 **    flagMarker's are sorted by line and col
344 */
345
346 static int
347 flagMarkerList_lastBeforeLoc (flagMarkerList s, fileloc loc)
348 {
349   int i;
350
351   for (i = s->nelements - 1; i >= 0; i--) 
352     {
353       flagMarker current = s->elements[i];
354       
355       if (fileloc_sameFile (current->loc, loc) 
356           && (!flagMarker_beforeMarker (current, loc)))
357         {
358           return i;
359         }
360     }
361
362   return -1;
363 }
364           
365 ynm
366 flagMarkerList_suppressError (flagMarkerList s, flagcode code, fileloc loc)
367 {
368   int i;
369   bool ignoreOff = FALSE;
370   bool nameChecksOff = FALSE;
371   bool flagOff = FALSE;
372   ynm flagSet = MAYBE;
373   bool islib = FALSE;
374   bool isNameChecksFlag = flagcode_isNameChecksFlag (code);
375
376   if (fileloc_isLib (loc))
377     {
378       i = s->nelements - 1;
379       islib = TRUE;
380     }
381   else
382     {
383       i = flagMarkerList_lastBeforeLoc (s, loc);
384     }
385   
386   if (i < 0)
387     {
388       DPRINTF (("RETURNING!"));
389       return MAYBE;
390     }
391   
392   /*
393   ** Go backwards through the remaining flagMarkers in this file.
394   */
395
396   for (; i >= 0; i--) 
397     {
398       flagMarker current = s->elements[i];
399       
400       DPRINTF (("Check current: %s", flagMarker_unparse (current)));
401
402       if (!islib && !flagMarker_sameFile (current, loc))
403         {
404           DPRINTF (("Not same file: %s", fileloc_unparse (loc)));
405           break;
406         }
407
408       if (flagMarker_isIgnoreOff (current))
409         {
410           ignoreOff = TRUE;
411         }
412       else if (flagMarker_isIgnoreOn (current))
413         {
414           if (!ignoreOff)
415             {
416               return YES;
417             }
418         }
419       else if (flagMarker_isIgnoreCount (current))
420         {
421           if (!ignoreOff)
422             {
423               flagMarkerList_splice (s, i,
424                                      flagMarker_createSuppress (code, loc));
425               return YES;
426             }
427         }
428       else if (flagMarker_isLocalSet (current))
429         {
430           
431           if (!flagOff && flagMarker_getCode (current) == code)
432             {
433               ynm set  = flagMarker_getSet (current);
434               
435               if (ynm_isOff (set))
436                 {
437                   return YES;
438                 }
439               else
440                 {
441                   if (ynm_isOn (set))
442                     {
443                       flagOff = TRUE;
444                       flagSet = NO;
445                     }
446                   else
447                     {
448                       flagOff = TRUE;
449                       flagSet = MAYBE;
450                     }
451                   
452                   if (ignoreOff)
453                     {
454                       if (isNameChecksFlag && !nameChecksOff)
455                         {
456                           ;
457                         }
458                       else
459                         {
460                           return flagSet;
461                         }
462                     }
463                 }
464             }
465           
466           if (flagMarker_getCode (current) == FLG_NAMECHECKS
467               && !nameChecksOff && isNameChecksFlag)
468             {
469               ynm set  = flagMarker_getSet (current);
470               
471               if (ynm_isOff (set))
472                 {
473                   return YES;
474                 }
475               else
476                 {
477                   if (ynm_isOn (set))
478                     {
479                       nameChecksOff = TRUE;
480                       flagSet = NO;
481                     }
482                   else
483                     {
484                       nameChecksOff = TRUE;
485                       flagSet = MAYBE;
486                     }
487                   
488                   if (ignoreOff && flagOff)
489                     {
490                       return flagSet;
491                     }
492                 }
493             }
494         }
495       else
496         {
497           llassert (flagMarker_isSuppress (current));
498         }
499     }
500   
501   return flagSet;
502 }
503
504 bool
505 flagMarkerList_inIgnore (flagMarkerList s, fileloc loc)
506 {
507   int i;
508
509   if (fileloc_isLib (loc))
510     {
511       return FALSE;
512     }
513
514   i = flagMarkerList_lastBeforeLoc (s, loc);
515   
516   /*
517   ** Go backwards through the remaining flagMarkers in this file.
518   */
519
520   for (; i >= 0; i--) 
521     {
522       flagMarker current = s->elements[i];
523       
524       if (!flagMarker_sameFile (current, loc))
525         {
526           break;
527         }
528
529       if (flagMarker_isIgnoreOff (current))
530         {
531           return FALSE;;
532         }
533       else if (flagMarker_isIgnoreOn (current))
534         {
535           return TRUE;
536         }
537       else if (flagMarker_isIgnoreCount (current))
538         {
539           flagMarkerList_splice (s, i,
540                                  flagMarker_createSuppress (SKIP_FLAG, loc));
541           return TRUE;
542         }
543       else
544         {
545           llassert (flagMarker_isLocalSet (current)
546                     || flagMarker_isSuppress (current));
547         }
548     }
549   
550   return FALSE;
551 }
552
This page took 0.080943 seconds and 5 git commands to generate.