]> andersk Git - splint.git/blob - src/flags.c
Fixed checking for shift expressions.
[splint.git] / src / flags.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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** flags.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30 # include "portab.h"
31
32 /*
33 ** from the CC man page:
34 **
35 **  -Idir          Search for #include files whose names do not begin with a
36 **                    slash (/) in the following order: (1) in the directory of
37 **                    the dir argument, (2) in the directories specified by -I
38 **                    options, (3) in the standard directory (/usr/include).
39 */
40
41 /* needed for string literals literals */
42
43 typedef struct { 
44   flagkind kind;
45   /*@null@*/ /*@observer@*/ char *name;
46   /*@null@*/ /*@observer@*/ char *describe;
47 } flagcatinfo;
48
49 static flagcatinfo categories[] =
50 {
51   { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
52   { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
53   { FK_USE, "alluse", "all declarations are used" } ,
54   { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
55   { FK_ARRAY, "arrays", "special checking involving arrays" } ,
56   { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
57   { FK_COMMENTS, "comments", "interpretation of semantic comments" } ,
58   { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
59   { FK_CONTROL, "controlflow", "suspicious control structures" } ,
60   { FK_DEBUG, "debug", "flags for debugging lclint" } ,
61   { FK_DECL, "declarations", "consistency of declarations" } ,
62   { FK_DEF, "definition", "undefined storage errors" } ,
63   { FK_DIRECT, "directories", "set directores" } ,
64   { FK_DISPLAY, "display", "control what is displayed" } ,
65   { FK_EFFECT, "effect", "statements with no effects" } ,
66   { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
67   { FK_EXPORT, "export", "control what may be exported" } ,
68   { FK_EXPOSURE, "exposure", "representation exposure" } ,
69   { FK_FILES, "files", "control system files" } ,
70   { FK_FORMAT, "format", "control format of warning messages" } ,
71   { FK_GLOBALS, "globals", "use of global and file static variables" },
72   { FK_HEADERS, "headers", "control inclusion and generation of header files" },
73   { FK_HELP, "help", "on-line help" },
74   { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
75   { FK_INIT, "initializations", "initialization files" } ,
76   { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
77   { FK_LEAK, "leaks", "memory leaks" } ,
78   { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
79   { FK_LIMITS, "limits", "violations of set limits" } ,
80   { FK_MACROS, "macros", "expansion, definition and use of macros" },
81   { FK_MEMORY, "memory", "memory management" } ,
82   { FK_MODIFIES, "modification", "modification errors" } ,
83   { FK_NAMES, "names", "naming conventions and limits" } ,
84   { FK_NULL, "null", "misuses of null pointers" } ,
85   { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
86   { FK_OPS, "operations", "checking of primitive operations" } ,
87   { FK_PARAMS, "parameters", "function and macro parameters" } ,
88   { FK_SPEED, "performance", "speeding up checking" } ,
89   { FK_POINTER, "pointers", "pointers" } ,
90   { FK_PRED, "predicates", "condition test expressions" } ,
91   { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
92   { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
93   { FK_PROTOS, "prototypes", "function prototypes" } ,
94   { FK_DEAD, "released", "using storage that has been deallocated" } ,
95   { FK_IGNORERET, "returnvals", "ignored return values" },
96   { FK_SECURITY, "security", "possible security vulnerability" },
97   { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
98   { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
99   { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
100   { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
101   { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
102   { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
103   { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
104   { FK_SYNTAX, NULL, NULL } ,
105   { FK_TYPE, NULL, NULL } ,
106   { FK_SECRET, NULL, NULL } ,
107   { FK_OBSOLETE, NULL, NULL } ,
108   { FK_NONE, NULL, NULL }  /* must be last */
109 } ; 
110
111 typedef enum {
112   ARG_NONE,
113   ARG_VALUE,
114   ARG_STRING,
115   ARG_SPECIAL
116 } argcode;
117
118 typedef struct { 
119   flagkind main;
120   flagkind sub;
121   bool isSpecial;  /* setting this flag may set other flags (or values) */
122   bool isIdem;     /* idempotent - always sets to TRUE */
123   bool isGlobal;   /* cannot be set locally (using control comments) */
124   bool isModeFlag; /* set by modes */
125   argcode argtype;
126   /*@observer@*/ char *flag;
127   flagcode code; 
128   /*@observer@*/ /*@null@*/ char *desc;
129   bn_mstring hint; 
130   int nreported; 
131   int nsuppressed; 
132 } fflag;
133
134 typedef fflag flaglist[];
135
136 # include "flags.def"
137
138 /*@iter allFlags (yield observer fflag f); @*/
139 # define allFlags(m_f) \
140   { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
141 # define end_allFlags }}
142
143 static bn_mstring mode_names[] =
144
145   "weak", "standard", "checks", "strict", NULL, 
146 };
147
148 /*@iter allModes (yield bn_mstring modename)@*/
149 # define allModes(m_m) \
150   { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
151       { bn_mstring m_m = mode_names[m_ii]; m_ii++; 
152
153 # define end_allModes }}
154
155 /*@+enumint@*/
156
157 static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
158 static cstringSList sortedFlags (void) /*@*/ ;
159 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
160
161 static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_msgstream@*/ ;
162
163 # if 0
164 static /*@unused@*/ cstring listModes (void) /*@*/ ;
165 # endif
166
167 bool flagcode_isSpecialFlag (flagcode f)
168 {
169   return (flags[f].isSpecial);
170 }
171
172 bool flagcode_isGlobalFlag (flagcode f)
173 {
174   return (flags[f].isGlobal);
175 }
176
177 bool flagcode_isIdemFlag (flagcode f)
178 {
179   return (flags[f].isIdem);
180 }
181
182 bool flagcode_isModeFlag (flagcode f)
183 {
184   return (flags[f].isModeFlag);
185 }
186
187 bool flagcode_isNameChecksFlag (flagcode f)
188 {
189   return (flags[f].main == FK_NAMES);
190 }
191
192 /*
193 ** Internal consistency check on the flags.
194 */
195
196 void flags_initMod ()
197 {
198   allFlagCodes (code)
199     {
200       /*@+enumint@*/
201       if (flags[code].code != code)
202         {
203           fprintf (stderr, 
204                    "*** ERROR: inconsistent flag %s / %d / %d", 
205                    flags[code].flag,
206                    flags[code].code, code);
207           
208           llbug (message ("*** ERROR: inconsistent flag %s / %d / %d", 
209                           cstring_fromChars (flags[code].flag),
210                           flags[code].code, code));
211         }
212       /*@=enumint@*/
213     } end_allFlagCodes;
214 }
215
216 void
217 summarizeErrors ()
218 {
219   bool hadOne = FALSE;
220   int sumrep = 0;
221   int sumsup = 0;
222
223   char *buf = mstring_create (128);
224
225   allFlags (f)
226     {
227       if (f.nreported > 0 || f.nsuppressed > 0)
228         {
229           int nrep = f.nreported;
230           int nsup = f.nsuppressed;
231           cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
232
233           if (!hadOne)
234             {
235               llmsgplain (cstring_makeLiteral
236                           ("\nError Type                Reported  Suppressed\n"
237                            "===================       ========  ========="));
238               hadOne = TRUE;
239             }
240
241           sprintf (buf, "%s%7d   %9d", cstring_toCharsSafe (fs), nrep, nsup);
242
243           sumrep += nrep;
244           sumsup += nsup;
245           
246           cstring_free (fs);
247           llmsg (cstring_copy (cstring_fromChars (buf)));
248         }
249     } end_allFlags;
250
251   if (hadOne)
252     {
253       cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
254
255       llmsglit ("                          ========  =========");
256
257       sprintf (buf, "%s%7d   %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
258       cstring_free (ts);
259       llmsgplain (cstring_copy (cstring_fromChars (buf)));
260     }
261
262   sfree (buf);
263 }
264
265 /*@+enumindex@*/
266
267 void
268 flagcode_recordError (flagcode f)
269 {
270   if (f != INVALID_FLAG)
271     {
272       if (f == FLG_WARNFLAGS)
273         {
274           ; /* don't count these */
275         }
276       else
277         {
278           flags[f].nreported = flags[f].nreported + 1;
279         }
280     }
281   else
282     {
283       llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
284     }
285 }
286
287 void
288 flagcode_recordSuppressed (flagcode f)
289 {
290   llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
291
292   flags[f].nsuppressed = flags[f].nsuppressed + 1;
293 }
294
295 int
296 flagcode_numReported (flagcode f)
297 {
298   llassert (f != INVALID_FLAG);
299
300   return (flags[f].nreported);
301 }
302
303 /*@observer@*/ cstring
304 flagcodeHint (flagcode f)
305 {
306   llassert (f != INVALID_FLAG);
307
308   if (mstring_isDefined (flags[f].hint))
309     {
310       return (cstring_fromChars (flags[f].hint));
311     }
312   else
313     {
314       return (cstring_fromChars (flags[f].desc));
315     }
316 }
317
318 static int categorySize (flagkind kind) /*@*/ 
319 {
320   int n = 0;
321
322   
323   allFlags (f)
324     {
325       if (f.main == kind || f.sub == kind)
326         {
327                   n++;
328         }
329     } end_allFlags;
330
331   return n;
332 }
333
334 flagkind identifyCategory (cstring s)
335 {
336   int i;
337
338   for (i = 0; categories[i].kind != FK_NONE; i++)
339     {
340       if (mstring_isDefined (categories[i].name))
341         {
342           if (cstring_equalLit (s, categories[i].name))
343             {
344               return categories[i].kind;
345             }
346         }
347     }
348
349   return FK_NONE;
350 }
351
352 static /*@observer@*/ cstring categoryName (flagkind kind)
353 {
354   int i;
355
356   for (i = 0; categories[i].kind != FK_NONE; i++)
357     {
358       if (categories[i].kind == kind)
359         {
360           return (cstring_fromChars (categories[i].name));
361         }
362     }
363   
364   return (cstring_makeLiteralTemp ("<No Category>"));
365 }
366
367 static int categoryIndex (flagkind kind)
368 {
369   int i;
370
371   for (i = 0; categories[i].kind != FK_NONE; i++)
372     {
373       if (categories[i].kind == kind)
374         {
375           return i;
376         }
377     }
378
379   return -1;
380 }
381
382 void printCategory (flagkind kind)
383 {
384   int index = categoryIndex (kind);
385
386   llassert (index >= 0);
387
388   llmsg (message ("%s (%d flags)\n\3%s\n\n", 
389                   cstring_fromChars (categories[index].name), 
390                   categorySize (kind),
391                   cstring_fromChars (categories[index].describe)));
392
393   allFlags (f)
394     {
395       if (f.main == kind || f.sub == kind)
396         {
397           llmsg (message ("   %s\n\6%q", cstring_fromChars (f.flag), 
398                           describeFlagCode (f.code)));
399         }
400     } end_allFlags;
401 }
402
403 void 
404 listAllCategories (void)
405 {
406   int i;
407
408   for (i = 0; categories[i].kind != FK_NONE; i++)
409     {
410       flagkind kind = categories[i].kind ;
411
412       if (categories[i].describe != NULL)
413         {
414           llmsg (message ("%s (%d flags)\n\3%s", 
415                           categoryName (kind), 
416                           categorySize (kind),
417                           cstring_fromChars (categories[i].describe)));
418         }
419     }
420 }
421
422 void
423 printAllFlags (bool desc, bool full)
424 {
425   if (full)
426     {
427       cstringSList fl = sortedFlags ();
428
429       cstringSList_elements (fl, el)
430         {
431           llmsg (message ("%q\n\n", describeFlag (el)));
432         } end_cstringSList_elements ;
433
434       cstringSList_free (fl);
435     }
436   else
437     {
438       allFlags (f)
439         {
440           if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
441             {
442               if (mstring_isDefined (f.desc))
443                 {
444                   if (desc)
445                     {
446                       llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
447                                       cstring_fromChars (f.desc)));
448                     }
449                 }
450             }
451         } end_allFlags;
452     }
453 }
454
455 cstring
456 describeFlagCode (flagcode flag)
457 {
458   cstring ret = cstring_undefined;
459   fflag f;
460
461   if (flagcode_isInvalid (flag))
462     {
463       return (cstring_makeLiteral ("<invalid>"));
464     }
465
466   context_resetAllFlags ();
467   
468   f = flags[flag];
469   ret = cstring_copy (cstring_fromChars (f.desc));
470
471   
472   if (f.sub != FK_NONE)
473     {
474       ret = message ("%q\nCategories: %s, %s",
475                      ret, 
476                      categoryName (f.main),
477                      categoryName (f.sub));
478     }
479   else 
480     {
481       if (f.main != FK_NONE)
482         {
483           cstring cname = categoryName (f.main);
484           
485           if (cstring_isDefined (cname))
486             {
487               ret = message ("%q\nCategory: %s",
488                              ret, cname);
489             }
490         }
491     }
492
493   if (f.isModeFlag)
494     {
495       bool first = TRUE;
496
497       allModes (mname)
498         {
499           context_setMode (cstring_fromChars (mname));
500
501           if (first)
502             {
503               ret = message ("%q\nMode Settings: %s %s",
504                              ret, cstring_fromChars (mname), 
505                              cstring_makeLiteralTemp 
506                              (context_getFlag (flag) ? "+" : "-"));
507               first = FALSE;
508             }
509           else
510             {
511               ret = message ("%q, %s %s",
512                              ret, cstring_fromChars (mname),
513                              cstring_makeLiteralTemp 
514                              (context_getFlag (flag) ? "+" : "-"));
515             }
516         } end_allModes;
517     }
518   else
519     {
520       ret = message ("%q\nDefault Setting: %s",
521                      ret, 
522                      cstring_makeLiteralTemp 
523                      (context_getFlag (flag) ? "+" : "-"));
524     }
525
526   if (f.isGlobal)
527     {
528       ret = message("%q\nSet globally only", ret);
529     }
530   else
531     {
532       ret = message("%q\nSet locally", ret);
533     }
534
535   switch (f.argtype)
536     {
537     case ARG_NONE:
538     case ARG_SPECIAL:
539       break;
540     case ARG_VALUE:
541       if (flag == FLG_COMMENTCHAR)
542         {
543           ret = message("%q\nCharacter Argument.  Default: %h",
544                         ret, (char) context_getValue (flag));
545         }
546       else
547         {
548           ret = message("%q\nNumeric Argument.  Default: %d",
549                         ret,
550                         context_getValue (flag));
551         }
552       break;
553     case ARG_STRING:
554       if (cstring_isDefined (context_getString (flag)))
555         {
556           ret = message("%q\nString Argument.  Default: %s",
557                         ret,
558                         context_getString (flag));
559         }
560       else
561         {
562           ret = message("%q\nString Argument.  No default.", ret);
563         }
564       break;
565     }
566
567   if (mstring_isDefined (f.hint))
568     {
569       ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
570     }
571
572   return ret;
573 }
574
575 cstring
576 describeFlag (cstring flagname)
577 {
578   cstring oflagname = cstring_copy (flagname);
579   flagcode f = flags_identifyFlag (flagname);
580
581   if (flagcode_isSkip (f))
582     {
583       cstring_free (oflagname);
584       return cstring_undefined;
585     }
586   else if (flagcode_isValid (f))
587     {
588       if (cstring_equal (flagname, oflagname))
589         {
590           cstring_free (oflagname);
591           return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
592         }
593       else
594         {
595           return (message ("%q (standardized name: %s)\n\3%q",
596                            oflagname, flagname, describeFlagCode (f)));
597         }
598     }
599   else
600     {
601       if (isMode (flagname))
602         {
603           cstring_free (oflagname);
604
605           return
606             (message ("%s: predefined mode (see User's Guide for information)",
607                       flagname));
608         }
609       else
610         {
611           return (message ("%q: <invalid flag>", oflagname));
612         }
613     }
614 }
615
616 static cstringSList
617 sortedFlags (void)
618 {
619   cstringSList s = cstringSList_new ();
620
621   allFlags (f)
622     {
623       if (f.desc != NULL)
624         {
625           s = cstringSList_add (s, cstring_fromChars (f.flag));
626         }
627     } end_allFlags;
628
629   cstringSList_alphabetize (s);
630
631   return s;
632 }
633
634 void printAlphaFlags ()
635 {
636   cstringSList fl = sortedFlags ();
637
638   cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25); 
639   cstringSList_free (fl);
640 }
641
642 /*@observer@*/ cstring
643 flagcode_unparse (flagcode code)
644 {
645   if (code == INVALID_FLAG)
646     {
647       return cstring_makeLiteralTemp ("<invalid flag>");
648     }
649
650   return cstring_fromChars (flags[code].flag);
651 }
652
653 /*
654 ** Transforms a flag into its cannonical form.
655 **
656 ** The following transformations are made:
657 **
658 **    function      -> fcn
659 **    variable      -> var
660 **    constant      -> const
661 **    iterator      -> iter
662 **    parameter     -> param
663 **    unrecognized  -> unrecog
664 **    qualifier     -> qual         
665 **    declaration   -> decl
666 **    globalias     -> (no change)
667 **    global        -> glob
668 **    modifies      -> mods
669 **    modify        -> mod
670 **    pointer       -> ptr
671 **    implies       -> imp
672 **    implicit      -> imp
673 **    implied       -> imp
674 **    unconstrained -> unspec       
675 **    unconst       -> unspec
676 **    memory        -> mem
677 **    length        -> len
678 */
679
680 static void
681 canonicalizeFlag (cstring s)
682 {
683   int i = 0;
684   static bn_mstring transform[] = 
685     { 
686       "function", "fcn",
687       "variable", "var",
688       "constant", "const",
689       "iterator", "iter",
690       "parameter", "param",
691       "unrecognized", "unrecog",
692       "qualifier", "qual",
693       "declaration", "decl",
694       "globals", "globs", 
695       "modifies", "mods", 
696       "modify", "mod",
697       "pointer", "ptr",
698       "implies", "imp",
699       "implicit", "imp",
700       "implied", "imp",
701       "unconstrained", "uncon",
702       "unconst", "uncon",
703       "memory", "mem",
704       "length", "len",
705       "return", "ret",
706       "system", "sys",
707       NULL
708       } ;
709   char *current;
710
711   while ((current = transform[i]) != NULL)
712     {
713       if (cstring_containsLit (s, current))
714         {
715           cstring_replaceLit (s, current, transform[i+1]);
716         }
717       i += 2;
718     }
719
720   /* remove whitespace, -'s, and _'s */
721   cstring_stripChars (s, " -_");
722 }
723
724 flagcode
725 flags_identifyFlag (cstring s)
726 {
727   return flags_identifyFlagAux (s, FALSE);
728 }
729
730 flagcode
731 flags_identifyFlagQuiet (cstring s)
732 {
733   return flags_identifyFlagAux (s, TRUE);
734 }
735
736 static flagcode
737 flags_identifyFlagAux (cstring s, bool quiet)
738 {
739   if (cstring_length (s) == 0) {
740     /* evs 2000-06-25: A malformed flag. */
741     return INVALID_FLAG;
742   }
743
744   if (cstring_firstChar (s) == 'I')
745     {
746       return FLG_INCLUDEPATH; /* no space after -I */
747     }
748
749   if (cstring_firstChar (s) == 'S') 
750     {
751       return FLG_SPECPATH;    /* no space after -S */
752     }
753
754   if (cstring_firstChar (s) == 'D') 
755     {
756       return FLG_DEFINE;      /* no space after -D */
757     }
758
759   if (cstring_firstChar (s) == 'U') 
760     {
761       return FLG_UNDEFINE;    /* no space after -D */
762     }
763
764   canonicalizeFlag (s);
765
766   allFlags (f)
767     {
768       if (cstring_equal (cstring_fromChars (f.flag), s))
769         {
770           return (f.code);
771         }
772     } end_allFlags;
773
774   /*
775   ** Synonyms
776   */
777
778   if (cstring_equalLit (s, "pred"))
779     {
780       return FLG_PREDBOOL;
781     }
782
783   if (cstring_equalLit (s, "modobserverstrict"))
784     {
785       return FLG_MODOBSERVERUNCON;
786     }
787
788   if (cstring_equalLit (s, "czechnames"))
789     {
790       return FLG_CZECH;
791     }
792
793   if (cstring_equalLit (s, "slovaknames"))
794     {
795       return FLG_SLOVAK;
796     }
797
798   if (cstring_equalLit (s, "czechoslovaknames"))
799     {
800       return FLG_CZECHOSLOVAK;
801     }
802
803   if (cstring_equalLit (s, "globunspec")
804            || cstring_equalLit (s, "globuncon"))
805     {
806       return FLG_GLOBUNSPEC;
807     }
808
809   if (cstring_equalLit (s, "modglobsunspec")
810            || cstring_equalLit (s, "modglobsuncon")
811            || cstring_equalLit (s, "modglobsnomods"))
812     {
813       return FLG_MODGLOBSUNSPEC;
814     }
815
816   if (cstring_equalLit (s, "export"))
817     {
818       return FLG_EXPORTANY;
819     }
820
821   if (cstring_equalLit (s, "macrospec"))
822     {
823       return FLG_MACRODECL;
824     }
825   
826   if (cstring_equalLit (s, "ansireservedlocal"))
827     {
828       return FLG_ANSIRESERVEDLOCAL;
829     }
830
831   if (cstring_equalLit (s, "warnposix"))
832     {
833       return FLG_WARNPOSIX;
834     }
835
836   if (cstring_equalLit (s, "defuse"))
837     {
838       return FLG_USEDEF;
839     }
840
841   if (cstring_equalLit (s, "macroundef"))
842     {
843       return FLG_MACROUNDEF;
844     }
845
846   if (cstring_equalLit (s, "showcol"))
847     {
848       return FLG_SHOWCOL;
849     }
850
851   if (cstring_equalLit (s, "intbool"))
852     {
853       return FLG_BOOLINT;
854     }
855
856   if (cstring_equalLit (s, "intchar"))
857     {
858       return FLG_CHARINT;
859     }
860
861   if (cstring_equalLit (s, "intenum"))
862     {
863       return FLG_ENUMINT;
864     }
865
866   /*
867   ** For our European friends...
868   */
869
870   if (cstring_equalLit (s, "isolib"))
871     {
872       return FLG_ANSILIB;
873     }
874
875   if (cstring_equalLit (s, "isostrictlib"))
876     {
877       return FLG_STRICTLIB;
878     }
879
880   if (cstring_equalLit (s, "ansistrictlib"))
881     {
882       return FLG_STRICTLIB;
883     }
884
885   if (cstring_equalLit (s, "skipisoheaders"))
886     {
887       return FLG_SKIPANSIHEADERS;
888     }
889
890   if (cstring_equalLit (s, "isoreserved"))
891     {
892       return FLG_ANSIRESERVED;
893     }
894
895   if (cstring_equalLit (s, "isoreservedinternal"))
896     {
897       return FLG_ANSIRESERVEDLOCAL;
898     }
899
900   if (cstring_equalLit (s, "isolimits"))
901     {
902       return FLG_ANSILIMITS;
903     }
904
905   /*
906   ** Obsolete Flags
907   */
908   
909   if (cstring_equalLit (s, "accessunspec"))
910     {
911       if (!quiet) 
912         {
913           llerror_flagWarning 
914             (cstring_makeLiteral
915              ("accessunspec flag is no longer supported.  It has been replaced by accessmodule, accessfile and "
916               "accessfunction to provide more precise control of accessibility "
917               "of representations.  For more information, "
918               "see lclint -help accessmodule"));
919         }
920       
921       return SKIP_FLAG;
922     }
923   else if (cstring_equalLit (s, "staticmods"))
924     {
925       if (!quiet) 
926         {
927           llerror_flagWarning 
928             (cstring_makeLiteral
929              ("staticmods flag is obsolete.  You probably "
930               "want impcheckmodstatics.  For more information, "
931               "see lclint -help impcheckmodstatics"));
932         }
933
934       return SKIP_FLAG;
935     }
936   else if (cstring_equalLit (s, "bool"))
937     {
938       if (!quiet) 
939         {
940           llerror_flagWarning
941             (cstring_makeLiteral ("bool flag is obsolete.  It never really "
942                                   "made sense in the first place."));
943         }
944       
945       return SKIP_FLAG;
946     }
947   else if (cstring_equalLit (s, "shiftsigned"))
948     {
949       if (!quiet) 
950         {
951           llerror_flagWarning
952             (cstring_makeLiteral ("shiftsigned flag is obsolete.  You probably "
953                                   "want bitwisesigned, shiftnegative or shiftsize."));
954         }
955       
956       return SKIP_FLAG;
957     }
958   else if (cstring_equalLit (s, "ansi"))
959     {
960       if (!quiet) 
961         {
962           llerror_flagWarning
963             (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
964                                   "want noparams and/or oldstyle."));
965         }
966       
967       return SKIP_FLAG;
968     }
969   else if (cstring_equalLit (s, "stdio"))
970     {
971       if (!quiet) 
972         {
973           llerror_flagWarning 
974             (cstring_makeLiteral
975              ("stdio flag is obsolete.  You may "
976               "want strictlib or one of the gloabls "
977               "checking flags.  For more information, "
978               "see lclint -help strictlib or lclint -help flags globals"));
979         }
980       
981       return SKIP_FLAG;
982     }
983   else
984     {
985       return INVALID_FLAG;
986     }
987 }
988
989 void setValueFlag (flagcode opt, cstring arg)
990 {
991   switch (opt)
992     {
993     case FLG_EXPECT:
994     case FLG_LCLEXPECT:
995     case FLG_LIMIT:  
996     case FLG_LINELEN:
997     case FLG_INDENTSPACES:
998     case FLG_BUGSLIMIT:
999     case FLG_EXTERNALNAMELEN:
1000     case FLG_INTERNALNAMELEN:
1001     case FLG_CONTROLNESTDEPTH:
1002     case FLG_STRINGLITERALLEN:
1003     case FLG_NUMSTRUCTFIELDS:
1004     case FLG_NUMENUMMEMBERS:
1005     case FLG_INCLUDENEST:
1006       {
1007         int val = cstring_toPosInt (arg);
1008
1009         if (val < 0)
1010           {
1011             llerror 
1012               (FLG_BADFLAG,
1013                message 
1014                ("Flag %s must be followed by a positive number number.  "
1015                 "Followed by %s",
1016                 flagcode_unparse (opt), arg));
1017           }
1018         else
1019           {
1020             context_setValueAndFlag (opt, val);
1021           }
1022       }
1023       break;
1024     case FLG_COMMENTCHAR:
1025       {
1026         if (cstring_length (arg) != 1)
1027           {
1028             llfatalerrorLoc
1029               (message
1030                ("Flag %s should be followed by a single character.  Followed by %s",
1031                 flagcode_unparse (opt), arg));
1032           }
1033         else
1034           {
1035             context_setCommentMarkerChar (cstring_firstChar (arg));
1036           }
1037       }
1038       break;
1039     BADDEFAULT;
1040     }
1041 }
1042
1043 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1044 {
1045   switch (opt)
1046     {
1047     case FLG_TMPDIR:
1048       {
1049         if (cstring_lastChar (arg) == CONNECTCHAR)
1050           {
1051             context_setString (opt, arg);
1052           }
1053         else
1054           {
1055             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1056           }
1057         break;
1058       }
1059     default:
1060       {
1061         context_setString (opt, arg);
1062         break;
1063       }
1064     }
1065 }
1066
1067 cstring
1068 describeModes ()
1069 {
1070   cstring s = cstring_makeLiteral ("Flag                    ");
1071   cstringSList sflags = sortedFlags ();
1072
1073   allModes (modename)
1074     {
1075       s = message ("%q%9s", s, cstring_fromChars (modename));
1076     } end_allModes;
1077   
1078   s = message ("%q\n", s);
1079
1080   cstringSList_elements (sflags, flagname)
1081     {
1082       flagcode code = flags_identifyFlag (flagname);
1083       fflag currentflag = flags[code];
1084       
1085       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1086         {
1087           s = message ("%q\n%27s", s, 
1088                        cstring_fromChars (currentflag.flag));
1089           
1090           allModes (modename)
1091             {
1092               context_setMode (cstring_fromChars (modename));
1093               
1094               if (context_getFlag (code))
1095                 {
1096                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1097                 }
1098               else
1099                 {
1100                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1101                 }
1102
1103               context_resetModeFlags ();
1104             } end_allModes;
1105         }
1106     } end_cstringSList_elements;
1107   
1108   cstringSList_free (sflags);
1109
1110   s = cstring_appendChar (s, '\n');
1111
1112   return (s);
1113 }
1114
1115 # if 0
1116 static /*@unused@*/ cstring
1117 listModes (void)
1118 {
1119   cstring s = cstring_makeLiteral ("\t");
1120   int i = 0;
1121
1122   allModes (modename)
1123     {
1124       if (i != 0 && (i % 4 == 0))
1125         {
1126           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1127         }
1128       else
1129         {
1130           s = message ("%q%15s", s, cstring_fromChars (modename));
1131         }
1132       i++;
1133     } end_allModes;
1134
1135   return s;
1136 }
1137 # endif
1138
1139 bool
1140 isMode (cstring s)
1141 {
1142   allModes (modename)
1143     {
1144       if (mstring_isDefined (modename))
1145         {
1146           if (cstring_equalLit (s, modename))
1147             {
1148               return TRUE;
1149             }
1150         }
1151      } end_allModes;
1152
1153   return FALSE;
1154 }
1155
1156 extern bool flagcode_hasArgument (flagcode f)
1157 {
1158   return (flags[f].argtype != ARG_NONE);
1159 }
1160
1161 extern bool flagcode_hasValue (flagcode f)
1162 {
1163   return (flags[f].argtype == ARG_VALUE);
1164 }
1165
1166 extern bool flagcode_hasString (flagcode f)
1167 {
1168   return (flags[f].argtype == ARG_STRING);
1169 }
1170
1171 extern int flagcode_valueIndex (flagcode f)
1172 {
1173   /*@unchecked@*/ static bool initialized = FALSE;
1174   int i;
1175   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1176   
1177   if (!initialized)
1178     {
1179       int nv = 0;
1180
1181       allFlagCodes (code)
1182         {
1183           if (flagcode_hasValue (code))
1184             {
1185               llassert (nv < NUMVALUEFLAGS);
1186               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1187               valueFlags[nv] = code;
1188               nv++;
1189             }
1190         } end_allFlagCodes;
1191
1192       llassertprint (nv == NUMVALUEFLAGS,
1193                      ("Number of value flags: %d (expected %d)",
1194                       nv, (int) NUMVALUEFLAGS));
1195       initialized = TRUE;
1196     }
1197
1198   for (i = 0; i < NUMVALUEFLAGS; i++)
1199     {
1200       /* static valueFlags must be defined */
1201       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1202         {
1203           return i;
1204         }
1205     }
1206
1207   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1208   exit (EXIT_FAILURE);
1209   /* Cannot do this...might call recursively...
1210   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1211   BADEXIT;
1212   */
1213 }
1214
1215 extern int flagcode_stringIndex (flagcode f)
1216 {
1217   /*@unchecked@*/ static bool initialized = FALSE;
1218   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1219   int i;
1220
1221
1222   if (!initialized)
1223     {
1224       int nv = 0;
1225
1226       allFlagCodes (code)
1227         {
1228           if (flagcode_hasString (code))
1229             {
1230               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1231               stringFlags[nv] = code;
1232               nv++;
1233             }
1234         } end_allFlagCodes;
1235
1236       llassertprint (nv == NUMSTRINGFLAGS,
1237                      ("number of string flags: %d (expected %d)",
1238                       nv, NUMSTRINGFLAGS));
1239       initialized = TRUE;
1240     }
1241
1242   for (i = 0; i < NUMSTRINGFLAGS; i++)
1243     {
1244       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1245         {
1246           return i;
1247         }
1248     }
1249
1250   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1251   BADEXIT;
1252 }
1253
1254 bool flagcode_isNamePrefixFlag (flagcode f)
1255 {
1256   switch (f)
1257     {
1258     case FLG_MACROVARPREFIX:
1259     case FLG_TAGPREFIX:
1260     case FLG_ENUMPREFIX:
1261     case FLG_FILESTATICPREFIX:
1262     case FLG_GLOBPREFIX:
1263     case FLG_TYPEPREFIX:
1264     case FLG_EXTERNALPREFIX:
1265     case FLG_LOCALPREFIX:
1266     case FLG_UNCHECKEDMACROPREFIX:
1267     case FLG_CONSTPREFIX:
1268     case FLG_ITERPREFIX:
1269     case FLG_DECLPARAMPREFIX:
1270       return TRUE;
1271     default:
1272       return FALSE;
1273     }
1274 }
1275         
This page took 0.175027 seconds and 5 git commands to generate.