]> andersk Git - splint.git/blob - src/flags.c
Generating flag manual; separated ARG_STRING into filename, path,
[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 [%s]>", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
508                                 context_getString (f.code));
509           }
510         else if (f.argtype == ARG_CHAR)
511           {
512             flagname = message ("%s <%s [%c]>", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
513                                 (char) context_getValue (f.code));
514           }
515         else 
516           {
517             llassert (f.argtype == ARG_NUMBER);
518             flagname = message ("%s <%s [%d]>", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
519                                 context_getValue (f.code));
520           }
521       }
522
523     if (f.isIdem)
524       {
525         flagtype = message("%q<->", flagtype);
526       }
527     else
528       {
529         flagtype = message("%q<+->", flagtype);
530       }
531     
532     if (f.isGlobal)
533       {
534         flagtype = message ("%q<G>", flagtype);
535       }
536
537     if (f.isSpecial)
538       {
539         flagtype = message("%q<S>", flagtype);
540       }
541     
542     if (f.isModeFlag)
543       {
544         flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
545       }
546     else /* its a plain flag */
547       {
548         flagtype = message ("%q<P:%s>", flagtype,
549                             cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
550       }
551
552     llmsg (message ("%s: %s", flagname, flagtype));
553   } end_allFlags ;
554 }
555
556 cstring
557 describeFlagCode (flagcode flag)
558 {
559   cstring ret = cstring_undefined;
560   fflag f;
561   
562   if (flagcode_isInvalid (flag))
563     {
564       return (cstring_makeLiteral ("<invalid>"));
565     }
566
567   context_resetAllFlags ();
568   
569   f = flags[flag];
570   ret = cstring_copy (cstring_fromChars (f.desc));
571   
572   
573   if (f.sub != FK_NONE)
574     {
575       ret = message ("%q\nCategories: %s, %s",
576                      ret, 
577                      categoryName (f.main),
578                      categoryName (f.sub));
579     }
580   else 
581     {
582       if (f.main != FK_NONE)
583         {
584           cstring cname = categoryName (f.main);
585           
586           if (cstring_isDefined (cname))
587             {
588               ret = message ("%q\nCategory: %s",
589                              ret, cname);
590             }
591         }
592     }
593   
594   if (f.isModeFlag)
595     {
596       ret = message ("%q\nMode Settings: %q",
597                      ret, getFlagModeSettings (flag));
598     }
599   else
600     {
601       ret = message ("%q\nDefault Setting: %s",
602                      ret, 
603                      cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
604     }
605   
606   if (f.isGlobal)
607     {
608       ret = message("%q\nSet globally only", ret);
609     }
610   else
611     {
612       ret = message("%q\nSet locally", ret);
613     }
614   
615   switch (f.argtype)
616     {
617     case ARG_NONE:
618     case ARG_SPECIAL:
619       break;
620     case ARG_NUMBER:
621       ret = message("%q\nNumeric Argument.  Default: %d",
622                     ret,
623                     context_getValue (flag));
624       break;
625     case ARG_CHAR:
626       ret = message("%q\nCharacter Argument.  Default: %h",
627                     ret, (char) context_getValue (flag));
628       break;
629     case ARG_STRING:
630     case ARG_FILE:
631     case ARG_PATH:
632     case ARG_DIRECTORY:
633       {
634       if (cstring_isDefined (context_getString (flag)))
635         {
636           ret = message("%q\n%q argument.  Default: %s",
637                         ret,
638                         cstring_capitalize (argcode_unparse (f.argtype)),
639                         context_getString (flag));
640         }
641       else
642         {
643           ret = message("%q\n%s argument.  No default.", 
644                         ret,
645                         cstring_capitalize (argcode_unparse (f.argtype)));
646         }
647       break;
648       }
649     }
650   
651   if (mstring_isDefined (f.hint))
652     {
653       ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
654     }
655   
656   return ret;
657 }
658   
659 static cstring getFlagModeSettings (flagcode flag)
660 {
661   cstring res = cstring_undefined;
662   
663   allModes (mname)
664     {
665       context_setMode (cstring_fromChars (mname));
666       
667       res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
668     } end_allModes;
669
670   return res;
671 }
672
673 cstring
674 describeFlag (cstring flagname)
675 {
676   cstring oflagname = cstring_copy (flagname);
677   flagcode f = flags_identifyFlag (flagname);
678
679   if (flagcode_isSkip (f))
680     {
681       cstring_free (oflagname);
682       return cstring_undefined;
683     }
684   else if (flagcode_isValid (f))
685     {
686       if (cstring_equal (flagname, oflagname))
687         {
688           cstring_free (oflagname);
689           return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
690         }
691       else
692         {
693           return (message ("%q (standardized name: %s)\n\3%q",
694                            oflagname, flagname, describeFlagCode (f)));
695         }
696     }
697   else
698     {
699       if (isMode (flagname))
700         {
701           cstring_free (oflagname);
702
703           return
704             (message ("%s: predefined mode (see Manual for information)",
705                       flagname));
706         }
707       else
708         {
709           return (message ("%q: <invalid flag>", oflagname));
710         }
711     }
712 }
713
714 static cstringSList
715 sortedFlags (void)
716 {
717   cstringSList s = cstringSList_new ();
718
719   allFlags (f)
720     {
721       if (f.desc != NULL)
722         {
723           s = cstringSList_add (s, cstring_fromChars (f.flag));
724         }
725     } end_allFlags;
726
727   cstringSList_alphabetize (s);
728
729   return s;
730 }
731
732 void printAlphaFlags ()
733 {
734   cstringSList fl = sortedFlags ();
735
736   cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25); 
737   cstringSList_free (fl);
738 }
739
740 /*@observer@*/ cstring
741 flagcode_unparse (flagcode code)
742 {
743   if (code == INVALID_FLAG)
744     {
745       return cstring_makeLiteralTemp ("<invalid flag>");
746     }
747
748   return cstring_fromChars (flags[code].flag);
749 }
750
751 /*
752 ** Transforms a flag into its cannonical form.
753 **
754 ** The following transformations are made:
755 **
756 **    function      -> fcn
757 **    variable      -> var
758 **    constant      -> const
759 **    iterator      -> iter
760 **    parameter     -> param
761 **    unrecognized  -> unrecog
762 **    qualifier     -> qual         
763 **    declaration   -> decl
764 **    globalias     -> (no change)
765 **    global        -> glob
766 **    modifies      -> mods
767 **    modify        -> mod
768 **    pointer       -> ptr
769 **    implies       -> imp
770 **    implicit      -> imp
771 **    implied       -> imp
772 **    unconstrained -> unspec       
773 **    unconst       -> unspec
774 **    memory        -> mem
775 **    length        -> len
776 */
777
778 static void
779 canonicalizeFlag (cstring s)
780 {
781   int i = 0;
782   static bn_mstring transform[] = 
783     { 
784       "function", "fcn",
785       "variable", "var",
786       "constant", "const",
787       "iterator", "iter",
788       "parameter", "param",
789       "unrecognized", "unrecog",
790       "qualifier", "qual",
791       "declaration", "decl",
792       "globals", "globs", 
793       "modifies", "mods", 
794       "modify", "mod",
795       "pointer", "ptr",
796       "implies", "imp",
797       "implicit", "imp",
798       "implied", "imp",
799       "unconstrained", "uncon",
800       "unconst", "uncon",
801       "memory", "mem",
802       "length", "len",
803       "return", "ret",
804       "system", "sys",
805       NULL
806       } ;
807   char *current;
808
809   while ((current = transform[i]) != NULL)
810     {
811       if (cstring_containsLit (s, current))
812         {
813           cstring_replaceLit (s, current, transform[i+1]);
814         }
815       i += 2;
816     }
817
818   /* remove whitespace, -'s, and _'s */
819   cstring_stripChars (s, " -_");
820 }
821
822 flagcode
823 flags_identifyFlag (cstring s)
824 {
825   return flags_identifyFlagAux (s, FALSE);
826 }
827
828 flagcode
829 flags_identifyFlagQuiet (cstring s)
830 {
831   return flags_identifyFlagAux (s, TRUE);
832 }
833
834 static flagcode
835 flags_identifyFlagAux (cstring s, bool quiet)
836 {
837   if (cstring_length (s) == 0) {
838     /* evs 2000-06-25: A malformed flag. */
839     return INVALID_FLAG;
840   }
841
842   if (cstring_firstChar (s) == 'I')
843     {
844       return FLG_INCLUDEPATH; /* no space after -I */
845     }
846
847   if (cstring_firstChar (s) == 'S') 
848     {
849       return FLG_SPECPATH;    /* no space after -S */
850     }
851
852   if (cstring_firstChar (s) == 'D') 
853     {
854       return FLG_DEFINE;      /* no space after -D */
855     }
856
857   if (cstring_firstChar (s) == 'U') 
858     {
859       return FLG_UNDEFINE;    /* no space after -D */
860     }
861
862   canonicalizeFlag (s);
863
864   allFlags (f)
865     {
866       if (cstring_equal (cstring_fromChars (f.flag), s))
867         {
868           return (f.code);
869         }
870     } end_allFlags;
871
872   /*
873   ** Synonyms
874   */
875
876   if (cstring_equalLit (s, "pred"))
877     {
878       return FLG_PREDBOOL;
879     }
880
881   if (cstring_equalLit (s, "modobserverstrict"))
882     {
883       return FLG_MODOBSERVERUNCON;
884     }
885
886   if (cstring_equalLit (s, "czechnames"))
887     {
888       return FLG_CZECH;
889     }
890
891   if (cstring_equalLit (s, "slovaknames"))
892     {
893       return FLG_SLOVAK;
894     }
895
896   if (cstring_equalLit (s, "czechoslovaknames"))
897     {
898       return FLG_CZECHOSLOVAK;
899     }
900
901   if (cstring_equalLit (s, "globunspec")
902            || cstring_equalLit (s, "globuncon"))
903     {
904       return FLG_GLOBUNSPEC;
905     }
906
907   if (cstring_equalLit (s, "modglobsunspec")
908            || cstring_equalLit (s, "modglobsuncon")
909            || cstring_equalLit (s, "modglobsnomods"))
910     {
911       return FLG_MODGLOBSUNSPEC;
912     }
913
914   if (cstring_equalLit (s, "export"))
915     {
916       return FLG_EXPORTANY;
917     }
918
919   if (cstring_equalLit (s, "macrospec"))
920     {
921       return FLG_MACRODECL;
922     }
923   
924   if (cstring_equalLit (s, "ansireservedlocal"))
925     {
926       return FLG_ANSIRESERVEDLOCAL;
927     }
928
929   if (cstring_equalLit (s, "warnposix"))
930     {
931       return FLG_WARNPOSIX;
932     }
933
934   if (cstring_equalLit (s, "defuse"))
935     {
936       return FLG_USEDEF;
937     }
938
939   if (cstring_equalLit (s, "macroundef"))
940     {
941       return FLG_MACROUNDEF;
942     }
943
944   if (cstring_equalLit (s, "showcol"))
945     {
946       return FLG_SHOWCOL;
947     }
948
949   if (cstring_equalLit (s, "intbool"))
950     {
951       return FLG_BOOLINT;
952     }
953
954   if (cstring_equalLit (s, "intchar"))
955     {
956       return FLG_CHARINT;
957     }
958
959   if (cstring_equalLit (s, "intenum"))
960     {
961       return FLG_ENUMINT;
962     }
963
964   /*
965   ** Backwards compatibility for our American friends...
966   */
967
968   if (cstring_equalLit (s, "ansilib"))
969     {
970       return FLG_ANSILIB;
971     }
972
973   if (cstring_equalLit (s, "ansistrictlib"))
974     {
975       return FLG_STRICTLIB;
976     }
977
978   if (cstring_equalLit (s, "skipansiheaders"))
979     {
980       return FLG_SKIPANSIHEADERS;
981     }
982
983   if (cstring_equalLit (s, "ansireserved"))
984     {
985       return FLG_ANSIRESERVED;
986     }
987
988   if (cstring_equalLit (s, "ansireservedinternal"))
989     {
990       return FLG_ANSIRESERVEDLOCAL;
991     }
992
993   /*
994   ** Obsolete Flags
995   */
996   
997   if (cstring_equalLit (s, "accessunspec"))
998     {
999       if (!quiet) 
1000         {
1001           llerror_flagWarning 
1002             (cstring_makeLiteral
1003              ("accessunspec flag is no longer supported.  It has been replaced by accessmodule, accessfile and "
1004               "accessfunction to provide more precise control of accessibility "
1005               "of representations.  For more information, "
1006               "see lclint -help accessmodule"));
1007         }
1008       
1009       return SKIP_FLAG;
1010     }
1011   else if (cstring_equalLit (s, "ansilimits"))
1012     {
1013           llerror_flagWarning 
1014             (cstring_makeLiteral
1015              ("ansilimits flag is no longer supported.  It has been replaced by ansi89limits and "
1016               "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1017               "standard or the typically higher limits prescribed by ISO C99."));
1018
1019       return SKIP_FLAG;
1020     }
1021   else if (cstring_equalLit (s, "staticmods"))
1022     {
1023       if (!quiet) 
1024         {
1025           llerror_flagWarning 
1026             (cstring_makeLiteral
1027              ("staticmods flag is obsolete.  You probably "
1028               "want impcheckmodstatics.  For more information, "
1029               "see lclint -help impcheckmodstatics"));
1030         }
1031
1032       return SKIP_FLAG;
1033     }
1034   else if (cstring_equalLit (s, "bool"))
1035     {
1036       if (!quiet) 
1037         {
1038           llerror_flagWarning
1039             (cstring_makeLiteral ("bool flag is obsolete.  It never really "
1040                                   "made sense in the first place."));
1041         }
1042       
1043       return SKIP_FLAG;
1044     }
1045   else if (cstring_equalLit (s, "shiftsigned"))
1046     {
1047       if (!quiet) 
1048         {
1049           llerror_flagWarning
1050             (cstring_makeLiteral ("shiftsigned flag is obsolete.  You probably "
1051                                   "want bitwisesigned, shiftnegative or shiftsize."));
1052         }
1053       
1054       return SKIP_FLAG;
1055     }
1056   else if (cstring_equalLit (s, "ansi"))
1057     {
1058       if (!quiet) 
1059         {
1060           llerror_flagWarning
1061             (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
1062                                   "want noparams and/or oldstyle."));
1063         }
1064       
1065       return SKIP_FLAG;
1066     }
1067   else if (cstring_equalLit (s, "stdio"))
1068     {
1069       if (!quiet) 
1070         {
1071           llerror_flagWarning 
1072             (cstring_makeLiteral
1073              ("stdio flag is obsolete.  You may "
1074               "want strictlib or one of the gloabls "
1075               "checking flags.  For more information, "
1076               "see lclint -help strictlib or lclint -help flags globals"));
1077         }
1078       
1079       return SKIP_FLAG;
1080     }
1081   else
1082     {
1083       return INVALID_FLAG;
1084     }
1085 }
1086
1087 void setValueFlag (flagcode opt, cstring arg)
1088 {
1089   switch (opt)
1090     {
1091     case FLG_EXPECT:
1092     case FLG_LCLEXPECT:
1093     case FLG_LIMIT:  
1094     case FLG_LINELEN:
1095     case FLG_INDENTSPACES:
1096     case FLG_BUGSLIMIT:
1097     case FLG_EXTERNALNAMELEN:
1098     case FLG_INTERNALNAMELEN:
1099     case FLG_CONTROLNESTDEPTH:
1100     case FLG_STRINGLITERALLEN:
1101     case FLG_NUMSTRUCTFIELDS:
1102     case FLG_NUMENUMMEMBERS:
1103     case FLG_INCLUDENEST:
1104       {
1105         int val = cstring_toPosInt (arg);
1106
1107         if (val < 0)
1108           {
1109             llerror 
1110               (FLG_BADFLAG,
1111                message 
1112                ("Flag %s must be followed by a positive number number.  "
1113                 "Followed by %s",
1114                 flagcode_unparse (opt), arg));
1115           }
1116         else
1117           {
1118             context_setValueAndFlag (opt, val);
1119           }
1120       }
1121       break;
1122     case FLG_COMMENTCHAR:
1123       {
1124         if (cstring_length (arg) != 1)
1125           {
1126             llfatalerrorLoc
1127               (message
1128                ("Flag %s should be followed by a single character.  Followed by %s",
1129                 flagcode_unparse (opt), arg));
1130           }
1131         else
1132           {
1133             context_setCommentMarkerChar (cstring_firstChar (arg));
1134           }
1135       }
1136       break;
1137     BADDEFAULT;
1138     }
1139 }
1140
1141 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1142 {
1143   switch (opt)
1144     {
1145     case FLG_TMPDIR:
1146       {
1147         if (cstring_lastChar (arg) == CONNECTCHAR)
1148           {
1149             context_setString (opt, arg);
1150           }
1151         else
1152           {
1153             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1154           }
1155         break;
1156       }
1157     default:
1158       {
1159         context_setString (opt, arg);
1160         break;
1161       }
1162     }
1163 }
1164
1165 cstring
1166 describeModes ()
1167 {
1168   cstring s = cstring_makeLiteral ("Flag                    ");
1169   cstringSList sflags = sortedFlags ();
1170
1171   allModes (modename)
1172     {
1173       s = message ("%q%9s", s, cstring_fromChars (modename));
1174     } end_allModes;
1175   
1176   s = message ("%q\n", s);
1177
1178   cstringSList_elements (sflags, flagname)
1179     {
1180       flagcode code = flags_identifyFlag (flagname);
1181       fflag currentflag = flags[code];
1182       
1183       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1184         {
1185           s = message ("%q\n%27s", s, 
1186                        cstring_fromChars (currentflag.flag));
1187           
1188           allModes (modename)
1189             {
1190               context_setMode (cstring_fromChars (modename));
1191               
1192               if (context_getFlag (code))
1193                 {
1194                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1195                 }
1196               else
1197                 {
1198                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1199                 }
1200
1201               context_resetModeFlags ();
1202             } end_allModes;
1203         }
1204     } end_cstringSList_elements;
1205   
1206   cstringSList_free (sflags);
1207
1208   s = cstring_appendChar (s, '\n');
1209
1210   return (s);
1211 }
1212
1213 # if 0
1214 static /*@unused@*/ cstring
1215 listModes (void)
1216 {
1217   cstring s = cstring_makeLiteral ("\t");
1218   int i = 0;
1219
1220   allModes (modename)
1221     {
1222       if (i != 0 && (i % 4 == 0))
1223         {
1224           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1225         }
1226       else
1227         {
1228           s = message ("%q%15s", s, cstring_fromChars (modename));
1229         }
1230       i++;
1231     } end_allModes;
1232
1233   return s;
1234 }
1235 # endif
1236
1237 bool
1238 isMode (cstring s)
1239 {
1240   allModes (modename)
1241     {
1242       if (mstring_isDefined (modename))
1243         {
1244           if (cstring_equalLit (s, modename))
1245             {
1246               return TRUE;
1247             }
1248         }
1249      } end_allModes;
1250
1251   return FALSE;
1252 }
1253
1254 extern bool flagcode_hasArgument (flagcode f)
1255 {
1256   return (flags[f].argtype != ARG_NONE);
1257 }
1258
1259 extern bool flagcode_hasNumber (flagcode f)
1260 {
1261   return (flags[f].argtype == ARG_NUMBER);
1262 }
1263
1264 extern bool flagcode_hasChar (flagcode f)
1265 {
1266   return (flags[f].argtype == ARG_CHAR);
1267 }
1268
1269 extern bool flagcode_hasString (flagcode f)
1270 {
1271   return (flags[f].argtype == ARG_STRING
1272           || flags[f].argtype == ARG_FILE
1273           || flags[f].argtype == ARG_DIRECTORY
1274           || flags[f].argtype == ARG_PATH);
1275 }
1276
1277 extern int flagcode_valueIndex (flagcode f)
1278 {
1279   /*@unchecked@*/ static bool initialized = FALSE;
1280   int i;
1281   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1282   
1283   if (!initialized)
1284     {
1285       int nv = 0;
1286
1287       allFlagCodes (code)
1288         {
1289           if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1290             {
1291               llassert (nv < NUMVALUEFLAGS);
1292               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1293               valueFlags[nv] = code;
1294               nv++;
1295             }
1296         } end_allFlagCodes;
1297
1298       llassertprint (nv == NUMVALUEFLAGS,
1299                      ("Number of value flags: %d (expected %d)",
1300                       nv, (int) NUMVALUEFLAGS));
1301       initialized = TRUE;
1302     }
1303
1304   for (i = 0; i < NUMVALUEFLAGS; i++)
1305     {
1306       /* static valueFlags must be defined */
1307       /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/
1308         {
1309           return i;
1310         }
1311     }
1312
1313   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1314   exit (EXIT_FAILURE);
1315   /* Cannot do this...might call recursively...
1316   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1317   BADEXIT;
1318   */
1319 }
1320
1321 extern int flagcode_stringIndex (flagcode f)
1322 {
1323   /*@unchecked@*/ static bool initialized = FALSE;
1324   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1325   int i;
1326
1327
1328   if (!initialized)
1329     {
1330       int nv = 0;
1331
1332       allFlagCodes (code)
1333         {
1334           if (flagcode_hasString (code))
1335             {
1336               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1337               stringFlags[nv] = code;
1338               nv++;
1339             }
1340         } end_allFlagCodes;
1341
1342       llassertprint (nv == NUMSTRINGFLAGS,
1343                      ("number of string flags: %d (expected %d)",
1344                       nv, NUMSTRINGFLAGS));
1345       initialized = TRUE;
1346     }
1347
1348   for (i = 0; i < NUMSTRINGFLAGS; i++)
1349     {
1350       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1351         {
1352           return i;
1353         }
1354     }
1355
1356   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1357   BADEXIT;
1358 }
1359
1360 bool flagcode_isNamePrefixFlag (flagcode f)
1361 {
1362   switch (f)
1363     {
1364     case FLG_MACROVARPREFIX:
1365     case FLG_TAGPREFIX:
1366     case FLG_ENUMPREFIX:
1367     case FLG_FILESTATICPREFIX:
1368     case FLG_GLOBPREFIX:
1369     case FLG_TYPEPREFIX:
1370     case FLG_EXTERNALPREFIX:
1371     case FLG_LOCALPREFIX:
1372     case FLG_UNCHECKEDMACROPREFIX:
1373     case FLG_CONSTPREFIX:
1374     case FLG_ITERPREFIX:
1375     case FLG_DECLPARAMPREFIX:
1376       return TRUE;
1377     default:
1378       return FALSE;
1379     }
1380 }
1381         
This page took 1.24009 seconds and 5 git commands to generate.