]> andersk Git - splint.git/blob - src/flags.c
9c36b0a59dab75f73bb9cea614c5575979ce4d24
[splint.git] / src / flags.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 ** 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 # if 0
162 static /*@unused@*/ cstring listModes (void) /*@*/ ;
163 # endif
164
165 bool flagcode_isSpecialFlag (flagcode f)
166 {
167   return (flags[f].isSpecial);
168 }
169
170 bool flagcode_isGlobalFlag (flagcode f)
171 {
172   return (flags[f].isGlobal);
173 }
174
175 bool flagcode_isIdemFlag (flagcode f)
176 {
177   return (flags[f].isIdem);
178 }
179
180 bool flagcode_isModeFlag (flagcode f)
181 {
182   return (flags[f].isModeFlag);
183 }
184
185 bool flagcode_isNameChecksFlag (flagcode f)
186 {
187   return (flags[f].main == FK_NAMES);
188 }
189
190 /*
191 ** Internal consistency check on the flags.
192 */
193
194 void flags_initMod ()
195 {
196   allFlagCodes (code)
197     {
198       /*@+enumint@*/
199       if (flags[code].code != code)
200         {
201           fprintf (stderr, 
202                    "*** ERROR: inconsistent flag %s / %d / %d", 
203                    flags[code].flag,
204                    flags[code].code, code);
205           
206           llbug (message ("*** ERROR: inconsistent flag %s / %d / %d", 
207                           cstring_fromChars (flags[code].flag),
208                           flags[code].code, code));
209         }
210       /*@=enumint@*/
211     } end_allFlagCodes;
212 }
213
214 void
215 summarizeErrors ()
216 {
217   bool hadOne = FALSE;
218   int sumrep = 0;
219   int sumsup = 0;
220
221   char *buf = mstring_create (128);
222
223   allFlags (f)
224     {
225       if (f.nreported > 0 || f.nsuppressed > 0)
226         {
227           int nrep = f.nreported;
228           int nsup = f.nsuppressed;
229           cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
230
231           if (!hadOne)
232             {
233               llmsgplain (cstring_makeLiteral
234                           ("\nError Type                Reported  Suppressed\n"
235                            "===================       ========  ========="));
236               hadOne = TRUE;
237             }
238
239           sprintf (buf, "%s%7d   %9d", cstring_toCharsSafe (fs), nrep, nsup);
240
241           sumrep += nrep;
242           sumsup += nsup;
243           
244           cstring_free (fs);
245           llmsg (cstring_copy (cstring_fromChars (buf)));
246         }
247     } end_allFlags;
248
249   if (hadOne)
250     {
251       cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
252
253       llmsglit ("                          ========  =========");
254
255       sprintf (buf, "%s%7d   %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
256       cstring_free (ts);
257       llmsgplain (cstring_copy (cstring_fromChars (buf)));
258     }
259
260   sfree (buf);
261 }
262
263 /*@+enumindex@*/
264
265 void
266 flagcode_recordError (flagcode f)
267 {
268   if (f != INVALID_FLAG)
269     {
270       if (f == FLG_WARNFLAGS)
271         {
272           ; /* don't count these */
273         }
274       else
275         {
276           flags[f].nreported = flags[f].nreported + 1;
277         }
278     }
279   else
280     {
281       llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
282     }
283 }
284
285 void
286 flagcode_recordSuppressed (flagcode f)
287 {
288   llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
289
290   flags[f].nsuppressed = flags[f].nsuppressed + 1;
291 }
292
293 int
294 flagcode_numReported (flagcode f)
295 {
296   llassert (f != INVALID_FLAG);
297
298   return (flags[f].nreported);
299 }
300
301 /*@observer@*/ cstring
302 flagcodeHint (flagcode f)
303 {
304   llassert (f != INVALID_FLAG);
305
306   if (mstring_isDefined (flags[f].hint))
307     {
308       return (cstring_fromChars (flags[f].hint));
309     }
310   else
311     {
312       return (cstring_fromChars (flags[f].desc));
313     }
314 }
315
316 static int categorySize (flagkind kind) /*@*/ 
317 {
318   int n = 0;
319
320   
321   allFlags (f)
322     {
323       if (f.main == kind || f.sub == kind)
324         {
325                   n++;
326         }
327     } end_allFlags;
328
329   return n;
330 }
331
332 flagkind identifyCategory (cstring s)
333 {
334   int i;
335
336   for (i = 0; categories[i].kind != FK_NONE; i++)
337     {
338       if (mstring_isDefined (categories[i].name))
339         {
340           if (cstring_equalLit (s, categories[i].name))
341             {
342               return categories[i].kind;
343             }
344         }
345     }
346
347   return FK_NONE;
348 }
349
350 static /*@observer@*/ cstring categoryName (flagkind kind)
351 {
352   int i;
353
354   for (i = 0; categories[i].kind != FK_NONE; i++)
355     {
356       if (categories[i].kind == kind)
357         {
358           return (cstring_fromChars (categories[i].name));
359         }
360     }
361   
362   return (cstring_makeLiteralTemp ("<No Category>"));
363 }
364
365 static int categoryIndex (flagkind kind)
366 {
367   int i;
368
369   for (i = 0; categories[i].kind != FK_NONE; i++)
370     {
371       if (categories[i].kind == kind)
372         {
373           return i;
374         }
375     }
376
377   return -1;
378 }
379
380 void printCategory (flagkind kind)
381 {
382   int index = categoryIndex (kind);
383
384   llassert (index >= 0);
385
386   llmsg (message ("%s (%d flags)\n\3%s\n\n", 
387                   cstring_fromChars (categories[index].name), 
388                   categorySize (kind),
389                   cstring_fromChars (categories[index].describe)));
390
391   allFlags (f)
392     {
393       if (f.main == kind || f.sub == kind)
394         {
395           llmsg (message ("   %s\n\6%q", cstring_fromChars (f.flag), 
396                           describeFlagCode (f.code)));
397         }
398     } end_allFlags;
399 }
400
401 void 
402 listAllCategories (void)
403 {
404   int i;
405
406   for (i = 0; categories[i].kind != FK_NONE; i++)
407     {
408       flagkind kind = categories[i].kind ;
409
410       if (categories[i].describe != NULL)
411         {
412           llmsg (message ("%s (%d flags)\n\3%s", 
413                           categoryName (kind), 
414                           categorySize (kind),
415                           cstring_fromChars (categories[i].describe)));
416         }
417     }
418 }
419
420 void
421 printAllFlags (bool desc, bool full)
422 {
423   if (full)
424     {
425       cstringSList fl = sortedFlags ();
426
427       cstringSList_elements (fl, el)
428         {
429           llmsg (message ("%q\n\n", describeFlag (el)));
430         } end_cstringSList_elements ;
431
432       cstringSList_free (fl);
433     }
434   else
435     {
436       allFlags (f)
437         {
438           if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
439             {
440               if (mstring_isDefined (f.desc))
441                 {
442                   if (desc)
443                     {
444                       llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
445                                       cstring_fromChars (f.desc)));
446                     }
447                 }
448             }
449         } end_allFlags;
450     }
451 }
452
453 cstring
454 describeFlagCode (flagcode flag)
455 {
456   cstring ret = cstring_undefined;
457   fflag f;
458
459   if (flagcode_isInvalid (flag))
460     {
461       return (cstring_makeLiteral ("<invalid>"));
462     }
463
464   context_resetAllFlags ();
465   
466   f = flags[flag];
467   ret = cstring_copy (cstring_fromChars (f.desc));
468
469   
470   if (f.sub != FK_NONE)
471     {
472       ret = message ("%q\nCategories: %s, %s",
473                      ret, 
474                      categoryName (f.main),
475                      categoryName (f.sub));
476     }
477   else 
478     {
479       if (f.main != FK_NONE)
480         {
481           cstring cname = categoryName (f.main);
482           
483           if (cstring_isDefined (cname))
484             {
485               ret = message ("%q\nCategory: %s",
486                              ret, cname);
487             }
488         }
489     }
490
491   if (f.isModeFlag)
492     {
493       bool first = TRUE;
494
495       allModes (mname)
496         {
497           context_setMode (cstring_fromChars (mname));
498
499           if (first)
500             {
501               ret = message ("%q\nMode Settings: %s %s",
502                              ret, cstring_fromChars (mname), 
503                              cstring_makeLiteralTemp 
504                              (context_getFlag (flag) ? "+" : "-"));
505               first = FALSE;
506             }
507           else
508             {
509               ret = message ("%q, %s %s",
510                              ret, cstring_fromChars (mname),
511                              cstring_makeLiteralTemp 
512                              (context_getFlag (flag) ? "+" : "-"));
513             }
514         } end_allModes;
515     }
516   else
517     {
518       ret = message ("%q\nDefault Setting: %s",
519                      ret, 
520                      cstring_makeLiteralTemp 
521                      (context_getFlag (flag) ? "+" : "-"));
522     }
523
524   if (f.isGlobal)
525     {
526       ret = message("%q\nSet globally only", ret);
527     }
528   else
529     {
530       ret = message("%q\nSet locally", ret);
531     }
532
533   switch (f.argtype)
534     {
535     case ARG_NONE:
536     case ARG_SPECIAL:
537       break;
538     case ARG_VALUE:
539       if (flag == FLG_COMMENTCHAR)
540         {
541           ret = message("%q\nCharacter Argument.  Default: %h",
542                         ret, (char) context_getValue (flag));
543         }
544       else
545         {
546           ret = message("%q\nNumeric Argument.  Default: %d",
547                         ret,
548                         context_getValue (flag));
549         }
550       break;
551     case ARG_STRING:
552       if (cstring_isDefined (context_getString (flag)))
553         {
554           ret = message("%q\nString Argument.  Default: %s",
555                         ret,
556                         context_getString (flag));
557         }
558       else
559         {
560           ret = message("%q\nString Argument.  No default.", ret);
561         }
562       break;
563     }
564
565   if (mstring_isDefined (f.hint))
566     {
567       ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
568     }
569
570   return ret;
571 }
572
573 cstring
574 describeFlag (cstring flagname)
575 {
576   cstring oflagname = cstring_copy (flagname);
577   flagcode f = identifyFlag (flagname);
578
579   if (flagcode_isSkip (f))
580     {
581       cstring_free (oflagname);
582       return cstring_undefined;
583     }
584   else if (flagcode_isValid (f))
585     {
586       if (cstring_equal (flagname, oflagname))
587         {
588           cstring_free (oflagname);
589           return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
590         }
591       else
592         {
593           return (message ("%q (standardized name: %s)\n\3%q",
594                            oflagname, flagname, describeFlagCode (f)));
595         }
596     }
597   else
598     {
599       if (isMode (flagname))
600         {
601           cstring_free (oflagname);
602
603           return
604             (message ("%s: predefined mode (see User's Guide for information)",
605                       flagname));
606         }
607       else
608         {
609           return (message ("%q: <invalid flag>", oflagname));
610         }
611     }
612 }
613
614 static cstringSList
615 sortedFlags (void)
616 {
617   cstringSList s = cstringSList_new ();
618
619   allFlags (f)
620     {
621       if (f.desc != NULL)
622         {
623           s = cstringSList_add (s, cstring_fromChars (f.flag));
624         }
625     } end_allFlags;
626
627   cstringSList_alphabetize (s);
628
629   return s;
630 }
631
632 void printAlphaFlags ()
633 {
634   cstringSList fl = sortedFlags ();
635
636   cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25); 
637   cstringSList_free (fl);
638 }
639
640 /*@observer@*/ cstring
641 flagcode_unparse (flagcode code)
642 {
643   if (code == INVALID_FLAG)
644     {
645       return cstring_makeLiteralTemp ("<invalid flag>");
646     }
647
648   return cstring_fromChars (flags[code].flag);
649 }
650
651 /*
652 ** Transforms a flag into its cannonical form.
653 **
654 ** The following transformations are made:
655 **
656 **    function      -> fcn
657 **    variable      -> var
658 **    constant      -> const
659 **    iterator      -> iter
660 **    parameter     -> param
661 **    unrecognized  -> unrecog
662 **    qualifier     -> qual         
663 **    declaration   -> decl
664 **    globalias     -> (no change)
665 **    global        -> glob
666 **    modifies      -> mods
667 **    modify        -> mod
668 **    pointer       -> ptr
669 **    implies       -> imp
670 **    implicit      -> imp
671 **    implied       -> imp
672 **    unconstrained -> unspec       
673 **    unconst       -> unspec
674 **    memory        -> mem
675 **    length        -> len
676 */
677
678 static void
679 canonicalizeFlag (cstring s)
680 {
681   int i = 0;
682   static bn_mstring transform[] = 
683     { 
684       "function", "fcn",
685       "variable", "var",
686       "constant", "const",
687       "iterator", "iter",
688       "parameter", "param",
689       "unrecognized", "unrecog",
690       "qualifier", "qual",
691       "declaration", "decl",
692       "globals", "globs", 
693       "modifies", "mods", 
694       "modify", "mod",
695       "pointer", "ptr",
696       "implies", "imp",
697       "implicit", "imp",
698       "implied", "imp",
699       "unconstrained", "uncon",
700       "unconst", "uncon",
701       "memory", "mem",
702       "length", "len",
703       "return", "ret",
704       "system", "sys",
705       NULL
706       } ;
707   char *current;
708
709   while ((current = transform[i]) != NULL)
710     {
711       if (cstring_containsLit (s, current))
712         {
713           cstring_replaceLit (s, current, transform[i+1]);
714         }
715       i += 2;
716     }
717
718   /* remove whitespace, -'s, and _'s */
719   cstring_stripChars (s, " -_");
720 }
721
722 flagcode
723 identifyFlag (cstring s)
724 {
725   if (cstring_length (s) == 0) {
726     /* evs 2000-06-25: A malformed flag. */
727     return INVALID_FLAG;
728   }
729
730   if (cstring_firstChar (s) == 'I')
731     {
732       return FLG_INCLUDEPATH; /* no space after -I */
733     }
734
735   if (cstring_firstChar (s) == 'S') 
736     {
737       return FLG_SPECPATH;    /* no space after -S */
738     }
739
740   if (cstring_firstChar (s) == 'D') 
741     {
742       return FLG_DEFINE;      /* no space after -D */
743     }
744
745   if (cstring_firstChar (s) == 'U') 
746     {
747       return FLG_UNDEFINE;    /* no space after -D */
748     }
749
750   canonicalizeFlag (s);
751
752   allFlags (f)
753     {
754       if (cstring_equal (cstring_fromChars (f.flag), s))
755         {
756           return (f.code);
757         }
758     } end_allFlags;
759
760   /*
761   ** Synonyms
762   */
763
764   if (cstring_equalLit (s, "pred"))
765     {
766       return FLG_PREDBOOL;
767     }
768
769   if (cstring_equalLit (s, "modobserverstrict"))
770     {
771       return FLG_MODOBSERVERUNCON;
772     }
773
774   if (cstring_equalLit (s, "czechnames"))
775     {
776       return FLG_CZECH;
777     }
778
779   if (cstring_equalLit (s, "slovaknames"))
780     {
781       return FLG_SLOVAK;
782     }
783
784   if (cstring_equalLit (s, "czechoslovaknames"))
785     {
786       return FLG_CZECHOSLOVAK;
787     }
788
789   if (cstring_equalLit (s, "globunspec")
790            || cstring_equalLit (s, "globuncon"))
791     {
792       return FLG_GLOBUNSPEC;
793     }
794
795   if (cstring_equalLit (s, "modglobsunspec")
796            || cstring_equalLit (s, "modglobsuncon")
797            || cstring_equalLit (s, "modglobsnomods"))
798     {
799       return FLG_MODGLOBSUNSPEC;
800     }
801
802   if (cstring_equalLit (s, "export"))
803     {
804       return FLG_EXPORTANY;
805     }
806
807   if (cstring_equalLit (s, "macrospec"))
808     {
809       return FLG_MACRODECL;
810     }
811   
812   if (cstring_equalLit (s, "ansireservedlocal"))
813     {
814       return FLG_ANSIRESERVEDLOCAL;
815     }
816
817   if (cstring_equalLit (s, "warnposix"))
818     {
819       return FLG_WARNPOSIX;
820     }
821
822   if (cstring_equalLit (s, "defuse"))
823     {
824       return FLG_USEDEF;
825     }
826
827   if (cstring_equalLit (s, "macroundef"))
828     {
829       return FLG_MACROUNDEF;
830     }
831
832   if (cstring_equalLit (s, "showcol"))
833     {
834       return FLG_SHOWCOL;
835     }
836
837   if (cstring_equalLit (s, "intbool"))
838     {
839       return FLG_BOOLINT;
840     }
841
842   if (cstring_equalLit (s, "intchar"))
843     {
844       return FLG_CHARINT;
845     }
846
847   if (cstring_equalLit (s, "intenum"))
848     {
849       return FLG_ENUMINT;
850     }
851
852   /*
853   ** For our European friends...
854   */
855
856   if (cstring_equalLit (s, "isolib"))
857     {
858       return FLG_ANSILIB;
859     }
860
861   if (cstring_equalLit (s, "isostrictlib"))
862     {
863       return FLG_STRICTLIB;
864     }
865
866   if (cstring_equalLit (s, "ansistrictlib"))
867     {
868       return FLG_STRICTLIB;
869     }
870
871   if (cstring_equalLit (s, "skipisoheaders"))
872     {
873       return FLG_SKIPANSIHEADERS;
874     }
875
876   if (cstring_equalLit (s, "isoreserved"))
877     {
878       return FLG_ANSIRESERVED;
879     }
880
881   if (cstring_equalLit (s, "isoreservedinternal"))
882     {
883       return FLG_ANSIRESERVEDLOCAL;
884     }
885
886   if (cstring_equalLit (s, "isolimits"))
887     {
888       return FLG_ANSILIMITS;
889     }
890
891   /*
892   ** Obsolete Flags
893   */
894   
895   if (cstring_equalLit (s, "accessunspec"))
896     {
897       llerror_flagWarning 
898         (cstring_makeLiteral
899          ("accessunspec flag is not supported by LCLint version 2.0 or "
900           "later.  It has been replaced by accessmodule, accessfile and "
901           "accessfunction to provide more precise control of accessibility "
902           "of representations.  For more information, "
903           "see lclint -help accessmodule"));
904       
905       return SKIP_FLAG;
906     }
907
908   if (cstring_equalLit (s, "staticmods"))
909     {
910       llerror_flagWarning 
911         (cstring_makeLiteral
912          ("staticmods flag is obsolete.  You probably "
913           "want impcheckmodstatics.  For more information, "
914           "see lclint -help impcheckmodstatics"));
915       
916       return SKIP_FLAG;
917     }
918
919   if (cstring_equalLit (s, "bool"))
920     {
921       llerror_flagWarning
922         (cstring_makeLiteral ("bool flag is obsolete.  It never really "
923                               "made sense in the first place."));
924       
925       return SKIP_FLAG;
926     }
927   
928   if (cstring_equalLit (s, "ansi"))
929     {
930       llerror_flagWarning
931         (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
932                               "want noparams and/or oldstyle."));
933       
934       return SKIP_FLAG;
935     }
936     
937   if (cstring_equalLit (s, "stdio"))
938     {
939       llerror_flagWarning 
940         (cstring_makeLiteral
941          ("stdio flag is obsolete.  You may "
942           "want strictlib or one of the gloabls "
943           "checking flags.  For more information, "
944           "see lclint -help strictlib or lclint -help flags globals"));
945       
946       return SKIP_FLAG;
947     }
948
949   return INVALID_FLAG;
950 }
951
952 void setValueFlag (flagcode opt, cstring arg)
953 {
954   switch (opt)
955     {
956     case FLG_EXPECT:
957     case FLG_LCLEXPECT:
958     case FLG_LIMIT:  
959     case FLG_LINELEN:
960     case FLG_INDENTSPACES:
961     case FLG_BUGSLIMIT:
962     case FLG_EXTERNALNAMELEN:
963     case FLG_INTERNALNAMELEN:
964     case FLG_CONTROLNESTDEPTH:
965     case FLG_STRINGLITERALLEN:
966     case FLG_NUMSTRUCTFIELDS:
967     case FLG_NUMENUMMEMBERS:
968     case FLG_INCLUDENEST:
969       {
970         int val = cstring_toPosInt (arg);
971
972         if (val < 0)
973           {
974             llerror 
975               (FLG_BADFLAG,
976                message 
977                ("Flag %s must be followed by a positive number number.  "
978                 "Followed by %s",
979                 flagcode_unparse (opt), arg));
980           }
981         else
982           {
983             context_setValueAndFlag (opt, val);
984           }
985       }
986       break;
987     case FLG_COMMENTCHAR:
988       {
989         if (cstring_length (arg) != 1)
990           {
991             llfatalerrorLoc
992               (message
993                ("Flag %s should be followed by a single character.  Followed by %s",
994                 flagcode_unparse (opt), arg));
995           }
996         else
997           {
998             context_setCommentMarkerChar (cstring_firstChar (arg));
999           }
1000       }
1001       break;
1002     BADDEFAULT;
1003     }
1004 }
1005
1006 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1007 {
1008   switch (opt)
1009     {
1010     case FLG_TMPDIR:
1011       {
1012         if (cstring_lastChar (arg) == CONNECTCHAR)
1013           {
1014             context_setString (opt, arg);
1015           }
1016         else
1017           {
1018             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1019           }
1020         break;
1021       }
1022     default:
1023       {
1024         context_setString (opt, arg);
1025         break;
1026       }
1027     }
1028 }
1029
1030 cstring
1031 describeModes ()
1032 {
1033   cstring s = cstring_makeLiteral ("Flag                    ");
1034   cstringSList sflags = sortedFlags ();
1035
1036   allModes (modename)
1037     {
1038       s = message ("%q%9s", s, cstring_fromChars (modename));
1039     } end_allModes;
1040   
1041   s = message ("%q\n", s);
1042
1043   cstringSList_elements (sflags, flagname)
1044     {
1045       flagcode code = identifyFlag (flagname);
1046       fflag currentflag = flags[code];
1047       
1048       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1049         {
1050           s = message ("%q\n%27s", s, 
1051                        cstring_fromChars (currentflag.flag));
1052           
1053           allModes (modename)
1054             {
1055               context_setMode (cstring_fromChars (modename));
1056               
1057               if (context_getFlag (code))
1058                 {
1059                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1060                 }
1061               else
1062                 {
1063                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1064                 }
1065
1066               context_resetModeFlags ();
1067             } end_allModes;
1068         }
1069     } end_cstringSList_elements;
1070   
1071   cstringSList_free (sflags);
1072
1073   s = cstring_appendChar (s, '\n');
1074
1075   return (s);
1076 }
1077
1078 # if 0
1079 static /*@unused@*/ cstring
1080 listModes (void)
1081 {
1082   cstring s = cstring_makeLiteral ("\t");
1083   int i = 0;
1084
1085   allModes (modename)
1086     {
1087       if (i != 0 && (i % 4 == 0))
1088         {
1089           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1090         }
1091       else
1092         {
1093           s = message ("%q%15s", s, cstring_fromChars (modename));
1094         }
1095       i++;
1096     } end_allModes;
1097
1098   return s;
1099 }
1100 # endif
1101
1102 bool
1103 isMode (cstring s)
1104 {
1105   allModes (modename)
1106     {
1107       if (mstring_isDefined (modename))
1108         {
1109           if (cstring_equalLit (s, modename))
1110             {
1111               return TRUE;
1112             }
1113         }
1114      } end_allModes;
1115
1116   return FALSE;
1117 }
1118
1119 extern bool flagcode_hasArgument (flagcode f)
1120 {
1121   return (flags[f].argtype != ARG_NONE);
1122 }
1123
1124 extern bool flagcode_hasValue (flagcode f)
1125 {
1126   return (flags[f].argtype == ARG_VALUE);
1127 }
1128
1129 extern bool flagcode_hasString (flagcode f)
1130 {
1131   return (flags[f].argtype == ARG_STRING);
1132 }
1133
1134 extern int flagcode_valueIndex (flagcode f)
1135 {
1136   /*@unchecked@*/ static bool initialized = FALSE;
1137   int i;
1138   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1139   
1140   if (!initialized)
1141     {
1142       int nv = 0;
1143
1144       allFlagCodes (code)
1145         {
1146           if (flagcode_hasValue (code))
1147             {
1148               llassert (nv < NUMVALUEFLAGS);
1149               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1150               valueFlags[nv] = code;
1151               nv++;
1152             }
1153         } end_allFlagCodes;
1154
1155       llassertprint (nv == NUMVALUEFLAGS,
1156                      ("Number of value flags: %d (expected %d)",
1157                       nv, (int) NUMVALUEFLAGS));
1158       initialized = TRUE;
1159     }
1160
1161   for (i = 0; i < NUMVALUEFLAGS; i++)
1162     {
1163       /* static valueFlags must be defined */
1164       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1165         {
1166           return i;
1167         }
1168     }
1169
1170   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1171   exit (EXIT_FAILURE);
1172   /* Cannot do this...might call recursively...
1173   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1174   BADEXIT;
1175   */
1176 }
1177
1178 extern int flagcode_stringIndex (flagcode f)
1179 {
1180   /*@unchecked@*/ static bool initialized = FALSE;
1181   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1182   int i;
1183
1184
1185   if (!initialized)
1186     {
1187       int nv = 0;
1188
1189       allFlagCodes (code)
1190         {
1191           if (flagcode_hasString (code))
1192             {
1193               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1194               stringFlags[nv] = code;
1195               nv++;
1196             }
1197         } end_allFlagCodes;
1198
1199       llassertprint (nv == NUMSTRINGFLAGS,
1200                      ("number of string flags: %d (expected %d)",
1201                       nv, NUMSTRINGFLAGS));
1202       initialized = TRUE;
1203     }
1204
1205   for (i = 0; i < NUMSTRINGFLAGS; i++)
1206     {
1207       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1208         {
1209           return i;
1210         }
1211     }
1212
1213   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1214   BADEXIT;
1215 }
1216
1217 bool flagcode_isNamePrefixFlag (flagcode f)
1218 {
1219   switch (f)
1220     {
1221     case FLG_MACROVARPREFIX:
1222     case FLG_TAGPREFIX:
1223     case FLG_ENUMPREFIX:
1224     case FLG_FILESTATICPREFIX:
1225     case FLG_GLOBPREFIX:
1226     case FLG_TYPEPREFIX:
1227     case FLG_EXTERNALPREFIX:
1228     case FLG_LOCALPREFIX:
1229     case FLG_UNCHECKEDMACROPREFIX:
1230     case FLG_CONSTPREFIX:
1231     case FLG_ITERPREFIX:
1232     case FLG_DECLPARAMPREFIX:
1233       return TRUE;
1234     default:
1235       return FALSE;
1236     }
1237 }
1238         
This page took 0.208641 seconds and 3 git commands to generate.