]> andersk Git - splint.git/blob - src/flags.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[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   return cstring_fromChars (flags[code].flag);
641 }
642
643 /*
644 ** Transforms a flag into its cannonical form.
645 **
646 ** The following transformations are made:
647 **
648 **    function      -> fcn
649 **    variable      -> var
650 **    constant      -> const
651 **    iterator      -> iter
652 **    parameter     -> param
653 **    unrecognized  -> unrecog
654 **    qualifier     -> qual         
655 **    declaration   -> decl
656 **    globalias     -> (no change)
657 **    global        -> glob
658 **    modifies      -> mods
659 **    modify        -> mod
660 **    pointer       -> ptr
661 **    implies       -> imp
662 **    implicit      -> imp
663 **    implied       -> imp
664 **    unconstrained -> unspec       
665 **    unconst       -> unspec
666 **    memory        -> mem
667 **    length        -> len
668 */
669
670 static void
671 canonicalizeFlag (cstring s)
672 {
673   int i = 0;
674   static bn_mstring transform[] = 
675     { 
676       "function", "fcn",
677       "variable", "var",
678       "constant", "const",
679       "iterator", "iter",
680       "parameter", "param",
681       "unrecognized", "unrecog",
682       "qualifier", "qual",
683       "declaration", "decl",
684       "globals", "globs", 
685       "modifies", "mods", 
686       "modify", "mod",
687       "pointer", "ptr",
688       "implies", "imp",
689       "implicit", "imp",
690       "implied", "imp",
691       "unconstrained", "uncon",
692       "unconst", "uncon",
693       "memory", "mem",
694       "length", "len",
695       "return", "ret",
696       "system", "sys",
697       NULL
698       } ;
699   char *current;
700
701   while ((current = transform[i]) != NULL)
702     {
703       if (cstring_containsLit (s, current))
704         {
705           cstring_replaceLit (s, current, transform[i+1]);
706         }
707       i += 2;
708     }
709
710   /* remove whitespace, -'s, and _'s */
711   cstring_stripChars (s, " -_");
712 }
713
714 flagcode
715 identifyFlag (cstring s)
716 {
717   if (cstring_length (s) == 0) {
718     /* evs 2000-06-25: A malformed flag. */
719     return INVALID_FLAG;
720   }
721
722   if (cstring_firstChar (s) == 'I')
723     {
724       return FLG_INCLUDEPATH; /* no space after -I */
725     }
726
727   if (cstring_firstChar (s) == 'S') 
728     {
729       return FLG_SPECPATH;    /* no space after -S */
730     }
731
732   if (cstring_firstChar (s) == 'D') 
733     {
734       return FLG_DEFINE;      /* no space after -D */
735     }
736
737   if (cstring_firstChar (s) == 'U') 
738     {
739       return FLG_UNDEFINE;    /* no space after -D */
740     }
741
742   canonicalizeFlag (s);
743
744   allFlags (f)
745     {
746       if (cstring_equal (cstring_fromChars (f.flag), s))
747         {
748           return (f.code);
749         }
750     } end_allFlags;
751
752   /*
753   ** Synonyms
754   */
755
756   if (cstring_equalLit (s, "pred"))
757     {
758       return FLG_PREDBOOL;
759     }
760
761   if (cstring_equalLit (s, "modobserverstrict"))
762     {
763       return FLG_MODOBSERVERUNCON;
764     }
765
766   if (cstring_equalLit (s, "czechnames"))
767     {
768       return FLG_CZECH;
769     }
770
771   if (cstring_equalLit (s, "slovaknames"))
772     {
773       return FLG_SLOVAK;
774     }
775
776   if (cstring_equalLit (s, "czechoslovaknames"))
777     {
778       return FLG_CZECHOSLOVAK;
779     }
780
781   if (cstring_equalLit (s, "globunspec")
782            || cstring_equalLit (s, "globuncon"))
783     {
784       return FLG_GLOBUNSPEC;
785     }
786
787   if (cstring_equalLit (s, "modglobsunspec")
788            || cstring_equalLit (s, "modglobsuncon")
789            || cstring_equalLit (s, "modglobsnomods"))
790     {
791       return FLG_MODGLOBSUNSPEC;
792     }
793
794   if (cstring_equalLit (s, "export"))
795     {
796       return FLG_EXPORTANY;
797     }
798
799   if (cstring_equalLit (s, "macrospec"))
800     {
801       return FLG_MACRODECL;
802     }
803   
804   if (cstring_equalLit (s, "ansireservedlocal"))
805     {
806       return FLG_ANSIRESERVEDLOCAL;
807     }
808
809   if (cstring_equalLit (s, "warnposix"))
810     {
811       return FLG_WARNPOSIX;
812     }
813
814   if (cstring_equalLit (s, "defuse"))
815     {
816       return FLG_USEDEF;
817     }
818
819   if (cstring_equalLit (s, "macroundef"))
820     {
821       return FLG_MACROUNDEF;
822     }
823
824   if (cstring_equalLit (s, "showcol"))
825     {
826       return FLG_SHOWCOL;
827     }
828
829   if (cstring_equalLit (s, "intbool"))
830     {
831       return FLG_BOOLINT;
832     }
833
834   if (cstring_equalLit (s, "intchar"))
835     {
836       return FLG_CHARINT;
837     }
838
839   if (cstring_equalLit (s, "intenum"))
840     {
841       return FLG_ENUMINT;
842     }
843
844   /*
845   ** For our European friends...
846   */
847
848   if (cstring_equalLit (s, "isolib"))
849     {
850       return FLG_ANSILIB;
851     }
852
853   if (cstring_equalLit (s, "isostrictlib"))
854     {
855       return FLG_STRICTLIB;
856     }
857
858   if (cstring_equalLit (s, "ansistrictlib"))
859     {
860       return FLG_STRICTLIB;
861     }
862
863   if (cstring_equalLit (s, "skipisoheaders"))
864     {
865       return FLG_SKIPANSIHEADERS;
866     }
867
868   if (cstring_equalLit (s, "isoreserved"))
869     {
870       return FLG_ANSIRESERVED;
871     }
872
873   if (cstring_equalLit (s, "isoreservedinternal"))
874     {
875       return FLG_ANSIRESERVEDLOCAL;
876     }
877
878   if (cstring_equalLit (s, "isolimits"))
879     {
880       return FLG_ANSILIMITS;
881     }
882
883   /*
884   ** Obsolete Flags
885   */
886   
887   if (cstring_equalLit (s, "accessunspec"))
888     {
889       flagWarning 
890         (cstring_makeLiteralTemp
891          ("accessunspec flag is not supported by LCLint version 2.0 or "
892           "later.  It has been replaced by accessmodule, accessfile and "
893           "accessfunction to provide more precise control of accessibility "
894           "of representations.  For more information, "
895           "see lclint -help accessmodule"));
896       
897       return SKIP_FLAG;
898     }
899
900   if (cstring_equalLit (s, "staticmods"))
901     {
902       flagWarning 
903         (cstring_makeLiteralTemp
904          ("staticmods flag is obsolete.  You probably "
905           "want impcheckmodstatics.  For more information, "
906           "see lclint -help impcheckmodstatics"));
907       
908       return SKIP_FLAG;
909     }
910
911   if (cstring_equalLit (s, "bool"))
912     {
913       flagWarning
914         (cstring_makeLiteralTemp ("bool flag is obsolete.  It never really "
915                                   "made sense in the first place."));
916       
917       return SKIP_FLAG;
918     }
919   
920   if (cstring_equalLit (s, "ansi"))
921     {
922       flagWarning
923         (cstring_makeLiteralTemp ("ansi flag is obsolete.  You probably "
924                                   "want noparams and/or oldstyle."));
925       
926       return SKIP_FLAG;
927     }
928     
929   if (cstring_equalLit (s, "stdio"))
930     {
931       flagWarning 
932         (cstring_makeLiteralTemp
933          ("stdio flag is obsolete.  You may "
934           "want strictlib or one of the gloabls "
935           "checking flags.  For more information, "
936           "see lclint -help strictlib or lclint -help flags globals"));
937       
938       return SKIP_FLAG;
939     }
940
941   return INVALID_FLAG;
942 }
943
944 void setValueFlag (flagcode opt, cstring arg)
945 {
946   switch (opt)
947     {
948     case FLG_EXPECT:
949     case FLG_LCLEXPECT:
950     case FLG_LIMIT:  
951     case FLG_LINELEN:
952     case FLG_INDENTSPACES:
953     case FLG_BUGSLIMIT:
954     case FLG_EXTERNALNAMELEN:
955     case FLG_INTERNALNAMELEN:
956     case FLG_CONTROLNESTDEPTH:
957     case FLG_STRINGLITERALLEN:
958     case FLG_NUMSTRUCTFIELDS:
959     case FLG_NUMENUMMEMBERS:
960     case FLG_INCLUDENEST:
961       {
962         int val = cstring_toPosInt (arg);
963
964         if (val < 0)
965           {
966             llerror 
967               (FLG_BADFLAG,
968                message 
969                ("Flag %s must be followed by a positive number number.  "
970                 "Followed by %s",
971                 flagcode_unparse (opt), arg));
972           }
973         else
974           {
975             context_setValueAndFlag (opt, val);
976           }
977       }
978       break;
979     case FLG_COMMENTCHAR:
980       {
981         if (cstring_length (arg) != 1)
982           {
983             llfatalerrorLoc
984               (message
985                ("Flag %s should be followed by a single character.  Followed by %s",
986                 flagcode_unparse (opt), arg));
987           }
988         else
989           {
990             context_setCommentMarkerChar (cstring_firstChar (arg));
991           }
992       }
993       break;
994     BADDEFAULT;
995     }
996 }
997
998 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
999 {
1000   switch (opt)
1001     {
1002     case FLG_TMPDIR:
1003       {
1004         if (cstring_lastChar (arg) == CONNECTCHAR)
1005           {
1006             context_setString (opt, arg);
1007           }
1008         else
1009           {
1010             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1011           }
1012         break;
1013       }
1014     default:
1015       {
1016         context_setString (opt, arg);
1017         break;
1018       }
1019     }
1020 }
1021
1022 cstring
1023 describeModes ()
1024 {
1025   cstring s = cstring_makeLiteral ("Flag                    ");
1026   cstringSList sflags = sortedFlags ();
1027
1028   allModes (modename)
1029     {
1030       s = message ("%q%9s", s, cstring_fromChars (modename));
1031     } end_allModes;
1032   
1033   s = message ("%q\n", s);
1034
1035   cstringSList_elements (sflags, flagname)
1036     {
1037       flagcode code = identifyFlag (flagname);
1038       fflag currentflag = flags[code];
1039       
1040       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1041         {
1042           s = message ("%q\n%27s", s, 
1043                        cstring_fromChars (currentflag.flag));
1044           
1045           allModes (modename)
1046             {
1047               context_setMode (cstring_fromChars (modename));
1048               
1049               if (context_getFlag (code))
1050                 {
1051                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1052                 }
1053               else
1054                 {
1055                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1056                 }
1057
1058               context_resetModeFlags ();
1059             } end_allModes;
1060         }
1061     } end_cstringSList_elements;
1062   
1063   cstringSList_free (sflags);
1064
1065   s = cstring_appendChar (s, '\n');
1066
1067   return (s);
1068 }
1069
1070 static cstring
1071 listModes (void)
1072 {
1073   cstring s = cstring_makeLiteral ("\t");
1074   int i = 0;
1075
1076   allModes (modename)
1077     {
1078       if (i != 0 && (i % 4 == 0))
1079         {
1080           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1081         }
1082       else
1083         {
1084           s = message ("%q%15s", s, cstring_fromChars (modename));
1085         }
1086       i++;
1087     } end_allModes;
1088
1089   return s;
1090 }
1091
1092 bool
1093 isMode (cstring s)
1094 {
1095   allModes (modename)
1096     {
1097       if (mstring_isDefined (modename))
1098         {
1099           if (cstring_equalLit (s, modename))
1100             {
1101               return TRUE;
1102             }
1103         }
1104      } end_allModes;
1105
1106   return FALSE;
1107 }
1108
1109 extern bool flagcode_hasArgument (flagcode f)
1110 {
1111   return (flags[f].argtype != ARG_NONE);
1112 }
1113
1114 extern bool flagcode_hasValue (flagcode f)
1115 {
1116   return (flags[f].argtype == ARG_VALUE);
1117 }
1118
1119 extern bool flagcode_hasString (flagcode f)
1120 {
1121   return (flags[f].argtype == ARG_STRING);
1122 }
1123
1124 extern int flagcode_valueIndex (flagcode f)
1125 {
1126   /*@unchecked@*/ static bool initialized = FALSE;
1127   int i;
1128   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1129   
1130   if (!initialized)
1131     {
1132       int nv = 0;
1133
1134       allFlagCodes (code)
1135         {
1136           if (flagcode_hasValue (code))
1137             {
1138               llassert (nv < NUMVALUEFLAGS);
1139               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1140               valueFlags[nv] = code;
1141               nv++;
1142             }
1143         } end_allFlagCodes;
1144
1145       llassertprint (nv == NUMVALUEFLAGS,
1146                      ("Number of value flags: %d (expected %d)",
1147                       nv, (int) NUMVALUEFLAGS));
1148       initialized = TRUE;
1149     }
1150
1151   for (i = 0; i < NUMVALUEFLAGS; i++)
1152     {
1153       /* static valueFlags must be defined */
1154       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1155         {
1156           return i;
1157         }
1158     }
1159
1160   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1161   exit (EXIT_FAILURE);
1162   /* Cannot do this...might call recursively...
1163   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1164   BADEXIT;
1165   */
1166 }
1167
1168 extern int flagcode_stringIndex (flagcode f)
1169 {
1170   /*@unchecked@*/ static bool initialized = FALSE;
1171   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1172   int i;
1173
1174
1175   if (!initialized)
1176     {
1177       int nv = 0;
1178
1179       allFlagCodes (code)
1180         {
1181           if (flagcode_hasString (code))
1182             {
1183               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1184               stringFlags[nv] = code;
1185               nv++;
1186             }
1187         } end_allFlagCodes;
1188
1189       llassertprint (nv == NUMSTRINGFLAGS,
1190                      ("number of string flags: %d (expected %d)",
1191                       nv, NUMSTRINGFLAGS));
1192       initialized = TRUE;
1193     }
1194
1195   for (i = 0; i < NUMSTRINGFLAGS; i++)
1196     {
1197       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1198         {
1199           return i;
1200         }
1201     }
1202
1203   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1204   BADEXIT;
1205 }
1206
1207 bool flagcode_isNamePrefixFlag (flagcode f)
1208 {
1209   switch (f)
1210     {
1211     case FLG_MACROVARPREFIX:
1212     case FLG_TAGPREFIX:
1213     case FLG_ENUMPREFIX:
1214     case FLG_FILESTATICPREFIX:
1215     case FLG_GLOBPREFIX:
1216     case FLG_TYPEPREFIX:
1217     case FLG_EXTERNALPREFIX:
1218     case FLG_LOCALPREFIX:
1219     case FLG_UNCHECKEDMACROPREFIX:
1220     case FLG_CONSTPREFIX:
1221     case FLG_ITERPREFIX:
1222     case FLG_DECLPARAMPREFIX:
1223       return TRUE;
1224     default:
1225       return FALSE;
1226     }
1227 }
1228         
This page took 0.127957 seconds and 5 git commands to generate.