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