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