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