]> andersk Git - splint.git/blob - src/flags.c
Fixed parsing problem with multiple inclusions of alt typedefs.
[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       else if (cstring_equalLit (cflag, "intlong"))
1115         {
1116           res = FLG_LONGINT;
1117         }
1118       else if (cstring_equalLit (cflag, "intshort"))
1119         {
1120           res = FLG_SHORTINT;
1121         }
1122       /*
1123       ** Backwards compatibility for our American friends...
1124       */
1125       
1126       else if (cstring_equalLit (cflag, "ansilib"))
1127         {
1128           res = FLG_ANSILIB;
1129         }
1130       else if (cstring_equalLit (cflag, "ansistrictlib"))
1131         {
1132           res = FLG_STRICTLIB;
1133         }
1134       else if (cstring_equalLit (cflag, "skipansiheaders"))
1135         {
1136           res = FLG_SKIPISOHEADERS;
1137         }
1138       else if (cstring_equalLit (cflag, "ansireserved"))
1139         {
1140           res = FLG_ISORESERVED;
1141         }
1142       else if (cstring_equalLit (cflag, "ansireservedinternal"))
1143         {
1144           res = FLG_ISORESERVEDLOCAL;
1145         }
1146       
1147       /*
1148       ** Obsolete Flags
1149       */
1150       
1151       else if (cstring_equalLit (cflag, "accessunspec"))
1152         {
1153           if (!quiet) 
1154             {
1155               llerror_flagWarning 
1156                 (cstring_makeLiteral
1157                  ("accessunspec flag is no longer supported.  It has been replaced by accessmodule, accessfile and "
1158                   "accessfunction to provide more precise control of accessibility "
1159                   "of representations.  For more information, "
1160                   "see splint -help accessmodule"));
1161             }
1162           
1163           res = SKIP_FLAG;
1164         }
1165       else if (cstring_equalLit (cflag, "ansilimits"))
1166         {
1167           llerror_flagWarning 
1168             (cstring_makeLiteral
1169              ("ansilimits flag is no longer supported.  It has been replaced by ansi89limits and "
1170               "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1171               "standard or the typically higher limits prescribed by ISO C99."));
1172           
1173           res = SKIP_FLAG;
1174         }
1175       else if (cstring_equalLit (cflag, "staticmods"))
1176         {
1177           if (!quiet) 
1178             {
1179               llerror_flagWarning 
1180                 (cstring_makeLiteral
1181                  ("staticmods flag is obsolete.  You probably "
1182                   "want impcheckmodstatics.  For more information, "
1183                   "see splint -help impcheckmodstatics"));
1184             }
1185           
1186           res = SKIP_FLAG;
1187         }
1188       else if (cstring_equalLit (cflag, "bool"))
1189         {
1190           if (!quiet) 
1191             {
1192               llerror_flagWarning
1193                 (cstring_makeLiteral ("bool flag is obsolete.  It never really "
1194                                       "made sense in the first place."));
1195             }
1196           
1197           res = SKIP_FLAG;
1198         }
1199       else if (cstring_equalLit (cflag, "shiftsigned"))
1200         {
1201           if (!quiet) 
1202             {
1203               llerror_flagWarning
1204                 (cstring_makeLiteral ("shiftsigned flag is obsolete.  You probably "
1205                                       "want bitwisesigned, shiftnegative or shiftimplementation."));
1206             }
1207           
1208           res = SKIP_FLAG;
1209         }
1210       else if (cstring_equalLit (cflag, "ansi"))
1211         {
1212           if (!quiet) 
1213             {
1214               llerror_flagWarning
1215                 (cstring_makeLiteral ("ansi flag is obsolete.  You probably "
1216                                       "want noparams and/or oldstyle."));
1217             }
1218           
1219           res = SKIP_FLAG;
1220         }
1221       else if (cstring_equalLit (cflag, "usestderr"))
1222         {
1223           if (!quiet)
1224             {
1225               llerror_flagWarning 
1226                 (cstring_makeLiteral
1227                  ("usestderr flag is obsolete. This has been replaced "
1228                   "by more precise flags for controlling the warning, "
1229                   "status message and fatal error streams independently: message-stream-stdout, "
1230                   "message-stream-stderr, message-stream <file>, "
1231                   "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1232                   "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1233             }
1234           
1235           res = SKIP_FLAG;
1236         }
1237
1238       else if (cstring_equalLit (cflag, "stdio"))
1239         {
1240           if (!quiet) 
1241             {
1242               llerror_flagWarning 
1243                 (cstring_makeLiteral
1244                  ("stdio flag is obsolete.  You may "
1245                   "want strictlib or one of the gloabls "
1246                   "checking flags.  For more information, "
1247                   "see splint -help strictlib or splint -help flags globals"));
1248             }
1249           
1250           res = SKIP_FLAG;
1251         }
1252       else if (flags_isModeName (cflag))
1253         {
1254           res = MODENAME_FLAG;
1255         }
1256       else
1257         {
1258           res = INVALID_FLAG;
1259         }
1260     }
1261
1262   cstring_free (cflag);
1263   return res;
1264 }
1265
1266 void setValueFlag (flagcode opt, cstring arg)
1267 {
1268   switch (opt)
1269     {
1270     case FLG_EXPECT:
1271     case FLG_LCLEXPECT:
1272     case FLG_LIMIT:  
1273     case FLG_LINELEN:
1274     case FLG_INDENTSPACES:
1275     case FLG_BUGSLIMIT:
1276     case FLG_EXTERNALNAMELEN:
1277     case FLG_INTERNALNAMELEN:
1278     case FLG_CONTROLNESTDEPTH:
1279     case FLG_STRINGLITERALLEN:
1280     case FLG_NUMSTRUCTFIELDS:
1281     case FLG_NUMENUMMEMBERS:
1282     case FLG_INCLUDENEST:
1283       {
1284         int val = cstring_toPosInt (arg);
1285
1286         if (val < 0)
1287           {
1288             llerror 
1289               (FLG_BADFLAG,
1290                message 
1291                ("Flag %s must be followed by a positive number number.  "
1292                 "Followed by %s",
1293                 flagcode_unparse (opt), arg));
1294           }
1295         else
1296           {
1297             context_setValueAndFlag (opt, val);
1298           }
1299       }
1300       break;
1301     case FLG_COMMENTCHAR:
1302       {
1303         if (cstring_length (arg) != 1)
1304           {
1305             llfatalerrorLoc
1306               (message
1307                ("Flag %s should be followed by a single character.  Followed by %s",
1308                 flagcode_unparse (opt), arg));
1309           }
1310         else
1311           {
1312             context_setCommentMarkerChar (cstring_firstChar (arg));
1313           }
1314       }
1315       break;
1316     BADDEFAULT;
1317     }
1318 }
1319
1320 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1321 {
1322   switch (opt)
1323     {
1324     case FLG_TMPDIR:
1325       {
1326         if (cstring_lastChar (arg) == CONNECTCHAR)
1327           {
1328             context_setString (opt, arg);
1329           }
1330         else
1331           {
1332             context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1333           }
1334         break;
1335       }
1336     default:
1337       {
1338         context_setString (opt, arg);
1339         break;
1340       }
1341     }
1342 }
1343
1344 cstring
1345 describeModes ()
1346 {
1347   cstring s = cstring_makeLiteral ("Flag                    ");
1348   cstringSList sflags = sortedFlags ();
1349
1350   allModes (modename)
1351     {
1352       s = message ("%q%9s", s, cstring_fromChars (modename));
1353     } end_allModes;
1354   
1355   s = message ("%q\n", s);
1356
1357   cstringSList_elements (sflags, flagname)
1358     {
1359       flagcode code = flags_identifyFlag (flagname);
1360       fflag currentflag = flags[code];
1361       
1362       if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1363         {
1364           s = message ("%q\n%27s", s, 
1365                        cstring_fromChars (currentflag.flag));
1366           
1367           allModes (modename)
1368             {
1369               context_setMode (cstring_fromChars (modename));
1370               
1371               if (context_getFlag (code))
1372                 {
1373                   s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1374                 }
1375               else
1376                 {
1377                   s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1378                 }
1379
1380               context_resetModeFlags ();
1381             } end_allModes;
1382         }
1383     } end_cstringSList_elements;
1384   
1385   cstringSList_free (sflags);
1386
1387   s = cstring_appendChar (s, '\n');
1388
1389   return (s);
1390 }
1391
1392 # if 0
1393 static /*@unused@*/ cstring
1394 listModes (void)
1395 {
1396   cstring s = cstring_makeLiteral ("\t");
1397   int i = 0;
1398
1399   allModes (modename)
1400     {
1401       if (i != 0 && (i % 4 == 0))
1402         {
1403           s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1404         }
1405       else
1406         {
1407           s = message ("%q%15s", s, cstring_fromChars (modename));
1408         }
1409       i++;
1410     } end_allModes;
1411
1412   return s;
1413 }
1414 # endif
1415
1416 bool
1417 flags_isModeName (cstring s)
1418 {
1419   allModes (modename)
1420     {
1421       if (mstring_isDefined (modename))
1422         {
1423           if (cstring_equalLit (s, modename))
1424             {
1425               return TRUE;
1426             }
1427         }
1428      } end_allModes;
1429
1430   return FALSE;
1431 }
1432
1433 extern bool flagcode_hasArgument (flagcode f)
1434 {
1435   return (flags[f].argtype != ARG_NONE);
1436 }
1437
1438 extern bool flagcode_hasNumber (flagcode f)
1439 {
1440   return (flags[f].argtype == ARG_NUMBER);
1441 }
1442
1443 extern bool flagcode_hasChar (flagcode f)
1444 {
1445   return (flags[f].argtype == ARG_CHAR);
1446 }
1447
1448 extern bool flagcode_hasString (flagcode f)
1449 {
1450   return (flags[f].argtype == ARG_STRING
1451           || flags[f].argtype == ARG_FILE
1452           || flags[f].argtype == ARG_DIRECTORY
1453           || flags[f].argtype == ARG_PATH);
1454 }
1455
1456 extern int flagcode_valueIndex (flagcode f)
1457 {
1458   /*@unchecked@*/ static bool initialized = FALSE;
1459   int i;
1460   /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1461   
1462   if (!initialized)
1463     {
1464       int nv = 0;
1465
1466       allFlagCodes (code)
1467         {
1468           if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1469             {
1470               llassert (nv < NUMVALUEFLAGS);
1471               DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1472               valueFlags[nv] = code;
1473               nv++;
1474             }
1475         } end_allFlagCodes;
1476
1477       llassertprint (nv == NUMVALUEFLAGS,
1478                      ("Number of value flags: %d (expected %d)",
1479                       nv, (int) NUMVALUEFLAGS));
1480       initialized = TRUE;
1481     }
1482
1483   for (i = 0; i < NUMVALUEFLAGS; i++)
1484     {
1485       /* static valueFlags must be defined */
1486       /*@-usedef@*/
1487       /*drl bee: sta*/
1488       if (f == valueFlags[i]) /*@=usedef@*/
1489         {
1490           return i;
1491         }
1492     }
1493
1494   fprintf (stderr, "Cannot find value flag: %d", (int) f);
1495   exit (EXIT_FAILURE);
1496   /* Cannot do this...might call recursively...
1497   llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1498   BADEXIT;
1499   */
1500 }
1501
1502 extern int flagcode_stringIndex (flagcode f)
1503 {
1504   /*@unchecked@*/ static bool initialized = FALSE;
1505   /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1506   int i;
1507
1508
1509   if (!initialized)
1510     {
1511       int nv = 0;
1512
1513       allFlagCodes (code)
1514         {
1515           if (flagcode_hasString (code))
1516             {
1517               llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1518               stringFlags[nv] = code;
1519               nv++;
1520             }
1521         } end_allFlagCodes;
1522
1523       llassertprint (nv == NUMSTRINGFLAGS,
1524                      ("number of string flags: %d (expected %d)",
1525                       nv, NUMSTRINGFLAGS));
1526       initialized = TRUE;
1527     }
1528
1529   for (i = 0; i < NUMSTRINGFLAGS; i++)
1530     {
1531               /*drl bee: sta*/
1532       /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1533         {
1534           return i;
1535         }
1536     }
1537
1538   llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1539   BADEXIT;
1540 }
1541
1542 bool flagcode_isNamePrefixFlag (flagcode f)
1543 {
1544   switch (f)
1545     {
1546     case FLG_MACROVARPREFIX:
1547     case FLG_TAGPREFIX:
1548     case FLG_ENUMPREFIX:
1549     case FLG_FILESTATICPREFIX:
1550     case FLG_GLOBPREFIX:
1551     case FLG_TYPEPREFIX:
1552     case FLG_EXTERNALPREFIX:
1553     case FLG_LOCALPREFIX:
1554     case FLG_UNCHECKEDMACROPREFIX:
1555     case FLG_CONSTPREFIX:
1556     case FLG_ITERPREFIX:
1557     case FLG_DECLPARAMPREFIX:
1558       return TRUE;
1559     default:
1560       return FALSE;
1561     }
1562 }
1563
1564 static cstring findLarchPathFile (/*@temp@*/ cstring s)
1565 {
1566   cstring pathName;
1567   filestatus status;
1568   
1569   status = osd_getPath (context_getLarchPath (), s, &pathName);
1570   
1571   if (status == OSD_FILEFOUND)
1572     {
1573       return pathName;
1574     }
1575   else if (status == OSD_FILENOTFOUND)
1576     {
1577       showHerald ();
1578       lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1579     }
1580   else if (status == OSD_PATHTOOLONG)
1581     {
1582       /* Directory and filename are too long.  Report error. */
1583       llbuglit ("soure_getPath: Filename plus directory from search path too long");
1584     }
1585   else
1586     {
1587       BADBRANCH;
1588     }
1589
1590   return cstring_undefined;
1591 }
1592
1593 static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s)
1594 {
1595   cstring pathName = findLarchPathFile (s);
1596
1597   if (cstring_isDefined (pathName))
1598     {
1599       if (fileTable_exists (context_fileTable (), pathName))
1600         {
1601           showHerald ();
1602           lldiagmsg (message ("File listed multiple times: %s", pathName));
1603           cstring_free (pathName);
1604         }
1605       else
1606         {
1607           fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName));
1608         }
1609     }
1610 }
1611
1612
1613 static void addFile (fileIdList files, /*@only@*/ cstring s)
1614 {
1615   if (fileTable_exists (context_fileTable (), s))
1616     {
1617       showHerald ();
1618       lldiagmsg (message ("File listed multiple times: %s", s));
1619       cstring_free (s);
1620     }
1621   else
1622     {
1623       fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
1624     }
1625 }
1626
1627 static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
1628 {
1629   cstring pathName = findLarchPathFile (s);
1630
1631   if (cstring_isDefined (pathName))
1632     {
1633       if (fileTable_exists (context_fileTable (), pathName))
1634         {
1635           showHerald ();
1636           lldiagmsg (message ("File listed multiple times: %s", s));
1637         }
1638       else
1639         {
1640           fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
1641         }
1642     }
1643
1644   cstring_free (pathName);
1645 }
1646
1647 void
1648 flags_processFlags (bool inCommandLine, 
1649                     fileIdList xfiles,
1650                     fileIdList cfiles,
1651                     fileIdList lclfiles,
1652                     fileIdList mtfiles,
1653                     cstringList *passThroughArgs,
1654                     int argc, char **argv)
1655 {
1656   int i;
1657   cstringSList fl = cstringSList_undefined;
1658     
1659   for (i = 0; i < argc; i++)
1660     {
1661       char *thisarg;
1662
1663       llassert (argv != NULL);
1664       thisarg = argv[i];
1665       
1666       DPRINTF (("process thisarg [%d]: %s", i, thisarg));
1667
1668       if (*thisarg == '-' || *thisarg == '+')
1669         {
1670           bool set = (*thisarg == '+');
1671           cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */
1672           flagcode opt = flags_identifyFlag (flagname);
1673
1674           DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
1675           
1676           if (flagcode_isInvalid (opt))
1677             {
1678               DPRINTF (("Error!"));
1679               voptgenerror (FLG_BADFLAG,
1680                             message ("Unrecognized option: %s", 
1681                                      cstring_fromChars (thisarg)),
1682                             g_currentloc);
1683             }
1684           else if (flagcode_isHelpFlag (opt))
1685             {
1686               if (inCommandLine)
1687                 {
1688                   voptgenerror (FLG_BADFLAG,
1689                                 message ("Help flag must be first on the command line: %s", 
1690                                          cstring_fromChars (thisarg)),
1691                                 g_currentloc);
1692                 }
1693               else
1694                 {
1695                   voptgenerror (FLG_BADFLAG,
1696                                 message ("Help flags can only be used on the command line: %s", 
1697                                          cstring_fromChars (thisarg)),
1698                                 g_currentloc);
1699                 }
1700             }
1701           else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
1702             { 
1703               /*
1704               ** Following space is optional, don't include the -
1705               */
1706               
1707               *passThroughArgs = cstringList_add (*passThroughArgs, 
1708                                                   cstring_fromCharsNew (thisarg + 1));
1709             }
1710           else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
1711             {
1712               if (mstring_length (thisarg) < 2) {
1713                 BADBRANCH;
1714               } else {
1715                 if (mstring_equal (thisarg, "-I-")) {
1716                   cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */
1717                 } else {
1718                   cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */
1719                   
1720                   DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg)));
1721                   
1722                   if (cstring_length (dir) == 0) {
1723                     DPRINTF (("space after directory: "));
1724                     if (++i < argc) {
1725                       dir = cstring_fromChars (argv[i]);
1726                     } else {
1727                       voptgenerror
1728                         (FLG_BADFLAG,
1729                          message
1730                          ("Flag %s must be followed by a directory name",
1731                           flagcode_unparse (opt)),
1732                          g_currentloc);
1733                     }
1734                   } 
1735                   
1736                   DPRINTF (("Got directory: [%s]", dir));
1737                   
1738                   switch (opt)
1739                     {
1740                     case FLG_INCLUDEPATH:
1741                       cppAddIncludeDir (dir);
1742                       /*@switchbreak@*/ break;
1743                     case FLG_SPECPATH:
1744                       /*@-mustfree@*/
1745                       g_localSpecPath = cstring_toCharsSafe
1746                         (message ("%s%h%s", 
1747                                   cstring_fromChars (g_localSpecPath), 
1748                                   PATH_SEPARATOR,
1749                                   dir));
1750                       /*@=mustfree@*/
1751                       /*@switchbreak@*/ break;
1752                       BADDEFAULT;
1753                     }
1754                 }
1755               }
1756             }
1757           else if (flagcode_isModeName (opt))
1758             {
1759               context_setMode (flagname);
1760             }
1761           else if (inCommandLine && flagcode_isMessageControlFlag (opt))
1762             {
1763               /*
1764               ** Processed on first pass
1765               */
1766               
1767               if (flagcode_hasArgument (opt))
1768                 {
1769                   ++i;
1770                 }
1771             }
1772           else
1773             {
1774               /*
1775               ** A normal control flag
1776               */
1777
1778               context_userSetFlag (opt, set);
1779               
1780               if (flagcode_hasArgument (opt))
1781                 {
1782                   if (flagcode_hasNumber (opt))
1783                     {
1784                       if (++i < argc)
1785                         {
1786                           setValueFlag (opt, cstring_fromChars (argv[i]));
1787                         }
1788                       else
1789                         {
1790                           voptgenerror
1791                             (FLG_BADFLAG,
1792                              message
1793                              ("Flag %s must be followed by a number",
1794                               flagcode_unparse (opt)),
1795                              g_currentloc);
1796                         }
1797                     } 
1798                   else if (flagcode_hasChar (opt))
1799                     {
1800                       if (++i < argc)
1801                         {
1802                           setValueFlag (opt, cstring_fromChars (argv[i]));
1803                         }
1804                       else
1805                         {
1806                           voptgenerror
1807                             (FLG_BADFLAG,
1808                              message
1809                              ("Flag %s must be followed by a character",
1810                               flagcode_unparse (opt)),
1811                              g_currentloc);
1812                         }
1813                     } 
1814                   else if (flagcode_hasString (opt)
1815                            || opt == FLG_INIT || opt == FLG_OPTF)
1816                     {
1817                       if (++i < argc)
1818                         {
1819                           /*drl 10/21/2002
1820                             Changed this because arg can be freed when it's passed to
1821                             lslinit_setInitFile and freeing argv[i] causes a seg fault
1822                           */
1823                           cstring arg =  cstring_fromCharsNew (argv[i]);
1824                           
1825                           if (opt == FLG_OPTF)
1826                             {
1827                               if (inCommandLine)
1828                                 {
1829                                   ; /* -f already processed */
1830                                 }
1831                               else
1832                                 {
1833                                   (void) rcfiles_read (arg, passThroughArgs, TRUE);
1834                                 }
1835                             }
1836                           else if (opt == FLG_INIT)
1837                             {
1838                               lslinit_setInitFile (inputStream_create 
1839                                                    (arg, 
1840                                                     cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1841                                                     FALSE));
1842                               break;
1843                             }
1844                           else
1845                             {
1846                               DPRINTF (("String flag: %s / %s",
1847                                         flagcode_unparse (opt), arg));
1848                               if (opt == FLG_MTSFILE)
1849                                 {
1850                                   /*
1851                                   ** arg identifies mts files
1852                                   */
1853                                   cstring tmp =  message ("%s%s", arg, MTS_EXTENSION);
1854                                   addLarchPathFile (mtfiles, tmp);
1855                                   cstring_free (tmp);
1856                                   tmp = message ("%s%s", arg, XH_EXTENSION);
1857                                   addXHFile (xfiles, tmp);
1858                                   cstring_free (tmp);
1859                                 }
1860                               else
1861                                 {
1862                                   setStringFlag (opt, cstring_copy (arg));
1863                                 }
1864                             }
1865                         }
1866                       else
1867                         {
1868                           voptgenerror
1869                             (FLG_BADFLAG,
1870                              message
1871                              ("Flag %s must be followed by a string",
1872                               flagcode_unparse (opt)),
1873                              g_currentloc);
1874                         }
1875                     }
1876                   else
1877                     {
1878                       /* no argument */
1879                     }
1880                 }
1881             }
1882         }
1883       else /* its a filename */
1884         {
1885           DPRINTF (("Adding filename: %s", thisarg));
1886           fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1887         }
1888     }
1889   
1890   /*
1891   ** create lists of C and LCL files
1892   */
1893   
1894   if (inCommandLine)
1895     {
1896       cstringSList_elements (fl, current)
1897         {
1898           cstring ext = fileLib_getExtension (current);
1899           
1900           if (cstring_isUndefined (ext))
1901             {
1902               /* no extension --- both C and LCL with default extensions */
1903               
1904               addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1905               addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
1906             }
1907           else if (cstring_equal (ext, XH_EXTENSION))
1908             {
1909               addXHFile (xfiles, current);
1910             }
1911           else if (cstring_equal (ext, PP_EXTENSION))
1912             {
1913               if (!context_getFlag (FLG_NOPP))
1914                 {
1915                   voptgenerror 
1916                     (FLG_FILEEXTENSIONS,
1917                      message ("File extension %s used without +nopp flag (will be processed as C source code): %s", 
1918                               ext, current),
1919                      g_currentloc);
1920                 }
1921               
1922               addFile (cfiles, cstring_copy (current));
1923             }
1924           else if (cstring_equal (ext, LCL_EXTENSION)) 
1925             {
1926               addFile (lclfiles, cstring_copy (current));
1927             }
1928           else if (fileLib_isCExtension (ext))
1929             {
1930               addFile (cfiles, cstring_copy (current));
1931             }
1932           else if (cstring_equal (ext, MTS_EXTENSION))
1933             {
1934               addLarchPathFile (mtfiles, current);
1935             }
1936           else 
1937             {
1938               voptgenerror 
1939                 (FLG_FILEEXTENSIONS,
1940                  message ("Unrecognized file extension: %s (assuming %s is C source code)", 
1941                           current, ext),
1942                  g_currentloc);
1943               
1944               addFile (cfiles, cstring_copy (current));
1945             }
1946         } end_cstringSList_elements;
1947     }
1948   else
1949     {
1950       if (cstringSList_size (fl) != 0)
1951         {
1952           /* Cannot list files in .splintrc files */
1953           voptgenerror (FLG_BADFLAG, 
1954                         message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
1955                                  cstringSList_unparse (fl)),
1956                         g_currentloc);
1957         }
1958     }
1959
1960   cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
1961 }
1962
1963 int flagcode_priority (/*@unused@*/ flagcode code)
1964 {
1965   /*
1966   ** For now, we do a really simple prioritization: all are 1
1967   */
1968
1969   return 1;
1970 }
This page took 0.195307 seconds and 5 git commands to generate.