]> andersk Git - splint.git/blob - src/flags.c
Initial revision
[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_firstChar (s) == 'I')
710     {
711       return FLG_INCLUDEPATH; /* no space after -I */
712     }
713
714   if (cstring_firstChar (s) == 'S') 
715     {
716       return FLG_SPECPATH;    /* no space after -S */
717     }
718
719   if (cstring_firstChar (s) == 'D') 
720     {
721       return FLG_DEFINE;      /* no space after -D */
722     }
723
724   if (cstring_firstChar (s) == 'U') 
725     {
726       return FLG_UNDEFINE;    /* no space after -D */
727     }
728
729   canonicalizeFlag (s);
730
731   allFlags (f)
732     {
733       if (cstring_equal (cstring_fromChars (f.flag), s))
734         {
735           return (f.code);
736         }
737     } end_allFlags;
738
739   /*
740   ** Synonyms
741   */
742
743   if (cstring_equalLit (s, "pred"))
744     {
745       return FLG_PREDBOOL;
746     }
747
748   if (cstring_equalLit (s, "modobserverstrict"))
749     {
750       return FLG_MODOBSERVERUNCON;
751     }
752
753   if (cstring_equalLit (s, "czechnames"))
754     {
755       return FLG_CZECH;
756     }
757
758   if (cstring_equalLit (s, "slovaknames"))
759     {
760       return FLG_SLOVAK;
761     }
762
763   if (cstring_equalLit (s, "czechoslovaknames"))
764     {
765       return FLG_CZECHOSLOVAK;
766     }
767
768   if (cstring_equalLit (s, "globunspec")
769            || cstring_equalLit (s, "globuncon"))
770     {
771       return FLG_GLOBUNSPEC;
772     }
773
774   if (cstring_equalLit (s, "modglobsunspec")
775            || cstring_equalLit (s, "modglobsuncon")
776            || cstring_equalLit (s, "modglobsnomods"))
777     {
778       return FLG_MODGLOBSUNSPEC;
779     }
780
781   if (cstring_equalLit (s, "export"))
782     {
783       return FLG_EXPORTANY;
784     }
785
786   if (cstring_equalLit (s, "macrospec"))
787     {
788       return FLG_MACRODECL;
789     }
790   
791   if (cstring_equalLit (s, "ansireservedlocal"))
792     {
793       return FLG_ANSIRESERVEDLOCAL;
794     }
795
796   if (cstring_equalLit (s, "warnposix"))
797     {
798       return FLG_WARNPOSIX;
799     }
800
801   if (cstring_equalLit (s, "defuse"))
802     {
803       return FLG_USEDEF;
804     }
805
806   if (cstring_equalLit (s, "macroundef"))
807     {
808       return FLG_MACROUNDEF;
809     }
810
811   if (cstring_equalLit (s, "showcol"))
812     {
813       return FLG_SHOWCOL;
814     }
815
816   if (cstring_equalLit (s, "intbool"))
817     {
818       return FLG_BOOLINT;
819     }
820
821   if (cstring_equalLit (s, "intchar"))
822     {
823       return FLG_CHARINT;
824     }
825
826   if (cstring_equalLit (s, "intenum"))
827     {
828       return FLG_ENUMINT;
829     }
830
831   /*
832   ** For our European friends...
833   */
834
835   if (cstring_equalLit (s, "isolib"))
836     {
837       return FLG_ANSILIB;
838     }
839
840   if (cstring_equalLit (s, "isostrictlib"))
841     {
842       return FLG_STRICTLIB;
843     }
844
845   if (cstring_equalLit (s, "ansistrictlib"))
846     {
847       return FLG_STRICTLIB;
848     }
849
850   if (cstring_equalLit (s, "skipisoheaders"))
851     {
852       return FLG_SKIPANSIHEADERS;
853     }
854
855   if (cstring_equalLit (s, "isoreserved"))
856     {
857       return FLG_ANSIRESERVED;
858     }
859
860   if (cstring_equalLit (s, "isoreservedinternal"))
861     {
862       return FLG_ANSIRESERVEDLOCAL;
863     }
864
865   if (cstring_equalLit (s, "isolimits"))
866     {
867       return FLG_ANSILIMITS;
868     }
869
870   /*
871   ** Obsolete Flags
872   */
873   
874   if (cstring_equalLit (s, "accessunspec"))
875     {
876       flagWarning 
877         (cstring_makeLiteralTemp
878          ("accessunspec flag is not supported by LCLint version 2.0 or "
879           "later.  It has been replaced by accessmodule, accessfile and "
880           "accessfunction to provide more precise control of accessibility "
881           "of representations.  For more information, "
882           "see lclint -help accessmodule"));
883       
884       return SKIP_FLAG;
885     }
886
887   if (cstring_equalLit (s, "staticmods"))
888     {
889       flagWarning 
890         (cstring_makeLiteralTemp
891          ("staticmods flag is obsolete.  You probably "
892           "want impcheckmodstatics.  For more information, "
893           "see lclint -help impcheckmodstatics"));
894       
895       return SKIP_FLAG;
896     }
897   
898   if (cstring_equalLit (s, "ansi"))
899     {
900       flagWarning
901         (cstring_makeLiteralTemp ("ansi flag is obsolete.  You probably "
902                                   "want noparams and/or oldstyle."));
903       
904       return SKIP_FLAG;
905     }
906     
907   if (cstring_equalLit (s, "stdio"))
908     {
909       flagWarning 
910         (cstring_makeLiteralTemp
911          ("stdio flag is obsolete.  You may "
912           "want strictlib or one of the gloabls "
913           "checking flags.  For more information, "
914           "see lclint -help strictlib or lclint -help flags globals"));
915       
916       return SKIP_FLAG;
917     }
918
919   return INVALID_FLAG;
920 }
921
922 void setValueFlag (flagcode opt, cstring arg)
923 {
924   switch (opt)
925     {
926     case FLG_EXPECT:
927     case FLG_LCLEXPECT:
928     case FLG_LIMIT:  
929     case FLG_LINELEN:
930     case FLG_EXTERNALNAMELEN:
931     case FLG_INTERNALNAMELEN:
932     case FLG_CONTROLNESTDEPTH:
933     case FLG_STRINGLITERALLEN:
934     case FLG_NUMSTRUCTFIELDS:
935     case FLG_NUMENUMMEMBERS:
936     case FLG_INCLUDENEST:
937       {
938         int val = cstring_toPosInt (arg);
939
940         if (val < 0)
941           {
942             llerror 
943               (FLG_BADFLAG,
944                message 
945                ("Flag %s must be followed by a positive number number.  "
946                 "Followed by %s",
947                 flagcode_unparse (opt), arg));
948           }
949         else
950           {
951                     context_setValueAndFlag (opt, val);
952           }
953       }
954       break;
955     case FLG_COMMENTCHAR:
956       {
957         if (cstring_length (arg) != 1)
958           {
959             llfatalerrorLoc
960               (message
961                ("Flag %s should be followed by a single character.  Followed by %s",
962                 flagcode_unparse (opt), arg));
963           }
964         else
965           {
966             context_setCommentMarkerChar (cstring_firstChar (arg));
967           }
968       }
969       break;
970     BADDEFAULT;
971     }
972 }
973
974 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
975 {
976   switch (opt)
977     {
978     case FLG_TMPDIR:
979       {
980         if (cstring_lastChar (arg) == CONNECTCHAR)
981           {
982             context_setString (opt, arg);
983           }
984         else
985           {
986             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
987           }
988         break;
989       }
990     default:
991       {
992         context_setString (opt, arg);
993         break;
994       }
995     }
996 }
997
998 cstring
999 describeModes ()
1000 {
1001   cstring s = cstring_makeLiteral ("Flag                    ");
1002   cstringSList sflags = sortedFlags ();
1003
1004   allModes (modename)
1005     {
1006       s = message ("%q%9s", s, cstring_fromChars (modename));
1007     } end_allModes;
1008   
1009   s = message ("%q\n", s);
1010
1011   cstringSList_elements (sflags, flagname)
1012     {
1013       flagcode code = identifyFlag (flagname);
1014       fflag currentflag = flags[code];
1015       
1016       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1017         {
1018           s = message ("%q\n%27s", s, 
1019                        cstring_fromChars (currentflag.flag));
1020           
1021           allModes (modename)
1022             {
1023               context_setMode (cstring_fromChars (modename));
1024               
1025               if (context_getFlag (code))
1026                 {
1027                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1028                 }
1029               else
1030                 {
1031                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1032                 }
1033
1034               context_resetModeFlags ();
1035             } end_allModes;
1036         }
1037     } end_cstringSList_elements;
1038   
1039   cstringSList_free (sflags);
1040
1041   s = cstring_appendChar (s, '\n');
1042
1043   return (s);
1044 }
1045
1046 static cstring
1047 listModes (void)
1048 {
1049   cstring s = cstring_makeLiteral ("\t");
1050   int i = 0;
1051
1052   allModes (modename)
1053     {
1054       if (i != 0 && (i % 4 == 0))
1055         {
1056           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1057         }
1058       else
1059         {
1060           s = message ("%q%15s", s, cstring_fromChars (modename));
1061         }
1062       i++;
1063     } end_allModes;
1064
1065   return s;
1066 }
1067
1068 bool
1069 isMode (cstring s)
1070 {
1071   allModes (modename)
1072     {
1073       if (mstring_isDefined (modename))
1074         {
1075           if (cstring_equalLit (s, modename))
1076             {
1077               return TRUE;
1078             }
1079         }
1080      } end_allModes;
1081
1082   return FALSE;
1083 }
1084
1085 extern bool flagcode_hasArgument (flagcode f)
1086 {
1087   return (flags[f].argtype != ARG_NONE);
1088 }
1089
1090 extern bool flagcode_hasValue (flagcode f)
1091 {
1092   return (flags[f].argtype == ARG_VALUE);
1093 }
1094
1095 extern bool flagcode_hasString (flagcode f)
1096 {
1097   return (flags[f].argtype == ARG_STRING);
1098 }
1099
1100 extern int flagcode_valueIndex (flagcode f)
1101 {
1102   /*@unchecked@*/ static bool initialized = FALSE;
1103   int i;
1104   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1105
1106   
1107   if (!initialized)
1108     {
1109       int nv = 0;
1110
1111       allFlagCodes (code)
1112         {
1113           if (flagcode_hasValue (code))
1114             {
1115               llassert (nv < NUMVALUEFLAGS);
1116               valueFlags[nv] = code;
1117                       nv++;
1118             }
1119         } end_allFlagCodes;
1120
1121       llassertprint (nv == NUMVALUEFLAGS,
1122                      ("number of value flags: %d (expected %d)",
1123                       nv, NUMVALUEFLAGS));
1124       initialized = TRUE;
1125     }
1126
1127   for (i = 0; i < NUMVALUEFLAGS; i++)
1128     {
1129       /* static valueFlags must be defined */
1130       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1131         {
1132           return i;
1133         }
1134           }
1135
1136   BADEXIT;
1137 }
1138
1139 extern int flagcode_stringIndex (flagcode f)
1140 {
1141   /*@unchecked@*/ static bool initialized = FALSE;
1142   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1143   int i;
1144
1145
1146   if (!initialized)
1147     {
1148       int nv = 0;
1149
1150       allFlagCodes (code)
1151         {
1152           if (flagcode_hasString (code))
1153             {
1154               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1155               stringFlags[nv] = code;
1156               nv++;
1157             }
1158         } end_allFlagCodes;
1159
1160       llassertprint (nv == NUMSTRINGFLAGS,
1161                      ("number of string flags: %d (expected %d)",
1162                       nv, NUMSTRINGFLAGS));
1163       initialized = TRUE;
1164     }
1165
1166   for (i = 0; i < NUMSTRINGFLAGS; i++)
1167     {
1168       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1169         {
1170           return i;
1171         }
1172     }
1173
1174   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1175   BADEXIT;
1176 }
1177
1178 bool flagcode_isNamePrefixFlag (flagcode f)
1179 {
1180   switch (f)
1181     {
1182     case FLG_MACROVARPREFIX:
1183     case FLG_TAGPREFIX:
1184     case FLG_ENUMPREFIX:
1185     case FLG_FILESTATICPREFIX:
1186     case FLG_GLOBPREFIX:
1187     case FLG_TYPEPREFIX:
1188     case FLG_EXTERNALPREFIX:
1189     case FLG_LOCALPREFIX:
1190     case FLG_UNCHECKEDMACROPREFIX:
1191     case FLG_CONSTPREFIX:
1192     case FLG_ITERPREFIX:
1193     case FLG_DECLPARAMPREFIX:
1194       return TRUE;
1195     default:
1196       return FALSE;
1197     }
1198 }
1199         
This page took 0.135608 seconds and 5 git commands to generate.