]> andersk Git - splint.git/blob - src/flags.c
- library fixes:
[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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** flags.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30 # include "osd.h"
31 # include "portab.h"
32 # include "rcfiles.h"
33 # include "lslinit.h"
34
35 /*
36 ** from the CC man page:
37 **
38 **  -Idir          Search for #include files whose names do not begin with a
39 **                    slash (/) in the following order: (1) in the directory of
40 **                    the dir argument, (2) in the directories specified by -I
41 **                    options, (3) in the standard directory (/usr/include).
42 */
43
44 /* needed for string literals literals */
45
46 typedef struct { 
47   flagkind kind;
48   /*@null@*/ /*@observer@*/ char *name;
49   /*@null@*/ /*@observer@*/ char *describe;
50 } flagcatinfo;
51
52 static flagcatinfo categories[] =
53 {
54   { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
55   { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
56   { FK_USE, "alluse", "all declarations are used" } ,
57   { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
58   { FK_ARRAY, "arrays", "special checking involving arrays" } ,
59   { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
60   { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
61   { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
62   { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
63   { FK_CONTROL, "controlflow", "suspicious control structures" } ,
64   { FK_DEBUG, "debug", "flags for debugging splint" } ,
65   { FK_DECL, "declarations", "consistency of declarations" } ,
66   { FK_DEF, "definition", "undefined storage errors" } ,
67   { FK_DIRECT, "directories", "set directores" } ,
68   { FK_DISPLAY, "display", "control what is displayed" } ,
69   { FK_EFFECT, "effect", "statements with no effects" } ,
70   { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
71   { FK_EXPORT, "export", "control what may be exported" } ,
72   { FK_EXPOSURE, "exposure", "representation exposure" } ,
73   { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
74   { FK_FILES, "files", "control system files" } ,
75   { FK_FORMAT, "format", "control format of warning messages" } ,
76   { FK_GLOBALS, "globals", "use of global and file static variables" },
77   { FK_HEADERS, "headers", "control inclusion and generation of header files" },
78   { FK_HELP, "help", "on-line help" },
79   { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" },
80   { FK_HINTS, "hints", "control display of warning hints" },
81   { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" },
82   { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
83   { FK_INIT, "initializations", "initialization files" } ,
84   { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
85   { FK_LEAK, "leaks", "memory leaks" } ,
86   { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
87   { FK_LIMITS, "limits", "violations of set limits" } ,
88   { FK_MACROS, "macros", "expansion, definition and use of macros" },
89   { FK_MEMORY, "memory", "memory management" } ,
90   { FK_MODIFIES, "modification", "modification errors" } ,
91   { FK_NAMES, "names", "naming conventions and limits" } ,
92   { FK_NULL, "null", "misuses of null pointers" } ,
93   { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
94   { FK_OPS, "operations", "checking of primitive operations" } ,
95   { FK_PARAMS, "parameters", "function and macro parameters" } ,
96   { FK_SPEED, "performance", "speeding up checking" } ,
97   { FK_POINTER, "pointers", "pointers" } ,
98   { FK_PRED, "predicates", "condition test expressions" } ,
99   { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
100   { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
101   { FK_PROTOS, "prototypes", "function prototypes" } ,
102   { FK_DEAD, "released", "using storage that has been deallocated" } ,
103   { FK_IGNORERET, "returnvals", "ignored return values" },
104   { FK_SECURITY, "security", "possible security vulnerability" },
105   { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
106   { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
107   { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
108   { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
109   { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
110   { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
111   { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
112   { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
113   { FK_SYNTAX, NULL, NULL } ,
114   { FK_TYPE, NULL, NULL } ,
115   { FK_SECRET, NULL, NULL } ,
116   { FK_OBSOLETE, NULL, NULL } ,
117   { FK_NONE, NULL, NULL }  /* must be last */
118 } ; 
119
120 typedef enum {
121   ARG_NONE,
122   ARG_NUMBER,    /* number */
123   ARG_CHAR,      /* char */
124   ARG_STRING,    /* string */
125   ARG_FILE,      /* filename (also a string) */
126   ARG_DIRECTORY, /* directory (also a string) */
127   ARG_PATH,      /* path */
128   ARG_SPECIAL   /* ? */
129 } argcode;
130
131 static /*@observer@*/ cstring argcode_unparse (argcode arg)
132 {
133   switch (arg) 
134     {
135     case ARG_STRING: return cstring_makeLiteralTemp ("string"); 
136     case ARG_FILE: return cstring_makeLiteralTemp ("filename"); 
137     case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
138     case ARG_PATH: return cstring_makeLiteralTemp ("path"); 
139     case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
140     case ARG_CHAR: return cstring_makeLiteralTemp ("character");
141     case ARG_NONE: 
142       BADBRANCH;
143     case ARG_SPECIAL:
144       BADBRANCH;
145     }
146 # ifdef WIN32
147 /* Make Microsoft VC++ happy */
148 # pragma warning (disable:4715) 
149 # endif
150 }      
151
152 typedef struct { 
153   flagkind main;
154   flagkind sub;
155   bool isSpecial;  /* setting this flag may set other flags (or values) */
156   bool isIdem;     /* idempotent - always sets to TRUE */
157   bool isGlobal;   /* cannot be set locally (using control comments) */
158   bool isModeFlag; /* set by modes */
159   argcode argtype;
160   /*@observer@*/ char *flag;
161   flagcode code; 
162   /*@observer@*/ /*@null@*/ char *desc;
163   bn_mstring hint; 
164   int nreported; 
165   int nsuppressed; 
166 } fflag;
167
168 typedef fflag flaglist[];
169
170 # include "flags.def"
171
172 /*@iter allFlags (yield observer fflag f); @*/
173 # define allFlags(m_f) \
174   { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
175 # define end_allFlags }}
176
177 static bn_mstring mode_names[] =
178
179   "weak", "standard", "checks", "strict", NULL, 
180 };
181
182 /*@iter allModes (yield bn_mstring modename)@*/
183 # define allModes(m_m) \
184   { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
185       { bn_mstring m_m = mode_names[m_ii]; m_ii++; 
186
187 # define end_allModes }}
188
189 /*@+enumint@*/
190
191 static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
192 static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
193 static cstringSList sortedFlags (void) /*@*/ ;
194 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
195
196 static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
197
198 # if 0
199 static /*@unused@*/ cstring listModes (void) /*@*/ ;
200 # endif
201
202 bool flagcode_isSpecialFlag (flagcode f)
203 {
204   return (flags[f].isSpecial);
205 }
206
207 bool flagcode_isGlobalFlag (flagcode f)
208 {
209   return (flags[f].isGlobal);
210 }
211
212 bool flagcode_isIdemFlag (flagcode f)
213 {
214   return (flags[f].isIdem);
215 }
216
217 bool flagcode_isModeFlag (flagcode f)
218 {
219   return (flags[f].isModeFlag);
220 }
221
222 bool flagcode_isNameChecksFlag (flagcode f)
223 {
224   return (flags[f].main == FK_NAMES);
225 }
226
227 bool flagcode_isHelpFlag (flagcode f)
228 {
229   return f == FLG_HELP;
230 }
231
232 bool flagcode_isMessageControlFlag (flagcode f)
233 {
234   /*
235   ** True if opt controls the display of messages.
236   ** These flags must be processed first.
237   */
238
239   return (f == FLG_SHOWSCAN 
240           || f == FLG_WARNRC 
241           || f == FLG_PARENFILEFORMAT
242           || f == FLG_MESSAGESTREAMSTDERR
243           || f == FLG_MESSAGESTREAMSTDOUT
244           || f == FLG_WARNINGSTREAMSTDERR
245           || f == FLG_WARNINGSTREAMSTDOUT
246           || f == FLG_ERRORSTREAMSTDERR
247           || f == FLG_ERRORSTREAMSTDOUT
248           || f == FLG_MESSAGESTREAM
249           || f == FLG_WARNINGSTREAM
250           || f == FLG_ERRORSTREAM
251           || f == FLG_STREAMOVERWRITE);
252 }
253
254 /*
255 ** Internal consistency check on the flags.
256 */
257
258 void flags_initMod ()
259 {
260   allFlagCodes (code)
261     {
262       /*@+enumint@*/
263       if (flags[code].code != code)
264         {
265           fprintf (stderr, 
266                    "*** ERROR: inconsistent flag %s / %d / %d", 
267                    flags[code].flag,
268                    flags[code].code, code);
269           
270           llbug (message ("*** ERROR: inconsistent flag %s / %d / %d", 
271                           cstring_fromChars (flags[code].flag),
272                           flags[code].code, code));
273         }
274       /*@=enumint@*/
275     } end_allFlagCodes;
276 }
277
278 void
279 summarizeErrors ()
280 {
281   bool hadOne = FALSE;
282   int sumrep = 0;
283   int sumsup = 0;
284
285   char *buf = mstring_create (128);
286
287   allFlags (f)
288     {
289       if (f.nreported > 0 || f.nsuppressed > 0)
290         {
291           int nrep = f.nreported;
292           int nsup = f.nsuppressed;
293           cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
294
295           if (!hadOne)
296             {
297               llmsgplain (cstring_makeLiteral
298                           ("\nError Type                Reported  Suppressed\n"
299                            "===================       ========  ========="));
300               hadOne = TRUE;
301             }
302
303           (void) snprintf (buf, 128, "%s%7d   %9d", cstring_toCharsSafe (fs), nrep, nsup);
304
305           sumrep += nrep;
306           sumsup += nsup;
307           
308           cstring_free (fs);
309           llmsg (cstring_copy (cstring_fromChars (buf)));
310         }
311     } end_allFlags;
312
313   if (hadOne)
314     {
315       cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
316
317       llmsglit ("                          ========  =========");
318
319       (void) snprintf (buf, 128, "%s%7d   %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
320       cstring_free (ts);
321       llmsgplain (cstring_copy (cstring_fromChars (buf)));
322     }
323
324   sfree (buf);
325 }
326
327 /*@+enumindex@*/
328
329 void
330 flagcode_recordError (flagcode f)
331 {
332   if (f != INVALID_FLAG)
333     {
334       if (f == FLG_WARNFLAGS)
335         {
336           ; /* don't count these */
337         }
338       else
339         {
340           /*drl bee: ec*/
341           /*drl bee: ec*/
342           flags[f].nreported = flags[f].nreported + 1;
343         }
344     }
345   else
346     {
347       llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
348     }
349 }
350
351 void
352 flagcode_recordSuppressed (flagcode f)
353 {
354   llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
355
356   /*drl bee: ec*/
357     /*drl bee: ec*/   flags[f].nsuppressed = flags[f].nsuppressed + 1;
358 }
359
360 int
361 flagcode_numReported (flagcode f)
362 {
363   llassert (f != INVALID_FLAG);
364
365   return (flags[f].nreported);
366 }
367
368 /*@observer@*/ cstring
369 flagcodeHint (flagcode f)
370 {
371   llassert (f != INVALID_FLAG);
372
373   /*drl bee: ec*/
374   if (mstring_isDefined (flags[f].hint))
375     {
376       return (cstring_fromChars (flags[f].hint));
377     }
378   else
379     {
380       return (cstring_fromChars (flags[f].desc));
381     }
382 }
383
384 static int categorySize (flagkind kind) /*@*/ 
385 {
386   int n = 0;
387
388   
389   allFlags (f)
390     {
391       if (f.main == kind || f.sub == kind)
392         {
393                   n++;
394         }
395     } end_allFlags;
396
397   return n;
398 }
399
400 flagkind identifyCategory (cstring s)
401 {
402   int i;
403
404   for (i = 0; categories[i].kind != FK_NONE; i++)
405     {
406         /*drl bee: mRug*/
407       if (mstring_isDefined (categories[i].name))
408         {
409           if (cstring_equalLit (s, categories[i].name))
410             {
411               return categories[i].kind;
412             }
413         }
414     }
415
416   return FK_NONE;
417 }
418
419 static /*@observer@*/ cstring categoryName (flagkind kind)
420 {
421   int i;
422
423   for (i = 0; categories[i].kind != FK_NONE; i++)
424     {
425         /*drl bee: mrUg*/
426       if (categories[i].kind == kind)
427         {
428           return (cstring_fromChars (categories[i].name));
429         }
430     }
431   
432   return (cstring_makeLiteralTemp ("<No Category>"));
433 }
434
435 static int categoryIndex (flagkind kind)
436 {
437   int i;
438
439   for (i = 0; categories[i].kind != FK_NONE; i++)
440     {
441         /*drl bee: mRug*/
442       if (categories[i].kind == kind)
443         {
444           return i;
445         }
446     }
447
448   return -1;
449 }
450
451 void printCategory (flagkind kind)
452 {
453   int index = categoryIndex (kind);
454
455   llassert (index >= 0);
456         /*drl bee: mRug*/
457   llmsg (message ("%s (%d flags)\n\3%s\n\n", 
458                   cstring_fromChars (categories[index].name), 
459                   categorySize (kind),
460                   cstring_fromChars (categories[index].describe)));
461
462   allFlags (f)
463     {
464       if (f.main == kind || f.sub == kind)
465         {
466           llmsg (message ("   %s\n\6%q", cstring_fromChars (f.flag), 
467                           describeFlagCode (f.code)));
468         }
469     } end_allFlags;
470 }
471
472 void 
473 listAllCategories (void)
474 {
475   int i;
476
477   for (i = 0; categories[i].kind != FK_NONE; i++)
478     {
479               /*drl bee: mRug*/
480       flagkind kind = categories[i].kind ;
481
482       if (categories[i].describe != NULL)
483         {
484           llmsg (message ("%s (%d flags)\n\3%s", 
485                           categoryName (kind), 
486                           categorySize (kind),
487                           cstring_fromChars (categories[i].describe)));
488         }
489     }
490 }
491
492 void
493 printAllFlags (bool desc, bool full)
494 {
495   if (full)
496     {
497       cstringSList fl = sortedFlags ();
498
499       cstringSList_elements (fl, el)
500         {
501           /*@i22@*/ /*find out why this is necessary*/
502           cstring tmp;
503           tmp = cstring_copy(el);
504           llmsg (message ("%q\n\n", describeFlag (tmp)));
505           cstring_free(tmp);
506         } end_cstringSList_elements ;
507
508       cstringSList_free (fl);
509     }
510   else
511     {
512       allFlags (f)
513         {
514           if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
515             {
516               if (mstring_isDefined (f.desc))
517                 {
518                   if (desc)
519                     {
520                       llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
521                                       cstring_fromChars (f.desc)));
522                     }
523                 }
524             }
525         } end_allFlags;
526     }
527 }
528
529 void
530 printFlagManual (bool html)
531 {
532   /*
533   ** Prints all flags by category, in order they appear in flags.def
534   */
535
536   flagkind lastCategory = FK_NONE;
537
538   allFlags (f) {
539     cstring flagname;
540     cstring flagtype = cstring_undefined;
541
542     if (f.main != lastCategory)
543       {
544         if (html)
545           {
546             llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
547           }
548         else
549           {
550             llmsg (message ("\n%s\n%s\n",
551                             categoryName (f.main),
552                             cstring_makeLiteralTemp ("===================================")));
553           }
554
555         lastCategory = f.main;
556       }
557
558     if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
559       {
560         if (html) 
561           {
562             flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
563           }
564         else
565           {
566             flagname = cstring_fromCharsNew (f.flag);
567           }
568       }
569     else
570       {
571         if (flagcode_hasString (f.code)) 
572           {
573             if (html)
574               {
575                 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
576                                     cstring_fromChars (f.flag), argcode_unparse (f.argtype));
577               }
578             else
579               {
580                 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
581               }
582             
583             if (cstring_isDefined (context_getString (f.code)))
584               {
585                 if (html)
586                   {
587                     flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
588                                         context_getString (f.code));
589                   }
590                 else
591                   {
592                     flagname = message ("%q [%s]", flagname,
593                                         context_getString (f.code));
594                   }
595               }
596           }
597         else if (f.argtype == ARG_CHAR)
598           {
599             if (html)
600               {
601                 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
602                                     cstring_fromChars (f.flag), argcode_unparse (f.argtype),
603                                     (char) context_getValue (f.code));
604               }
605             else
606               {
607                 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
608                                     (char) context_getValue (f.code));
609               }
610           }
611         else 
612           {
613             llassert (f.argtype == ARG_NUMBER);
614
615             if (html)
616               {
617                 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
618                                     cstring_fromChars (f.flag), argcode_unparse (f.argtype),
619                                     context_getValue (f.code));
620               }
621             else
622               {
623                 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
624                                     context_getValue (f.code));
625               }
626           }
627       }
628
629     if (f.isIdem)
630       {
631         if (html)
632           {
633             flagtype = message("%q<font color=\"green\">-</font>", flagtype);
634           }
635         else
636           {
637             flagtype = message("%q<->", flagtype);
638           }
639       }
640     
641     if (f.isGlobal)
642       {
643         if (html)
644           {
645             flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
646           }
647         else
648           {
649             flagtype = message ("%q<G>", flagtype);
650           }
651       }
652
653     if (f.isSpecial)
654       {
655         if (html)
656           {
657             flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
658           }
659         else
660           {
661             flagtype = message("%q<S>", flagtype);
662           }
663       }
664     
665     if (f.isModeFlag)
666       {
667         if (html)
668           {
669             flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
670           }
671         else
672           {
673             flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
674           }
675       }
676     else /* its a plain flag */
677       {
678         if (html)
679           {
680             flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
681                                 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
682           }
683         else
684           {
685             flagtype = message ("%q<P:%s>", flagtype,
686                                 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
687           }
688       }
689     
690     llmsg (message ("%s: %s", flagname, flagtype));
691
692     if (html)
693       {
694         llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
695       }
696
697     if (mstring_isDefined (f.hint))
698       {
699         llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
700       }
701     else
702       {
703         llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
704       }
705
706     if (html)
707       {
708         llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
709       }
710   } end_allFlags ;
711 }
712
713 cstring
714 describeFlagCode (flagcode flag)
715 {
716   cstring ret = cstring_undefined;
717   fflag f;
718   
719   if (flagcode_isInvalid (flag))
720     {
721       return (cstring_makeLiteral ("<invalid>"));
722     }
723
724   context_resetAllFlags ();
725   
726   /*drl bee: mRug*/
727   f = flags[flag];
728   ret = cstring_copy (cstring_fromChars (f.desc));
729   
730   if (f.sub != FK_NONE)
731     {
732       ret = message ("%q\nCategories: %s, %s",
733                      ret, 
734                      categoryName (f.main),
735                      categoryName (f.sub));
736     }
737   else 
738     {
739       if (f.main != FK_NONE)
740         {
741           cstring cname = categoryName (f.main);
742           
743           if (cstring_isDefined (cname))
744             {
745               ret = message ("%q\nCategory: %s",
746                              ret, cname);
747             }
748         }
749     }
750   
751   if (f.isModeFlag)
752     {
753       ret = message ("%q\nMode Settings: %q",
754                      ret, getFlagModeSettings (flag));
755     }
756   else
757     {
758       ret = message ("%q\nDefault Setting: %s",
759                      ret, 
760                      cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
761     }
762   
763   if (f.isGlobal)
764     {
765       ret = message("%q\nSet globally only", ret);
766     }
767   else
768     {
769       ret = message("%q\nSet locally", ret);
770     }
771   
772   switch (f.argtype)
773     {
774     case ARG_NONE:
775     case ARG_SPECIAL:
776       break;
777     case ARG_NUMBER:
778       ret = message("%q\nNumeric Argument.  Default: %d",
779                     ret,
780                     context_getValue (flag));
781       break;
782     case ARG_CHAR:
783       ret = message("%q\nCharacter Argument.  Default: %h",
784                     ret, (char) context_getValue (flag));
785       break;
786     case ARG_STRING:
787     case ARG_FILE:
788     case ARG_PATH:
789     case ARG_DIRECTORY:
790       {
791       if (cstring_isDefined (context_getString (flag)))
792         {
793           ret = message("%q\n%q argument.  Default: %s",
794                         ret,
795                         cstring_capitalize (argcode_unparse (f.argtype)),
796                         context_getString (flag));
797         }
798       else
799         {
800           ret = message("%q\n%s argument.  No default.", 
801                         ret,
802                         cstring_capitalize (argcode_unparse (f.argtype)));
803         }
804       break;
805       }
806     }
807   
808   if (mstring_isDefined (f.hint))
809     {
810       ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
811     }
812   
813   return ret;
814 }
815   
816 static cstring getFlagModeSettings (flagcode flag)
817 {
818   cstring res = cstring_undefined;
819   
820   allModes (mname)
821     {
822       context_setModeNoWarn (cstring_fromChars (mname));
823       
824       res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
825     } end_allModes;
826
827   return res;
828 }
829
830 cstring
831 describeFlag (cstring flagname)
832 {
833   cstring oflagname = cstring_copy (flagname);
834   flagcode f = flags_identifyFlag (flagname);
835
836   if (flagcode_isSkip (f))
837     {
838       cstring_free (oflagname);
839       return cstring_undefined;
840     }
841   else if (flagcode_isValid (f))
842     {
843       if (cstring_equal (flagname, oflagname))
844         {
845           cstring_free (oflagname);
846           return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
847         }
848       else
849         {
850           return (message ("%q (standardized name: %s)\n\3%q",
851                            oflagname, flagname, describeFlagCode (f)));
852         }
853     }
854   else
855     {
856       if (flags_isModeName (flagname))
857         {
858           cstring_free (oflagname);
859
860           return
861             (message ("%s: predefined mode (see Manual for information)",
862                       flagname));
863         }
864       else
865         {
866           return (message ("%q: <invalid flag>", oflagname));
867         }
868     }
869 }
870
871 static cstringSList
872 sortedFlags (void)
873 {
874   cstringSList s = cstringSList_new ();
875
876   allFlags (f)
877     {
878       if (f.desc != NULL)
879         {
880           s = cstringSList_add (s, cstring_fromChars (f.flag));
881         }
882     } end_allFlags;
883
884   cstringSList_alphabetize (s);
885
886   return s;
887 }
888
889 void printAlphaFlags ()
890 {
891   cstringSList fl = sortedFlags ();
892
893   cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25); 
894   cstringSList_free (fl);
895 }
896
897 /*@observer@*/ cstring
898 flagcode_unparse (flagcode code)
899 {
900   if (code == INVALID_FLAG)
901     {
902       return cstring_makeLiteralTemp ("<invalid flag>");
903     }
904
905   return cstring_fromChars (flags[code].flag);
906 }
907
908 /*
909 ** Transforms a flag into its cannonical form.
910 **
911 ** The following transformations are made:
912 **
913 **    function      -> fcn
914 **    variable      -> var
915 **    constant      -> const
916 **    iterator      -> iter
917 **    parameter     -> param
918 **    unrecognized  -> unrecog
919 **    qualifier     -> qual         
920 **    declaration   -> decl
921 **    globalias     -> (no change)
922 **    global        -> glob
923 **    modifies      -> mods
924 **    modify        -> mod
925 **    pointer       -> ptr
926 **    implies       -> imp
927 **    implicit      -> imp
928 **    implied       -> imp
929 **    unconstrained -> unspec       
930 **    unconst       -> unspec
931 **    memory        -> mem
932 **    length        -> len
933 */
934
935 static /*@only@*/ cstring
936 canonicalizeFlag (cstring s)
937 {
938   int i = 0;
939   cstring res = cstring_copy (s);
940   static bn_mstring transform[] = 
941     { 
942       "function", "fcn",
943       "variable", "var",
944       "constant", "const",
945       "iterator", "iter",
946       "parameter", "param",
947       "unrecognized", "unrecog",
948       "qualifier", "qual",
949       "declaration", "decl",
950       "globals", "globs", 
951       "modifies", "mods", 
952       "modify", "mod",
953       "pointer", "ptr",
954       "implies", "imp",
955       "implicit", "imp",
956       "implied", "imp",
957       "unconstrained", "uncon",
958       "unconst", "uncon",
959       "memory", "mem",
960       "length", "len",
961       "return", "ret",
962       "system", "sys",
963       NULL
964       } ;
965   char *current;
966   
967   /*drl bee: ia*/
968   while ((current = transform[i]) != NULL)
969     {
970       if (cstring_containsLit (res, current))
971         {
972           cstring_replaceLit (res, current, transform[i+1]);
973         }
974       i += 2;
975     }
976
977   /* remove whitespace, -'s, and _'s */
978   cstring_stripChars (res, " -_");
979   return res;
980 }
981
982 flagcode
983 flags_identifyFlag (cstring s)
984 {
985   return flags_identifyFlagAux (s, FALSE);
986 }
987
988 flagcode
989 flags_identifyFlagQuiet (cstring s)
990 {
991   return flags_identifyFlagAux (s, TRUE);
992 }
993
994 static flagcode
995 flags_identifyFlagAux (cstring s, bool quiet)
996 {
997   cstring cflag;
998   flagcode res;
999
1000   if (cstring_length (s) == 0) {
1001     /* evs 2000-06-25: A malformed flag. */
1002     return INVALID_FLAG;
1003   }
1004
1005   if (cstring_firstChar (s) == 'I')
1006     {
1007       return FLG_INCLUDEPATH; /* no space required after -I */
1008     }
1009
1010   if (cstring_firstChar (s) == 'S') 
1011     {
1012       return FLG_SPECPATH;    /* no space required after -S */
1013     }
1014
1015   if (cstring_firstChar (s) == 'D') 
1016     {
1017       return FLG_DEFINE;      /* no space required after -D */
1018     }
1019
1020   if (cstring_firstChar (s) == 'U') 
1021     {
1022       return FLG_UNDEFINE;    /* no space required after -D */
1023     }
1024
1025   cflag = canonicalizeFlag (s);
1026   res = INVALID_FLAG;
1027
1028   allFlags (f)
1029     {
1030       if (cstring_equal (cstring_fromChars (f.flag), cflag))
1031         {
1032           res = f.code;
1033           break;
1034         }
1035     } end_allFlags;
1036   
1037   if (res == INVALID_FLAG)
1038     {
1039       /*
1040       ** Synonyms
1041       */
1042       
1043       if (cstring_equalLit (cflag, "pred"))
1044         {
1045           res = FLG_PREDBOOL;
1046         }
1047       else if (cstring_equalLit (cflag, "modobserverstrict"))
1048         {
1049           res = FLG_MODOBSERVERUNCON;
1050         }
1051       else if (cstring_equalLit (cflag, "czechnames"))
1052         {
1053           res = FLG_CZECH;
1054         }
1055       else if (cstring_equalLit (cflag, "slovaknames"))
1056         {
1057           res = FLG_SLOVAK;
1058         }
1059       else if (cstring_equalLit (cflag, "czechoslovaknames"))
1060         {
1061           res = FLG_CZECHOSLOVAK;
1062         }
1063       else if (cstring_equalLit (cflag, "globunspec")
1064                || cstring_equalLit (cflag, "globuncon"))
1065         {
1066           res = FLG_GLOBUNSPEC;
1067         }
1068       else if (cstring_equalLit (cflag, "modglobsunspec")
1069                || cstring_equalLit (cflag, "modglobsuncon")
1070                || cstring_equalLit (cflag, "modglobsnomods"))
1071         {
1072           res = FLG_MODGLOBSUNSPEC;
1073         }
1074       else if (cstring_equalLit (cflag, "export"))
1075         {
1076           res = FLG_EXPORTANY;
1077         }
1078       else if (cstring_equalLit (cflag, "macrospec"))
1079         {
1080           res = FLG_MACRODECL;
1081         }
1082       else if (cstring_equalLit (cflag, "ansireservedlocal"))
1083         {
1084           res = FLG_ISORESERVEDLOCAL;
1085         }
1086       else if (cstring_equalLit (cflag, "warnposix"))
1087         {
1088           res = FLG_WARNPOSIX;
1089         }
1090       else if (cstring_equalLit (cflag, "defuse"))
1091         {
1092           res = FLG_USEDEF;
1093         }
1094       else if (cstring_equalLit (cflag, "macroundef"))
1095         {
1096           res = FLG_MACROUNDEF;
1097         }
1098       else if (cstring_equalLit (cflag, "showcol"))
1099         {
1100           res = FLG_SHOWCOL;
1101         }
1102       else if (cstring_equalLit (cflag, "intbool"))
1103         {
1104           res = FLG_BOOLINT;
1105         }
1106       else if (cstring_equalLit (cflag, "intchar"))
1107         {
1108           res = FLG_CHARINT;
1109         }
1110       else if (cstring_equalLit (cflag, "intenum"))
1111         {
1112           res = FLG_ENUMINT;
1113         }
1114       /*
1115       ** Backwards compatibility for our American friends...
1116       */
1117       
1118       else if (cstring_equalLit (cflag, "ansilib"))
1119         {
1120           res = FLG_ANSILIB;
1121         }
1122       else if (cstring_equalLit (cflag, "ansistrictlib"))
1123         {
1124           res = FLG_STRICTLIB;
1125         }
1126       else if (cstring_equalLit (cflag, "skipansiheaders"))
1127         {
1128           res = FLG_SKIPISOHEADERS;
1129         }
1130       else if (cstring_equalLit (cflag, "ansireserved"))
1131         {
1132           res = FLG_ISORESERVED;
1133         }
1134       else if (cstring_equalLit (cflag, "ansireservedinternal"))
1135         {
1136           res = FLG_ISORESERVEDLOCAL;
1137         }
1138       
1139       /*
1140       ** Obsolete Flags
1141       */
1142       
1143       else if (cstring_equalLit (cflag, "accessunspec"))
1144         {
1145           if (!quiet) 
1146             {
1147               llerror_flagWarning 
1148                 (cstring_makeLiteral
1149                  ("accessunspec flag is no longer supported.  It has been replaced by accessmodule, accessfile and "
1150                   "accessfunction to provide more precise control of accessibility "
1151                   "of representations.  For more information, "
1152                   "see splint -help accessmodule"));
1153             }
1154           
1155           res = SKIP_FLAG;
1156         }
1157       else if (cstring_equalLit (cflag, "ansilimits"))
1158         {
1159           llerror_flagWarning 
1160             (cstring_makeLiteral
1161              ("ansilimits flag is no longer supported.  It has been replaced by ansi89limits and "
1162               "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1163               "standard or the typically higher limits prescribed by ISO C99."));
1164           
1165           res = SKIP_FLAG;
1166         }
1167       else if (cstring_equalLit (cflag, "staticmods"))
1168         {
1169           if (!quiet) 
1170             {
1171               llerror_flagWarning 
1172                 (cstring_makeLiteral
1173                  ("staticmods flag is obsolete.  You probably "
1174                   "want impcheckmodstatics.  For more information, "
1175                   "see splint -help impcheckmodstatics"));
1176             }
1177           
1178           res = SKIP_FLAG;
1179         }
1180       else if (cstring_equalLit (cflag, "bool"))
1181         {
1182           if (!quiet) 
1183             {
1184               llerror_flagWarning
1185                 (cstring_makeLiteral ("bool flag is obsolete.  It never really "
1186                                       "made sense in the first place."));
1187             }
1188           
1189           res = SKIP_FLAG;
1190         }
1191       else if (cstring_equalLit (cflag, "shiftsigned"))
1192         {
1193           if (!quiet) 
1194             {
1195               llerror_flagWarning
1196                 (cstring_makeLiteral ("shiftsigned flag is obsolete.  You probably "
1197                                       "want bitwisesigned, shiftnegative or shiftimplementation."));
1198             }
1199           
1200           res = SKIP_FLAG;
1201         }
1202       else if (cstring_equalLit (cflag, "ansi"))
1203         {
1204           if (!quiet) 
1205             {
1206               llerror_flagWarning
1207                 (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
1208                                       "want noparams and/or oldstyle."));
1209             }
1210           
1211           res = SKIP_FLAG;
1212         }
1213       else if (cstring_equalLit (cflag, "usestderr"))
1214         {
1215           if (!quiet)
1216             {
1217               llerror_flagWarning 
1218                 (cstring_makeLiteral
1219                  ("usestderr flag is obsolete. This has been replaced "
1220                   "by more precise flags for controlling the warning, "
1221                   "status message and fatal error streams independently: message-stream-stdout, "
1222                   "message-stream-stderr, message-stream <file>, "
1223                   "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1224                   "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1225             }
1226           
1227           res = SKIP_FLAG;
1228         }
1229
1230       else if (cstring_equalLit (cflag, "stdio"))
1231         {
1232           if (!quiet) 
1233             {
1234               llerror_flagWarning 
1235                 (cstring_makeLiteral
1236                  ("stdio flag is obsolete.  You may "
1237                   "want strictlib or one of the gloabls "
1238                   "checking flags.  For more information, "
1239                   "see splint -help strictlib or splint -help flags globals"));
1240             }
1241           
1242           res = SKIP_FLAG;
1243         }
1244       else if (flags_isModeName (cflag))
1245         {
1246           res = MODENAME_FLAG;
1247         }
1248       else
1249         {
1250           res = INVALID_FLAG;
1251         }
1252     }
1253
1254   cstring_free (cflag);
1255   return res;
1256 }
1257
1258 void setValueFlag (flagcode opt, cstring arg)
1259 {
1260   switch (opt)
1261     {
1262     case FLG_EXPECT:
1263     case FLG_LCLEXPECT:
1264     case FLG_LIMIT:  
1265     case FLG_LINELEN:
1266     case FLG_INDENTSPACES:
1267     case FLG_BUGSLIMIT:
1268     case FLG_EXTERNALNAMELEN:
1269     case FLG_INTERNALNAMELEN:
1270     case FLG_CONTROLNESTDEPTH:
1271     case FLG_STRINGLITERALLEN:
1272     case FLG_NUMSTRUCTFIELDS:
1273     case FLG_NUMENUMMEMBERS:
1274     case FLG_INCLUDENEST:
1275       {
1276         int val = cstring_toPosInt (arg);
1277
1278         if (val < 0)
1279           {
1280             llerror 
1281               (FLG_BADFLAG,
1282                message 
1283                ("Flag %s must be followed by a positive number number.  "
1284                 "Followed by %s",
1285                 flagcode_unparse (opt), arg));
1286           }
1287         else
1288           {
1289             context_setValueAndFlag (opt, val);
1290           }
1291       }
1292       break;
1293     case FLG_COMMENTCHAR:
1294       {
1295         if (cstring_length (arg) != 1)
1296           {
1297             llfatalerrorLoc
1298               (message
1299                ("Flag %s should be followed by a single character.  Followed by %s",
1300                 flagcode_unparse (opt), arg));
1301           }
1302         else
1303           {
1304             context_setCommentMarkerChar (cstring_firstChar (arg));
1305           }
1306       }
1307       break;
1308     BADDEFAULT;
1309     }
1310 }
1311
1312 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1313 {
1314   switch (opt)
1315     {
1316     case FLG_TMPDIR:
1317       {
1318         if (cstring_lastChar (arg) == CONNECTCHAR)
1319           {
1320             context_setString (opt, arg);
1321           }
1322         else
1323           {
1324             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1325           }
1326         break;
1327       }
1328     default:
1329       {
1330         context_setString (opt, arg);
1331         break;
1332       }
1333     }
1334 }
1335
1336 cstring
1337 describeModes ()
1338 {
1339   cstring s = cstring_makeLiteral ("Flag                    ");
1340   cstringSList sflags = sortedFlags ();
1341
1342   allModes (modename)
1343     {
1344       s = message ("%q%9s", s, cstring_fromChars (modename));
1345     } end_allModes;
1346   
1347   s = message ("%q\n", s);
1348
1349   cstringSList_elements (sflags, flagname)
1350     {
1351       flagcode code = flags_identifyFlag (flagname);
1352       fflag currentflag = flags[code];
1353       
1354       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1355         {
1356           s = message ("%q\n%27s", s, 
1357                        cstring_fromChars (currentflag.flag));
1358           
1359           allModes (modename)
1360             {
1361               context_setMode (cstring_fromChars (modename));
1362               
1363               if (context_getFlag (code))
1364                 {
1365                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1366                 }
1367               else
1368                 {
1369                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1370                 }
1371
1372               context_resetModeFlags ();
1373             } end_allModes;
1374         }
1375     } end_cstringSList_elements;
1376   
1377   cstringSList_free (sflags);
1378
1379   s = cstring_appendChar (s, '\n');
1380
1381   return (s);
1382 }
1383
1384 # if 0
1385 static /*@unused@*/ cstring
1386 listModes (void)
1387 {
1388   cstring s = cstring_makeLiteral ("\t");
1389   int i = 0;
1390
1391   allModes (modename)
1392     {
1393       if (i != 0 && (i % 4 == 0))
1394         {
1395           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1396         }
1397       else
1398         {
1399           s = message ("%q%15s", s, cstring_fromChars (modename));
1400         }
1401       i++;
1402     } end_allModes;
1403
1404   return s;
1405 }
1406 # endif
1407
1408 bool
1409 flags_isModeName (cstring s)
1410 {
1411   allModes (modename)
1412     {
1413       if (mstring_isDefined (modename))
1414         {
1415           if (cstring_equalLit (s, modename))
1416             {
1417               return TRUE;
1418             }
1419         }
1420      } end_allModes;
1421
1422   return FALSE;
1423 }
1424
1425 extern bool flagcode_hasArgument (flagcode f)
1426 {
1427   return (flags[f].argtype != ARG_NONE);
1428 }
1429
1430 extern bool flagcode_hasNumber (flagcode f)
1431 {
1432   return (flags[f].argtype == ARG_NUMBER);
1433 }
1434
1435 extern bool flagcode_hasChar (flagcode f)
1436 {
1437   return (flags[f].argtype == ARG_CHAR);
1438 }
1439
1440 extern bool flagcode_hasString (flagcode f)
1441 {
1442   return (flags[f].argtype == ARG_STRING
1443           || flags[f].argtype == ARG_FILE
1444           || flags[f].argtype == ARG_DIRECTORY
1445           || flags[f].argtype == ARG_PATH);
1446 }
1447
1448 extern int flagcode_valueIndex (flagcode f)
1449 {
1450   /*@unchecked@*/ static bool initialized = FALSE;
1451   int i;
1452   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1453   
1454   if (!initialized)
1455     {
1456       int nv = 0;
1457
1458       allFlagCodes (code)
1459         {
1460           if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1461             {
1462               llassert (nv < NUMVALUEFLAGS);
1463               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1464               valueFlags[nv] = code;
1465               nv++;
1466             }
1467         } end_allFlagCodes;
1468
1469       llassertprint (nv == NUMVALUEFLAGS,
1470                      ("Number of value flags: %d (expected %d)",
1471                       nv, (int) NUMVALUEFLAGS));
1472       initialized = TRUE;
1473     }
1474
1475   for (i = 0; i < NUMVALUEFLAGS; i++)
1476     {
1477       /* static valueFlags must be defined */
1478       /*@-usedef@*/
1479       /*drl bee: sta*/
1480       if (f == valueFlags[i]) /*@=usedef@*/
1481         {
1482           return i;
1483         }
1484     }
1485
1486   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1487   exit (EXIT_FAILURE);
1488   /* Cannot do this...might call recursively...
1489   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1490   BADEXIT;
1491   */
1492 }
1493
1494 extern int flagcode_stringIndex (flagcode f)
1495 {
1496   /*@unchecked@*/ static bool initialized = FALSE;
1497   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1498   int i;
1499
1500
1501   if (!initialized)
1502     {
1503       int nv = 0;
1504
1505       allFlagCodes (code)
1506         {
1507           if (flagcode_hasString (code))
1508             {
1509               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1510               stringFlags[nv] = code;
1511               nv++;
1512             }
1513         } end_allFlagCodes;
1514
1515       llassertprint (nv == NUMSTRINGFLAGS,
1516                      ("number of string flags: %d (expected %d)",
1517                       nv, NUMSTRINGFLAGS));
1518       initialized = TRUE;
1519     }
1520
1521   for (i = 0; i < NUMSTRINGFLAGS; i++)
1522     {
1523               /*drl bee: sta*/
1524       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1525         {
1526           return i;
1527         }
1528     }
1529
1530   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1531   BADEXIT;
1532 }
1533
1534 bool flagcode_isNamePrefixFlag (flagcode f)
1535 {
1536   switch (f)
1537     {
1538     case FLG_MACROVARPREFIX:
1539     case FLG_TAGPREFIX:
1540     case FLG_ENUMPREFIX:
1541     case FLG_FILESTATICPREFIX:
1542     case FLG_GLOBPREFIX:
1543     case FLG_TYPEPREFIX:
1544     case FLG_EXTERNALPREFIX:
1545     case FLG_LOCALPREFIX:
1546     case FLG_UNCHECKEDMACROPREFIX:
1547     case FLG_CONSTPREFIX:
1548     case FLG_ITERPREFIX:
1549     case FLG_DECLPARAMPREFIX:
1550       return TRUE;
1551     default:
1552       return FALSE;
1553     }
1554 }
1555
1556 static cstring findLarchPathFile (/*@temp@*/ cstring s)
1557 {
1558   cstring pathName;
1559   filestatus status;
1560   
1561   status = osd_getPath (context_getLarchPath (), s, &pathName);
1562   
1563   if (status == OSD_FILEFOUND)
1564     {
1565       return pathName;
1566     }
1567   else if (status == OSD_FILENOTFOUND)
1568     {
1569       showHerald ();
1570       lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1571     }
1572   else if (status == OSD_PATHTOOLONG)
1573     {
1574       /* Directory and filename are too long.  Report error. */
1575       llbuglit ("soure_getPath: Filename plus directory from search path too long");
1576     }
1577   else
1578     {
1579       BADBRANCH;
1580     }
1581
1582   return cstring_undefined;
1583 }
1584
1585 static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1586 {
1587   cstring pathName = findLarchPathFile (s);
1588
1589   if (cstring_isDefined (pathName))
1590     {
1591       if (fileTable_exists (context_fileTable (), pathName))
1592         {
1593           showHerald ();
1594           lldiagmsg (message ("File listed multiple times: %s", pathName));
1595           cstring_free (pathName);
1596         }
1597       else
1598         {
1599           fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1600         }
1601     }
1602 }
1603
1604
1605 static void addFile (fileIdList files, /*@only@*/ cstring s)
1606 {
1607   if (fileTable_exists (context_fileTable (), s))
1608     {
1609       showHerald ();
1610       lldiagmsg (message ("File listed multiple times: %s", s));
1611       cstring_free (s);
1612     }
1613   else
1614     {
1615       fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1616     }
1617 }
1618
1619 static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1620 {
1621   cstring pathName = findLarchPathFile (s);
1622
1623   if (cstring_isDefined (pathName))
1624     {
1625       if (fileTable_exists (context_fileTable (), pathName))
1626         {
1627           showHerald ();
1628           lldiagmsg (message ("File listed multiple times: %s", s));
1629         }
1630       else
1631         {
1632           fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1633         }
1634     }
1635
1636   cstring_free (pathName);
1637 }
1638
1639 void
1640 flags_processFlags (bool inCommandLine, 
1641                     fileIdList xfiles,
1642                     fileIdList cfiles,
1643                     fileIdList lclfiles,
1644                     fileIdList mtfiles,
1645                     cstringSList *passThroughArgs,
1646                     int argc, char **argv)
1647 {
1648   int i;
1649   cstringSList fl = cstringSList_undefined;
1650     
1651   for (i = 0; i < argc; i++)
1652     {
1653       char *thisarg;
1654
1655       llassert (argv != NULL);
1656       thisarg = argv[i];
1657       
1658       DPRINTF (("process thisarg [%d]: %s", i, thisarg));
1659
1660       if (*thisarg == '-' || *thisarg == '+')
1661         {
1662           bool set = (*thisarg == '+');
1663           cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */
1664           flagcode opt = flags_identifyFlag (flagname);
1665
1666           DPRINTF (("Flag: %s", flagcode_unparse (opt)));
1667           
1668           if (flagcode_isInvalid (opt))
1669             {
1670               DPRINTF (("Error!"));
1671               voptgenerror (FLG_BADFLAG,
1672                             message ("Unrecognized option: %s", 
1673                                      cstring_fromChars (thisarg)),
1674                             g_currentloc);
1675             }
1676           else if (flagcode_isHelpFlag (opt))
1677             {
1678               if (inCommandLine)
1679                 {
1680                   voptgenerror (FLG_BADFLAG,
1681                                 message ("Help flag must be first on the command line: %s", 
1682                                          cstring_fromChars (thisarg)),
1683                                 g_currentloc);
1684                 }
1685               else
1686                 {
1687                   voptgenerror (FLG_BADFLAG,
1688                                 message ("Help flags can only be used on the command line: %s", 
1689                                          cstring_fromChars (thisarg)),
1690                                 g_currentloc);
1691                 }
1692             }
1693           else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1694             { 
1695               /*
1696               ** Following space is optional, don't include the -
1697               */
1698               
1699               *passThroughArgs = cstringSList_add (*passThroughArgs, 
1700                                                    cstring_fromChars (thisarg + 1));
1701             }
1702           else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1703             {
1704               cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
1705               
1706               DPRINTF (("Directory: %s", dir));
1707               
1708               switch (opt)
1709                 {
1710                 case FLG_INCLUDEPATH:
1711                   cppAddIncludeDir (dir);
1712                   /*@switchbreak@*/ break;
1713                 case FLG_SPECPATH:
1714                   /*@-mustfree@*/
1715                   g_localSpecPath = cstring_toCharsSafe
1716                     (message ("%s%h%s", 
1717                               cstring_fromChars (g_localSpecPath), 
1718                               PATH_SEPARATOR,
1719                               dir));
1720                   /*@=mustfree@*/
1721                   /*@switchbreak@*/ break;
1722                   BADDEFAULT;
1723                 }
1724             }
1725           else if (flagcode_isModeName (opt))
1726             {
1727               context_setMode (flagname);
1728             }
1729           else if (inCommandLine && flagcode_isMessageControlFlag (opt))
1730             {
1731               /*
1732               ** Processed on first pass
1733               */
1734               
1735               if (flagcode_hasArgument (opt))
1736                 {
1737                   ++i;
1738                 }
1739             }
1740           else
1741             {
1742               /*
1743               ** A normal control flag
1744               */
1745
1746               context_userSetFlag (opt, set);
1747               
1748               if (flagcode_hasArgument (opt))
1749                 {
1750                   if (flagcode_hasNumber (opt))
1751                     {
1752                       if (++i < argc)
1753                         {
1754                           setValueFlag (opt, cstring_fromChars (argv[i]));
1755                         }
1756                       else
1757                         {
1758                           voptgenerror
1759                             (FLG_BADFLAG,
1760                              message
1761                              ("Flag %s must be followed by a number",
1762                               flagcode_unparse (opt)),
1763                              g_currentloc);
1764                         }
1765                     } 
1766                   else if (flagcode_hasChar (opt))
1767                     {
1768                       if (++i < argc)
1769                         {
1770                           setValueFlag (opt, cstring_fromChars (argv[i]));
1771                         }
1772                       else
1773                         {
1774                           voptgenerror
1775                             (FLG_BADFLAG,
1776                              message
1777                              ("Flag %s must be followed by a character",
1778                               flagcode_unparse (opt)),
1779                              g_currentloc);
1780                         }
1781                     } 
1782                   else if (flagcode_hasString (opt)
1783                            || opt == FLG_INIT || opt == FLG_OPTF)
1784                     {
1785                       if (++i < argc)
1786                         {
1787                           cstring arg = cstring_fromChars (argv[i]);
1788                           
1789                           if (opt == FLG_OPTF)
1790                             {
1791                               if (inCommandLine)
1792                                 {
1793                                   ; /* -f already processed */
1794                                 }
1795                               else
1796                                 {
1797                                   (void) rcfiles_read (arg, passThroughArgs, TRUE);
1798                                 }
1799                             }
1800                           else if (opt == FLG_INIT)
1801                             {
1802 # ifndef NOLCL
1803                               lslinit_setInitFile (inputStream_create 
1804                                                    (arg, 
1805                                                     cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1806                                                     FALSE));
1807 # endif
1808                               break;
1809                             }
1810                           else
1811                             {
1812                               DPRINTF (("String flag: %s / %s",
1813                                         flagcode_unparse (opt), arg));
1814                               if (opt == FLG_MTSFILE)
1815                                 {
1816                                   /*
1817                                   ** arg identifies mts files
1818                                   */
1819                                   cstring tmp =  message ("%s%s", arg, MTS_EXTENSION);
1820                                   addLarchPathFile (mtfiles, tmp);
1821                                   cstring_free (tmp);
1822                                   tmp = message ("%s%s", arg, XH_EXTENSION);
1823                                   addXHFile (xfiles, tmp);
1824                                   cstring_free (tmp);
1825                                 }
1826                               else
1827                                 {
1828                                   setStringFlag (opt, cstring_copy (arg));
1829                                 }
1830                             }
1831                         }
1832                       else
1833                         {
1834                           voptgenerror
1835                             (FLG_BADFLAG,
1836                              message
1837                              ("Flag %s must be followed by a string",
1838                               flagcode_unparse (opt)),
1839                              g_currentloc);
1840                         }
1841                     }
1842                   else
1843                     {
1844                       /* no argument */
1845                     }
1846                 }
1847             }
1848         }
1849       else /* its a filename */
1850         {
1851           DPRINTF (("Adding filename: %s", thisarg));
1852           fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1853         }
1854     }
1855   
1856   /*
1857   ** create lists of C and LCL files
1858   */
1859   
1860   if (inCommandLine)
1861     {
1862       cstringSList_elements (fl, current)
1863         {
1864           cstring ext = fileLib_getExtension (current);
1865           
1866           if (cstring_isUndefined (ext))
1867             {
1868               /* no extension --- both C and LCL with default extensions */
1869               
1870               addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1871               addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
1872             }
1873           else if (cstring_equal (ext, XH_EXTENSION))
1874             {
1875               addXHFile (xfiles, current);
1876             }
1877           else if (cstring_equal (ext, PP_EXTENSION))
1878             {
1879               if (!context_getFlag (FLG_NOPP))
1880                 {
1881                   voptgenerror 
1882                     (FLG_FILEEXTENSIONS,
1883                      message ("File extension %s used without +nopp flag (will be processed as C source code): %s", 
1884                               ext, current),
1885                      g_currentloc);
1886                 }
1887               
1888               addFile (cfiles, cstring_copy (current));
1889             }
1890           else if (cstring_equal (ext, LCL_EXTENSION)) 
1891             {
1892               addFile (lclfiles, cstring_copy (current));
1893             }
1894           else if (fileLib_isCExtension (ext))
1895             {
1896               addFile (cfiles, cstring_copy (current));
1897             }
1898           else if (cstring_equal (ext, MTS_EXTENSION))
1899             {
1900               addLarchPathFile (mtfiles, current);
1901             }
1902           else 
1903             {
1904               voptgenerror 
1905                 (FLG_FILEEXTENSIONS,
1906                  message ("Unrecognized file extension: %s (assuming %s is C source code)", 
1907                           current, ext),
1908                  g_currentloc);
1909               
1910               addFile (cfiles, cstring_copy (current));
1911             }
1912         } end_cstringSList_elements;
1913     }
1914   else
1915     {
1916       if (cstringSList_size (fl) != 0)
1917         {
1918           /* Cannot list files in .splintrc files */
1919           voptgenerror (FLG_BADFLAG, 
1920                         message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1921                                  cstringSList_unparse (fl)),
1922                         g_currentloc);
1923         }
1924     }
1925 }
This page took 3.02863 seconds and 5 git commands to generate.