]> andersk Git - splint.git/blob - src/flags.c
Renaming - LCLint => Splint
[splint.git] / src / flags.c
1 /*
2 ** Splint - 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://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 # 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 no longer supported.  It has been replaced by accessmodule, accessfile and "
900           "accessfunction to provide more precise control of accessibility "
901           "of representations.  For more information, "
902           "see lclint -help accessmodule"));
903       
904       return SKIP_FLAG;
905     }
906
907   if (cstring_equalLit (s, "staticmods"))
908     {
909       llerror_flagWarning 
910         (cstring_makeLiteral
911          ("staticmods flag is obsolete.  You probably "
912           "want impcheckmodstatics.  For more information, "
913           "see lclint -help impcheckmodstatics"));
914       
915       return SKIP_FLAG;
916     }
917
918   if (cstring_equalLit (s, "bool"))
919     {
920       llerror_flagWarning
921         (cstring_makeLiteral ("bool flag is obsolete.  It never really "
922                               "made sense in the first place."));
923       
924       return SKIP_FLAG;
925     }
926   
927   if (cstring_equalLit (s, "ansi"))
928     {
929       llerror_flagWarning
930         (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
931                               "want noparams and/or oldstyle."));
932       
933       return SKIP_FLAG;
934     }
935     
936   if (cstring_equalLit (s, "stdio"))
937     {
938       llerror_flagWarning 
939         (cstring_makeLiteral
940          ("stdio flag is obsolete.  You may "
941           "want strictlib or one of the gloabls "
942           "checking flags.  For more information, "
943           "see lclint -help strictlib or lclint -help flags globals"));
944       
945       return SKIP_FLAG;
946     }
947
948   return INVALID_FLAG;
949 }
950
951 void setValueFlag (flagcode opt, cstring arg)
952 {
953   switch (opt)
954     {
955     case FLG_EXPECT:
956     case FLG_LCLEXPECT:
957     case FLG_LIMIT:  
958     case FLG_LINELEN:
959     case FLG_INDENTSPACES:
960     case FLG_BUGSLIMIT:
961     case FLG_EXTERNALNAMELEN:
962     case FLG_INTERNALNAMELEN:
963     case FLG_CONTROLNESTDEPTH:
964     case FLG_STRINGLITERALLEN:
965     case FLG_NUMSTRUCTFIELDS:
966     case FLG_NUMENUMMEMBERS:
967     case FLG_INCLUDENEST:
968       {
969         int val = cstring_toPosInt (arg);
970
971         if (val < 0)
972           {
973             llerror 
974               (FLG_BADFLAG,
975                message 
976                ("Flag %s must be followed by a positive number number.  "
977                 "Followed by %s",
978                 flagcode_unparse (opt), arg));
979           }
980         else
981           {
982             context_setValueAndFlag (opt, val);
983           }
984       }
985       break;
986     case FLG_COMMENTCHAR:
987       {
988         if (cstring_length (arg) != 1)
989           {
990             llfatalerrorLoc
991               (message
992                ("Flag %s should be followed by a single character.  Followed by %s",
993                 flagcode_unparse (opt), arg));
994           }
995         else
996           {
997             context_setCommentMarkerChar (cstring_firstChar (arg));
998           }
999       }
1000       break;
1001     BADDEFAULT;
1002     }
1003 }
1004
1005 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1006 {
1007   switch (opt)
1008     {
1009     case FLG_TMPDIR:
1010       {
1011         if (cstring_lastChar (arg) == CONNECTCHAR)
1012           {
1013             context_setString (opt, arg);
1014           }
1015         else
1016           {
1017             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1018           }
1019         break;
1020       }
1021     default:
1022       {
1023         context_setString (opt, arg);
1024         break;
1025       }
1026     }
1027 }
1028
1029 cstring
1030 describeModes ()
1031 {
1032   cstring s = cstring_makeLiteral ("Flag                    ");
1033   cstringSList sflags = sortedFlags ();
1034
1035   allModes (modename)
1036     {
1037       s = message ("%q%9s", s, cstring_fromChars (modename));
1038     } end_allModes;
1039   
1040   s = message ("%q\n", s);
1041
1042   cstringSList_elements (sflags, flagname)
1043     {
1044       flagcode code = identifyFlag (flagname);
1045       fflag currentflag = flags[code];
1046       
1047       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1048         {
1049           s = message ("%q\n%27s", s, 
1050                        cstring_fromChars (currentflag.flag));
1051           
1052           allModes (modename)
1053             {
1054               context_setMode (cstring_fromChars (modename));
1055               
1056               if (context_getFlag (code))
1057                 {
1058                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1059                 }
1060               else
1061                 {
1062                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1063                 }
1064
1065               context_resetModeFlags ();
1066             } end_allModes;
1067         }
1068     } end_cstringSList_elements;
1069   
1070   cstringSList_free (sflags);
1071
1072   s = cstring_appendChar (s, '\n');
1073
1074   return (s);
1075 }
1076
1077 # if 0
1078 static /*@unused@*/ cstring
1079 listModes (void)
1080 {
1081   cstring s = cstring_makeLiteral ("\t");
1082   int i = 0;
1083
1084   allModes (modename)
1085     {
1086       if (i != 0 && (i % 4 == 0))
1087         {
1088           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1089         }
1090       else
1091         {
1092           s = message ("%q%15s", s, cstring_fromChars (modename));
1093         }
1094       i++;
1095     } end_allModes;
1096
1097   return s;
1098 }
1099 # endif
1100
1101 bool
1102 isMode (cstring s)
1103 {
1104   allModes (modename)
1105     {
1106       if (mstring_isDefined (modename))
1107         {
1108           if (cstring_equalLit (s, modename))
1109             {
1110               return TRUE;
1111             }
1112         }
1113      } end_allModes;
1114
1115   return FALSE;
1116 }
1117
1118 extern bool flagcode_hasArgument (flagcode f)
1119 {
1120   return (flags[f].argtype != ARG_NONE);
1121 }
1122
1123 extern bool flagcode_hasValue (flagcode f)
1124 {
1125   return (flags[f].argtype == ARG_VALUE);
1126 }
1127
1128 extern bool flagcode_hasString (flagcode f)
1129 {
1130   return (flags[f].argtype == ARG_STRING);
1131 }
1132
1133 extern int flagcode_valueIndex (flagcode f)
1134 {
1135   /*@unchecked@*/ static bool initialized = FALSE;
1136   int i;
1137   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1138   
1139   if (!initialized)
1140     {
1141       int nv = 0;
1142
1143       allFlagCodes (code)
1144         {
1145           if (flagcode_hasValue (code))
1146             {
1147               llassert (nv < NUMVALUEFLAGS);
1148               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1149               valueFlags[nv] = code;
1150               nv++;
1151             }
1152         } end_allFlagCodes;
1153
1154       llassertprint (nv == NUMVALUEFLAGS,
1155                      ("Number of value flags: %d (expected %d)",
1156                       nv, (int) NUMVALUEFLAGS));
1157       initialized = TRUE;
1158     }
1159
1160   for (i = 0; i < NUMVALUEFLAGS; i++)
1161     {
1162       /* static valueFlags must be defined */
1163       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1164         {
1165           return i;
1166         }
1167     }
1168
1169   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1170   exit (EXIT_FAILURE);
1171   /* Cannot do this...might call recursively...
1172   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1173   BADEXIT;
1174   */
1175 }
1176
1177 extern int flagcode_stringIndex (flagcode f)
1178 {
1179   /*@unchecked@*/ static bool initialized = FALSE;
1180   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1181   int i;
1182
1183
1184   if (!initialized)
1185     {
1186       int nv = 0;
1187
1188       allFlagCodes (code)
1189         {
1190           if (flagcode_hasString (code))
1191             {
1192               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1193               stringFlags[nv] = code;
1194               nv++;
1195             }
1196         } end_allFlagCodes;
1197
1198       llassertprint (nv == NUMSTRINGFLAGS,
1199                      ("number of string flags: %d (expected %d)",
1200                       nv, NUMSTRINGFLAGS));
1201       initialized = TRUE;
1202     }
1203
1204   for (i = 0; i < NUMSTRINGFLAGS; i++)
1205     {
1206       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1207         {
1208           return i;
1209         }
1210     }
1211
1212   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1213   BADEXIT;
1214 }
1215
1216 bool flagcode_isNamePrefixFlag (flagcode f)
1217 {
1218   switch (f)
1219     {
1220     case FLG_MACROVARPREFIX:
1221     case FLG_TAGPREFIX:
1222     case FLG_ENUMPREFIX:
1223     case FLG_FILESTATICPREFIX:
1224     case FLG_GLOBPREFIX:
1225     case FLG_TYPEPREFIX:
1226     case FLG_EXTERNALPREFIX:
1227     case FLG_LOCALPREFIX:
1228     case FLG_UNCHECKEDMACROPREFIX:
1229     case FLG_CONSTPREFIX:
1230     case FLG_ITERPREFIX:
1231     case FLG_DECLPARAMPREFIX:
1232       return TRUE;
1233     default:
1234       return FALSE;
1235     }
1236 }
1237         
This page took 0.433743 seconds and 5 git commands to generate.