Two useless/empty bison reductions removed.
[splint-patched.git] / src / flags.c
blobaca4f4490f1297cb462ab28a0c1364e8ebfdeaac
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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.
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
25 ** flags.c
28 # include "splintMacros.nf"
29 # include "basic.h"
30 # include "osd.h"
31 # include "rcfiles.h"
32 # include "lslinit.h"
33 # include "llmain.h"
36 ** from the CC man page:
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).
44 /* needed for string literals literals */
46 typedef struct {
47 flagkind kind;
48 /*@null@*/ /*@observer@*/ const char *name;
49 /*@null@*/ /*@observer@*/ const char *describe;
50 } flagcatinfo;
52 static flagcatinfo categories[] =
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 } ;
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;
131 static /*@observer@*/ cstring argcode_unparse (argcode arg)
133 switch (arg)
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 default: BADBRANCH; return cstring_undefined;
145 typedef struct {
146 flagkind main;
147 flagkind sub;
148 bool isSpecial; /* setting this flag may set other flags (or values) */
149 bool isIdem; /* idempotent - always sets to TRUE */
150 bool isGlobal; /* cannot be set locally (using control comments) */
151 bool isModeFlag; /* set by modes */
152 argcode argtype;
153 /*@observer@*/ const char *flag;
154 flagcode code;
155 /*@observer@*/ /*@null@*/ const char *desc;
156 /*@observer@*/ /*@null@*/ const char *hint;
157 int nreported;
158 int nsuppressed;
159 } fflag;
161 typedef fflag flaglist[];
163 # include "flags.def"
165 /*@iter allFlags (yield observer fflag f); @*/
166 # define allFlags(m_f) \
167 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
168 # define end_allFlags }}
170 static /*@observer@*/ /*@null@*/ const char * mode_names[] =
172 "weak", "standard", "checks", "strict", NULL,
175 /*@iter allModes (yield const char* modename)@*/
176 # define allModes(m_m) \
177 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
178 { /*@observer@*/ /*@null@*/ const char* m_m = mode_names[m_ii]; m_ii++;
180 # define end_allModes }}
182 /*@+enumint@*/
184 static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
185 static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
186 static cstringSList sortedFlags (void) /*@*/ ;
187 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
189 static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
191 # if 0
192 static /*@unused@*/ cstring listModes (void) /*@*/ ;
193 # endif
195 bool flagcode_isSpecialFlag (flagcode f)
197 return (flags[f].isSpecial);
200 bool flagcode_isGlobalFlag (flagcode f)
202 return (flags[f].isGlobal);
205 bool flagcode_isIdemFlag (flagcode f)
207 return (flags[f].isIdem);
210 bool flagcode_isModeFlag (flagcode f)
212 return (flags[f].isModeFlag);
215 bool flagcode_isNameChecksFlag (flagcode f)
217 return (flags[f].main == FK_NAMES);
220 bool flagcode_isHelpFlag (flagcode f)
222 return f == FLG_HELP;
225 bool flagcode_isMessageControlFlag (flagcode f)
228 ** True if opt controls the display of messages.
229 ** These flags must be processed first.
232 return (f == FLG_SHOWSCAN
233 || f == FLG_WARNRC
234 || f == FLG_PARENFILEFORMAT
235 || f == FLG_MESSAGESTREAMSTDERR
236 || f == FLG_MESSAGESTREAMSTDOUT
237 || f == FLG_WARNINGSTREAMSTDERR
238 || f == FLG_WARNINGSTREAMSTDOUT
239 || f == FLG_ERRORSTREAMSTDERR
240 || f == FLG_ERRORSTREAMSTDOUT
241 || f == FLG_MESSAGESTREAM
242 || f == FLG_WARNINGSTREAM
243 || f == FLG_ERRORSTREAM
244 || f == FLG_STREAMOVERWRITE);
248 ** Internal consistency check on the flags.
251 void flags_initMod (void)
253 allFlagCodes (code)
255 /*@+enumint@*/
256 if (flags[code].code != code)
258 fprintf (stderr,
259 "*** ERROR: inconsistent flag %s / %d / %d",
260 flags[code].flag,
261 flags[code].code, code);
263 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
264 cstring_fromChars (flags[code].flag),
265 flags[code].code, code));
267 /*@=enumint@*/
268 } end_allFlagCodes;
271 void
272 summarizeErrors (void)
274 bool hadOne = FALSE;
275 int sumrep = 0;
276 int sumsup = 0;
278 char *buf = mstring_create (128);
280 allFlags (f)
282 if (f.nreported > 0 || f.nsuppressed > 0)
284 int nrep = f.nreported;
285 int nsup = f.nsuppressed;
286 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
288 if (!hadOne)
290 llmsgplain (cstring_makeLiteral
291 ("\nError Type Reported Suppressed\n"
292 "=================== ======== ========="));
293 hadOne = TRUE;
296 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
298 sumrep += nrep;
299 sumsup += nsup;
301 cstring_free (fs);
302 llmsg (cstring_copy (cstring_fromChars (buf)));
304 } end_allFlags;
306 if (hadOne)
308 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
310 llmsglit (" ======== =========");
312 (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
313 cstring_free (ts);
314 llmsgplain (cstring_copy (cstring_fromChars (buf)));
317 sfree (buf);
320 /*@+enumindex@*/
322 void
323 flagcode_recordError (flagcode f)
325 if (f != INVALID_FLAG)
327 if (f == FLG_WARNFLAGS)
329 ; /* don't count these */
331 else
333 flags[f].nreported = flags[f].nreported + 1;
336 else
338 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
342 void
343 flagcode_recordSuppressed (flagcode f)
345 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
347 flags[f].nsuppressed = flags[f].nsuppressed + 1;
351 flagcode_numReported (flagcode f)
353 llassert (f != INVALID_FLAG);
355 return (flags[f].nreported);
358 /*@observer@*/ cstring
359 flagcodeHint (flagcode f)
361 llassert (f != INVALID_FLAG);
363 if (mstring_isDefined (flags[f].hint))
365 return (cstring_fromChars (flags[f].hint));
367 else
369 return (cstring_fromChars (flags[f].desc));
373 static int categorySize (flagkind kind) /*@*/
375 int n = 0;
378 allFlags (f)
380 if (f.main == kind || f.sub == kind)
382 n++;
384 } end_allFlags;
386 return n;
389 flagkind identifyCategory (cstring s)
391 int i;
393 for (i = 0; categories[i].kind != FK_NONE; i++)
395 if (mstring_isDefined (categories[i].name))
397 if (cstring_equalLit (s, categories[i].name))
399 return categories[i].kind;
404 return FK_NONE;
407 static /*@observer@*/ cstring categoryName (flagkind kind)
409 int i;
411 for (i = 0; categories[i].kind != FK_NONE; i++)
413 if (categories[i].kind == kind)
415 return (cstring_fromChars (categories[i].name));
419 return (cstring_makeLiteralTemp ("<No Category>"));
422 static int categoryIndex (flagkind kind)
424 int i;
426 for (i = 0; categories[i].kind != FK_NONE; i++)
428 if (categories[i].kind == kind)
430 return i;
434 return -1;
437 void printCategory (flagkind kind)
439 int index = categoryIndex (kind);
441 llassert (index >= 0);
442 llmsg (message ("%s (%d flags)\n\3%s\n\n",
443 cstring_fromChars (categories[index].name),
444 categorySize (kind),
445 cstring_fromChars (categories[index].describe)));
447 allFlags (f)
449 if (f.main == kind || f.sub == kind)
451 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
452 describeFlagCode (f.code)));
454 } end_allFlags;
457 void
458 listAllCategories (void)
460 int i;
462 for (i = 0; categories[i].kind != FK_NONE; i++)
464 flagkind kind = categories[i].kind ;
466 if (categories[i].describe != NULL)
468 llmsg (message ("%s (%d flags)\n\3%s",
469 categoryName (kind),
470 categorySize (kind),
471 cstring_fromChars (categories[i].describe)));
476 void
477 printAllFlags (bool desc, bool full)
479 if (full)
481 cstringSList fl = sortedFlags ();
483 cstringSList_elements (fl, el)
485 cstring tmp;
486 tmp = cstring_copy(el);
487 llmsg (message ("%q\n\n", describeFlag (tmp)));
488 cstring_free(tmp);
489 } end_cstringSList_elements ;
491 cstringSList_free (fl);
493 else
495 allFlags (f)
497 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
499 if (mstring_isDefined (f.desc))
501 if (desc)
503 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
504 cstring_fromChars (f.desc)));
508 } end_allFlags;
512 void
513 printFlagManual (bool html)
516 ** Prints all flags by category, in order they appear in flags.def
519 flagkind lastCategory = FK_NONE;
521 allFlags (f) {
522 cstring flagname;
523 cstring flagtype = cstring_undefined;
525 if (f.main != lastCategory)
527 if (html)
529 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
531 else
533 llmsg (message ("\n%s\n%s\n",
534 categoryName (f.main),
535 cstring_makeLiteralTemp ("===================================")));
538 lastCategory = f.main;
541 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
543 if (html)
545 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
547 else
549 flagname = cstring_fromCharsNew (f.flag);
552 else
554 if (flagcode_hasString (f.code))
556 if (html)
558 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt>",
559 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
561 else
563 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
566 if (cstring_isDefined (context_getString (f.code)))
568 if (html)
570 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
571 context_getString (f.code));
573 else
575 flagname = message ("%q [%s]", flagname,
576 context_getString (f.code));
580 else if (f.argtype == ARG_CHAR)
582 if (html)
584 flagname = message ("<tt>%s <em>&lt;%s&gt;</em></tt> <font color=\"blue\">[%c]</font>",
585 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
586 (char) context_getValue (f.code));
588 else
590 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
591 (char) context_getValue (f.code));
594 else
596 llassert (f.argtype == ARG_NUMBER);
598 if (html)
600 flagname = message ("<tt>%s <em>&lt;%s&gt;</em> <font color=\"blue\">[%d]</font>",
601 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
602 context_getValue (f.code));
604 else
606 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
607 context_getValue (f.code));
612 if (f.isIdem)
614 if (html)
616 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
618 else
620 flagtype = message("%q<->", flagtype);
624 if (f.isGlobal)
626 if (html)
628 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
630 else
632 flagtype = message ("%q<G>", flagtype);
636 if (f.isSpecial)
638 if (html)
640 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
642 else
644 flagtype = message("%q<S>", flagtype);
648 if (f.isModeFlag)
650 if (html)
652 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
654 else
656 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
659 else /* its a plain flag */
661 if (html)
663 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
664 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
666 else
668 flagtype = message ("%q<P:%s>", flagtype,
669 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
673 llmsg (message ("%s: %s", flagname, flagtype));
675 if (html)
677 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
680 if (mstring_isDefined (f.hint))
682 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
684 else
686 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
689 if (html)
691 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
693 } end_allFlags ;
696 cstring
697 describeMode (cstring mode)
699 cstringSList sflags = sortedFlags ();
700 cstring res = message ("Predefined mode %s sets: ", mode);
702 llassert (flags_isModeName (mode));
704 context_setMode (mode);
706 cstringSList_elements (sflags, flagname)
708 flagcode code = flags_identifyFlag (flagname);
709 fflag currentflag = flags[code];
711 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
713 if (context_getFlag (code))
715 res = message ("%q\n +%s", res, cstring_fromChars (currentflag.flag));
717 else
719 res = message ("%q\n -%s", res, cstring_fromChars (currentflag.flag));
722 } end_cstringSList_elements;
724 cstringSList_free (sflags);
726 res = cstring_appendChar (res, '\n');
727 return (res);
730 cstring
731 describeFlagCode (flagcode flag)
733 cstring ret = cstring_undefined;
734 fflag f;
736 if (flagcode_isInvalid (flag))
738 return (cstring_makeLiteral ("<invalid>"));
741 if (flagcode_isModeName (flag))
743 return (cstring_makeLiteral ("<mode flag>"));
746 context_resetAllFlags ();
748 f = flags[flag];
749 ret = cstring_copy (cstring_fromChars (f.desc));
751 if (f.sub != FK_NONE)
753 ret = message ("%q\nCategories: %s, %s",
754 ret,
755 categoryName (f.main),
756 categoryName (f.sub));
758 else
760 if (f.main != FK_NONE)
762 cstring cname = categoryName (f.main);
764 if (cstring_isDefined (cname))
766 ret = message ("%q\nCategory: %s",
767 ret, cname);
772 if (f.isModeFlag)
774 ret = message ("%q\nMode Settings: %q",
775 ret, getFlagModeSettings (flag));
777 else
779 ret = message ("%q\nDefault Setting: %s",
780 ret,
781 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
784 if (f.isGlobal)
786 ret = message("%q\nSet globally only", ret);
788 else
790 ret = message("%q\nSet locally", ret);
793 switch (f.argtype)
795 case ARG_NONE:
796 case ARG_SPECIAL:
797 break;
798 case ARG_NUMBER:
799 ret = message("%q\nNumeric Argument. Default: %d",
800 ret,
801 context_getValue (flag));
802 break;
803 case ARG_CHAR:
804 ret = message("%q\nCharacter Argument. Default: %h",
805 ret, (char) context_getValue (flag));
806 break;
807 case ARG_STRING:
808 case ARG_FILE:
809 case ARG_PATH:
810 case ARG_DIRECTORY:
812 if (cstring_isDefined (context_getString (flag)))
814 ret = message("%q\n%q argument. Default: %s",
815 ret,
816 cstring_capitalize (argcode_unparse (f.argtype)),
817 context_getString (flag));
819 else
821 ret = message("%q\n%s argument. No default.",
822 ret,
823 cstring_capitalize (argcode_unparse (f.argtype)));
825 break;
829 if (mstring_isDefined (f.hint))
831 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
834 return ret;
837 static cstring getFlagModeSettings (flagcode flag)
839 cstring res = cstring_undefined;
841 allModes (mname)
843 context_setModeNoWarn (cstring_fromChars (mname));
845 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
846 } end_allModes;
848 return res;
851 cstring
852 describeFlag (cstring flagname)
854 cstring oflagname = cstring_copy (flagname);
855 flagcode f = flags_identifyFlag (flagname);
857 if (flagcode_isSkip (f))
859 cstring_free (oflagname);
860 return cstring_undefined;
862 else if (flagcode_isValid (f))
864 if (cstring_equal (flagname, oflagname))
866 cstring_free (oflagname);
867 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
869 else
871 return (message ("%q (standardized name: %s)\n\3%q",
872 oflagname, flagname, describeFlagCode (f)));
875 else
877 if (flags_isModeName (flagname))
879 cstring_free (oflagname);
880 return describeMode (flagname);
882 else
884 return (message ("%q: <invalid flag>", oflagname));
889 static cstringSList
890 sortedFlags (void)
892 cstringSList s = cstringSList_new ();
894 allFlags (f)
896 if (f.desc != NULL)
898 s = cstringSList_add (s, cstring_fromChars (f.flag));
900 } end_allFlags;
902 cstringSList_alphabetize (s);
904 return s;
907 void printAlphaFlags (void)
909 cstringSList fl = sortedFlags ();
911 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
912 cstringSList_free (fl);
915 /*@observer@*/ cstring
916 flagcode_unparse (flagcode code)
918 if (code == INVALID_FLAG)
920 return cstring_makeLiteralTemp ("<invalid flag>");
923 return cstring_fromChars (flags[code].flag);
927 ** Transforms a flag into its cannonical form.
929 ** The following transformations are made:
931 ** function -> fcn
932 ** variable -> var
933 ** constant -> const
934 ** iterator -> iter
935 ** parameter -> param
936 ** unrecognized -> unrecog
937 ** qualifier -> qual
938 ** declaration -> decl
939 ** globals -> globs
940 ** modifies -> mods
941 ** modify -> mod
942 ** pointer -> ptr
943 ** implies -> imp
944 ** implicit -> imp
945 ** implied -> imp
946 ** unconstrained -> uncon
947 ** unconst -> uncon
948 ** memory -> mem
949 ** length -> len
950 ** return -> ret
951 ** system -> sys
954 static /*@only@*/ cstring
955 canonicalizeFlag (cstring s)
957 int i = 0;
958 cstring res = cstring_copy (s);
959 static /*@observer@*/ /*@null@*/ const char* transform[] =
961 "function", "fcn",
962 "variable", "var",
963 "constant", "const",
964 "iterator", "iter",
965 "parameter", "param",
966 "unrecognized", "unrecog",
967 "qualifier", "qual",
968 "declaration", "decl",
969 "globals", "globs",
970 "modifies", "mods",
971 "modify", "mod",
972 "pointer", "ptr",
973 "implies", "imp",
974 "implicit", "imp",
975 "implied", "imp",
976 "unconstrained", "uncon",
977 "unconst", "uncon",
978 "memory", "mem",
979 "length", "len",
980 "return", "ret",
981 "system", "sys",
982 NULL
984 const char *current;
986 while ((current = transform[i]) != NULL)
988 if (cstring_containsLit (res, current))
990 cstring_replaceLit (res, current, transform[i+1]);
992 i += 2;
995 /* remove whitespace, -'s, and _'s */
996 cstring_stripChars (res, " -_");
997 return res;
1000 flagcode
1001 flags_identifyFlag (cstring s)
1003 return flags_identifyFlagAux (s, FALSE);
1006 flagcode
1007 flags_identifyFlagQuiet (cstring s)
1009 return flags_identifyFlagAux (s, TRUE);
1012 static flagcode
1013 flags_identifyFlagAux (cstring s, bool quiet)
1015 cstring cflag;
1016 flagcode res;
1018 if (cstring_length (s) == 0) {
1019 /* evs 2000-06-25: A malformed flag. */
1020 return INVALID_FLAG;
1023 if (cstring_firstChar (s) == 'I')
1025 return FLG_INCLUDEPATH; /* no space required after -I */
1028 if (cstring_firstChar (s) == 'S')
1030 return FLG_SPECPATH; /* no space required after -S */
1033 if (cstring_firstChar (s) == 'D')
1035 return FLG_DEFINE; /* no space required after -D */
1038 if (cstring_firstChar (s) == 'U')
1040 return FLG_UNDEFINE; /* no space required after -D */
1043 cflag = canonicalizeFlag (s);
1044 res = INVALID_FLAG;
1046 allFlags (f)
1048 if (cstring_equal (cstring_fromChars (f.flag), cflag))
1050 res = f.code;
1051 break;
1053 } end_allFlags;
1055 if (res == INVALID_FLAG)
1058 ** Synonyms
1061 if (cstring_equalLit (cflag, "pred"))
1063 res = FLG_PREDBOOL;
1065 else if (cstring_equalLit (cflag, "modobserverstrict"))
1067 res = FLG_MODOBSERVERUNCON;
1069 else if (cstring_equalLit (cflag, "czechnames"))
1071 res = FLG_CZECH;
1073 else if (cstring_equalLit (cflag, "slovaknames"))
1075 res = FLG_SLOVAK;
1077 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1079 res = FLG_CZECHOSLOVAK;
1081 else if (cstring_equalLit (cflag, "globunspec")
1082 || cstring_equalLit (cflag, "globuncon"))
1084 res = FLG_GLOBUNSPEC;
1086 else if (cstring_equalLit (cflag, "modglobsunspec")
1087 || cstring_equalLit (cflag, "modglobsuncon")
1088 || cstring_equalLit (cflag, "modglobsnomods"))
1090 res = FLG_MODGLOBSUNSPEC;
1092 else if (cstring_equalLit (cflag, "export"))
1094 res = FLG_EXPORTANY;
1096 else if (cstring_equalLit (cflag, "macrospec"))
1098 res = FLG_MACRODECL;
1100 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1102 res = FLG_ISORESERVEDLOCAL;
1104 else if (cstring_equalLit (cflag, "warnposix"))
1106 res = FLG_WARNPOSIX;
1108 else if (cstring_equalLit (cflag, "defuse"))
1110 res = FLG_USEDEF;
1112 else if (cstring_equalLit (cflag, "macroundef"))
1114 res = FLG_MACROUNDEF;
1116 else if (cstring_equalLit (cflag, "showcol"))
1118 res = FLG_SHOWCOL;
1120 else if (cstring_equalLit (cflag, "intbool"))
1122 res = FLG_BOOLINT;
1124 else if (cstring_equalLit (cflag, "intchar"))
1126 res = FLG_CHARINT;
1128 else if (cstring_equalLit (cflag, "intenum"))
1130 res = FLG_ENUMINT;
1132 else if (cstring_equalLit (cflag, "intlong"))
1134 res = FLG_LONGINT;
1136 else if (cstring_equalLit (cflag, "intshort"))
1138 res = FLG_SHORTINT;
1141 ** Backwards compatibility for our American friends...
1144 else if (cstring_equalLit (cflag, "ansilib"))
1146 res = FLG_ANSILIB;
1148 else if (cstring_equalLit (cflag, "ansistrictlib"))
1150 res = FLG_STRICTLIB;
1152 else if (cstring_equalLit (cflag, "skipansiheaders"))
1154 res = FLG_SKIPISOHEADERS;
1156 else if (cstring_equalLit (cflag, "ansireserved"))
1158 res = FLG_ISORESERVED;
1160 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1162 res = FLG_ISORESERVEDLOCAL;
1166 ** Obsolete Flags
1169 else if (cstring_equalLit (cflag, "accessunspec"))
1171 if (!quiet)
1173 llerror_flagWarning
1174 (cstring_makeLiteral
1175 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1176 "accessfunction to provide more precise control of accessibility "
1177 "of representations. For more information, "
1178 "see splint -help accessmodule"));
1181 res = SKIP_FLAG;
1183 else if (cstring_equalLit (cflag, "ansilimits"))
1185 llerror_flagWarning
1186 (cstring_makeLiteral
1187 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1188 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1189 "standard or the typically higher limits prescribed by ISO C99."));
1191 res = SKIP_FLAG;
1193 else if (cstring_equalLit (cflag, "staticmods"))
1195 if (!quiet)
1197 llerror_flagWarning
1198 (cstring_makeLiteral
1199 ("staticmods flag is obsolete. You probably "
1200 "want impcheckmodstatics. For more information, "
1201 "see splint -help impcheckmodstatics"));
1204 res = SKIP_FLAG;
1206 else if (cstring_equalLit (cflag, "bool"))
1208 if (!quiet)
1210 llerror_flagWarning
1211 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1212 "made sense in the first place."));
1215 res = SKIP_FLAG;
1217 else if (cstring_equalLit (cflag, "shiftsigned"))
1219 if (!quiet)
1221 llerror_flagWarning
1222 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1223 "want bitwisesigned, shiftnegative or shiftimplementation."));
1226 res = SKIP_FLAG;
1228 else if (cstring_equalLit (cflag, "ansi"))
1230 if (!quiet)
1232 llerror_flagWarning
1233 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1234 "want noparams and/or oldstyle."));
1237 res = SKIP_FLAG;
1239 else if (cstring_equalLit (cflag, "usestderr"))
1241 if (!quiet)
1243 llerror_flagWarning
1244 (cstring_makeLiteral
1245 ("usestderr flag is obsolete. This has been replaced "
1246 "by more precise flags for controlling the warning, "
1247 "status message and fatal error streams independently: message-stream-stdout, "
1248 "message-stream-stderr, message-stream <file>, "
1249 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
1250 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
1253 res = SKIP_FLAG;
1256 else if (cstring_equalLit (cflag, "stdio"))
1258 if (!quiet)
1260 llerror_flagWarning
1261 (cstring_makeLiteral
1262 ("stdio flag is obsolete. You may "
1263 "want strictlib or one of the gloabls "
1264 "checking flags. For more information, "
1265 "see splint -help strictlib or splint -help flags globals"));
1268 res = SKIP_FLAG;
1270 else if (flags_isModeName (cflag))
1272 res = MODENAME_FLAG;
1274 else
1276 res = INVALID_FLAG;
1280 cstring_free (cflag);
1281 return res;
1284 void flags_setValueFlag (flagcode opt, cstring arg)
1286 switch (opt)
1288 case FLG_EXPECT:
1289 case FLG_LCLEXPECT:
1290 case FLG_LIMIT:
1291 case FLG_LINELEN:
1292 case FLG_INDENTSPACES:
1293 case FLG_LOCINDENTSPACES:
1294 case FLG_BUGSLIMIT:
1295 case FLG_EXTERNALNAMELEN:
1296 case FLG_INTERNALNAMELEN:
1297 case FLG_CONTROLNESTDEPTH:
1298 case FLG_STRINGLITERALLEN:
1299 case FLG_NUMSTRUCTFIELDS:
1300 case FLG_NUMENUMMEMBERS:
1301 case FLG_INCLUDENEST:
1303 int val = cstring_toPosInt (arg);
1305 if (val < 0)
1307 llerror
1308 (FLG_BADFLAG,
1309 message
1310 ("Flag %s must be followed by a positive number number. "
1311 "Followed by %s",
1312 flagcode_unparse (opt), arg));
1314 else
1316 context_setValueAndFlag (opt, val);
1319 break;
1320 case FLG_COMMENTCHAR:
1322 if (cstring_length (arg) != 1)
1324 llfatalerrorLoc
1325 (message
1326 ("Flag %s should be followed by a single character. Followed by %s",
1327 flagcode_unparse (opt), arg));
1329 else
1331 context_setCommentMarkerChar (cstring_firstChar (arg));
1334 break;
1335 BADDEFAULT;
1339 void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1341 switch (opt)
1343 case FLG_TMPDIR:
1345 if (cstring_lastChar (arg) == CONNECTCHAR)
1347 context_setString (opt, arg);
1349 else
1351 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1353 break;
1355 default:
1357 context_setString (opt, arg);
1358 break;
1363 cstring
1364 describeModes (void)
1366 cstring s = cstring_makeLiteral ("Flag ");
1367 cstringSList sflags = sortedFlags ();
1369 allModes (modename)
1371 s = message ("%q%9s", s, cstring_fromChars (modename));
1372 } end_allModes;
1374 s = message ("%q\n", s);
1376 cstringSList_elements (sflags, flagname)
1378 flagcode code = flags_identifyFlag (flagname);
1379 fflag currentflag = flags[code];
1381 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1383 s = message ("%q\n%27s", s,
1384 cstring_fromChars (currentflag.flag));
1386 allModes (modename)
1388 context_setMode (cstring_fromChars (modename));
1390 if (context_getFlag (code))
1392 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1394 else
1396 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1399 context_resetModeFlags ();
1400 } end_allModes;
1402 } end_cstringSList_elements;
1404 cstringSList_free (sflags);
1406 s = cstring_appendChar (s, '\n');
1408 return (s);
1411 # if 0
1412 static /*@unused@*/ cstring
1413 listModes (void)
1415 cstring s = cstring_makeLiteral ("\t");
1416 int i = 0;
1418 allModes (modename)
1420 if (i != 0 && (i % 4 == 0))
1422 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1424 else
1426 s = message ("%q%15s", s, cstring_fromChars (modename));
1428 i++;
1429 } end_allModes;
1431 return s;
1433 # endif
1435 bool
1436 flags_isModeName (cstring s)
1438 allModes (modename)
1440 if (mstring_isDefined (modename))
1442 if (cstring_equalLit (s, modename))
1444 return TRUE;
1447 } end_allModes;
1449 return FALSE;
1452 extern bool flagcode_hasArgument (flagcode f)
1454 return (flags[f].argtype != ARG_NONE);
1457 extern bool flagcode_hasNumber (flagcode f)
1459 return (flags[f].argtype == ARG_NUMBER);
1462 extern bool flagcode_hasChar (flagcode f)
1464 return (flags[f].argtype == ARG_CHAR);
1467 extern bool flagcode_hasString (flagcode f)
1469 return (flags[f].argtype == ARG_STRING
1470 || flags[f].argtype == ARG_FILE
1471 || flags[f].argtype == ARG_DIRECTORY
1472 || flags[f].argtype == ARG_PATH);
1475 extern int flagcode_valueIndex (flagcode f)
1477 /*@unchecked@*/ static bool initialized = FALSE;
1478 int i;
1479 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1481 if (!initialized)
1483 int nv = 0;
1485 allFlagCodes (code)
1487 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1489 llassert (nv < NUMVALUEFLAGS);
1490 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1491 valueFlags[nv] = code;
1492 nv++;
1494 } end_allFlagCodes;
1496 llassertprint (nv == NUMVALUEFLAGS,
1497 ("Number of value flags: %d (expected %d)",
1498 nv, (int) NUMVALUEFLAGS));
1499 initialized = TRUE;
1502 for (i = 0; i < NUMVALUEFLAGS; i++)
1504 /* static valueFlags must be defined */
1505 /*@-usedef@*/
1506 if (f == valueFlags[i]) /*@=usedef@*/
1508 return i;
1512 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1513 exit (EXIT_FAILURE);
1514 /* Cannot do this...might call recursively...
1515 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1516 BADEXIT;
1520 extern int flagcode_stringIndex (flagcode f)
1522 /*@unchecked@*/ static bool initialized = FALSE;
1523 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1524 int i;
1527 if (!initialized)
1529 int nv = 0;
1531 allFlagCodes (code)
1533 if (flagcode_hasString (code))
1535 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1536 stringFlags[nv] = code;
1537 nv++;
1539 } end_allFlagCodes;
1541 llassertprint (nv == NUMSTRINGFLAGS,
1542 ("number of string flags: %d (expected %d)",
1543 nv, NUMSTRINGFLAGS));
1544 initialized = TRUE;
1547 for (i = 0; i < NUMSTRINGFLAGS; i++)
1549 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1551 return i;
1555 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1556 BADEXIT;
1559 bool flagcode_isNamePrefixFlag (flagcode f)
1561 switch (f)
1563 case FLG_MACROVARPREFIX:
1564 case FLG_TAGPREFIX:
1565 case FLG_ENUMPREFIX:
1566 case FLG_FILESTATICPREFIX:
1567 case FLG_GLOBPREFIX:
1568 case FLG_TYPEPREFIX:
1569 case FLG_EXTERNALPREFIX:
1570 case FLG_LOCALPREFIX:
1571 case FLG_UNCHECKEDMACROPREFIX:
1572 case FLG_CONSTPREFIX:
1573 case FLG_ITERPREFIX:
1574 case FLG_DECLPARAMPREFIX:
1575 return TRUE;
1576 default:
1577 return FALSE;
1581 static cstring findLarchPathFile (/*@temp@*/ cstring s)
1583 cstring pathName;
1584 filestatus status;
1586 status = osd_getPath (context_getLarchPath (), s, &pathName);
1588 if (status == OSD_FILEFOUND)
1590 return pathName;
1592 else if (status == OSD_FILENOTFOUND)
1594 showHerald ();
1595 lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s));
1597 else if (status == OSD_PATHTOOLONG)
1599 /* Directory and filename are too long. Report error. */
1600 llbuglit ("soure_getPath: Filename plus directory from search path too long");
1602 else
1604 BADBRANCH;
1607 return cstring_undefined;
1610 static void addFile (fileIdList files, /*@temp@*/ cstring pathName, fileType typ)
1612 if (fileTable_exists (context_fileTable (), pathName))
1614 showHerald ();
1615 lldiagmsg (message ("File listed multiple times: %s", pathName));
1617 else
1619 fileIdList_add (files, fileTable_addFile (context_fileTable (), typ, pathName));
1623 static bool
1624 strIsQuoteOpen (const char * arg)
1626 register const char * s;
1627 bool escape, quoted;
1629 llassert (arg != NULL);
1631 s = arg;
1632 escape = FALSE;
1633 quoted = FALSE;
1634 while (*s != '\0')
1636 if (!escape)
1638 if (*s == '\\')
1640 escape = TRUE;
1642 else if (*s == '\"')
1644 quoted = !quoted;
1647 else
1649 escape = FALSE;
1651 ++s;
1654 return quoted;
1657 void
1658 flags_processFlags (bool inCommandLine,
1659 fileIdList cfiles,
1660 fileIdList lclfiles,
1661 fileIdList mtfiles,
1662 cstringList *cppArgs,
1663 int argc, char **argv)
1665 int i;
1666 cstringSList fl = cstringSList_undefined;
1668 for (i = 0; i < argc; i++)
1670 char *thisarg;
1672 llassert (argv != NULL);
1673 thisarg = argv[i];
1675 DPRINTF (("process thisarg [%d]: %s", i, thisarg));
1677 if (*thisarg == '-' || *thisarg == '+')
1679 bool set = (*thisarg == '+');
1680 cstring flagname;
1681 flagcode opt;
1683 if (*thisarg == '-' && *(thisarg + 1) == '-') { /* allow -- before flags */
1684 flagname = cstring_fromChars (thisarg + 2);
1685 } else {
1686 flagname = cstring_fromChars (thisarg + 1);
1689 opt = flags_identifyFlag (flagname);
1690 DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt)));
1692 if (flagcode_isInvalid (opt))
1694 DPRINTF (("Error!"));
1695 voptgenerror (FLG_BADFLAG,
1696 message ("Unrecognized option: %s",
1697 cstring_fromChars (thisarg)),
1698 g_currentloc);
1700 else if (flagcode_isHelpFlag (opt))
1702 if (inCommandLine)
1704 voptgenerror (FLG_BADFLAG,
1705 message ("Help flag must be first on the command line: %s",
1706 cstring_fromChars (thisarg)),
1707 g_currentloc);
1709 else
1711 voptgenerror (FLG_BADFLAG,
1712 message ("Help flags can only be used on the command line: %s",
1713 cstring_fromChars (thisarg)),
1714 g_currentloc);
1717 else if (flagcode_isCpp (opt)) /* preprocessor flag: -D, -U or -I */
1719 if (*thisarg == '+') /* reject +D, +U or +I */
1721 voptgenerror
1722 (FLG_BADFLAG,
1723 message
1724 ("Unrecognized option +%c (did you meant -%c?)", *flagname, *flagname),
1725 g_currentloc);
1727 else if (*(thisarg+1) == '-') /* reject --D, --U or --I */
1729 voptgenerror
1730 (FLG_BADFLAG,
1731 message
1732 ("Unrecognized option --%c (did you meant -%c?)", *flagname, *flagname),
1733 g_currentloc);
1735 else if (*(thisarg + 2) == '\0' && flagcode_isCppMacro (opt))
1737 voptgenerror
1738 (FLG_BADFLAG,
1739 message
1740 ("Flag -%c requires a preprocessor macro merged with it (no separate arguments)", *flagname),
1741 g_currentloc);
1743 else if (*(thisarg + 2) == '\0' && i+1 >= argc) /* -I allows spaces between itself and argument */
1745 llassert (opt == FLG_INCLUDEPATH);
1746 voptgenerror
1747 (FLG_BADFLAG,
1748 message ("Flag -I must be followed by a directory name"),
1749 g_currentloc);
1751 else
1753 const char *quotcheck;
1754 if (*(thisarg + 2) != '\0') /* argument is merged with flag */
1756 quotcheck = thisarg;
1758 else
1760 ++i;
1761 llassert (opt == FLG_INCLUDEPATH && *(thisarg + 2) == '\0' && i < argc);
1762 quotcheck = argv[i];
1765 if (strIsQuoteOpen (quotcheck))
1767 voptgenerror (FLG_BADFLAG,
1768 message ("Unclosed quote in flag: %s", quotcheck),
1769 g_currentloc);
1771 else
1773 cstring newCppArg = cstring_undefined;
1775 if (*(thisarg + 2) != '\0') /* argument is merged with flag */
1777 newCppArg = cstring_fromCharsNew (thisarg + 1);
1779 else /* use next argument */
1781 newCppArg = cstring_prependChar ('I', cstring_fromChars (argv[i]));
1784 *cppArgs = cstringList_add (*cppArgs, newCppArg);
1788 else if (opt == FLG_SPECPATH)
1790 char* dir = thisarg + 2; /* skip over -S */
1792 if (*dir == '\0') {
1793 DPRINTF (("space after directory: "));
1794 if (++i < argc) {
1795 DPRINTF (("use next argument, argv[%d] : %s", i, argv[i]));
1796 dir = argv[i];
1797 } else {
1798 voptgenerror
1799 (FLG_BADFLAG,
1800 message
1801 ("Flag %s must be followed by a directory name",
1802 flagcode_unparse (opt)),
1803 g_currentloc);
1804 /* TODO: do we really want to add an empty path? */
1807 DPRINTF (("Got directory: [%s]", dir));
1809 /*@-mustfree@*/
1810 /* TODO: why aren't we freeing the intermediary g_localSpecPath? */
1811 g_localSpecPath = cstring_toCharsSafe
1812 (osd_pathListConcat (g_localSpecPath, dir));
1813 /*@=mustfree@*/
1815 else if (flagcode_isModeName (opt))
1817 context_setMode (flagname);
1819 else if (inCommandLine && flagcode_isMessageControlFlag (opt))
1822 ** Processed on first pass
1825 if (flagcode_hasArgument (opt))
1827 ++i;
1830 else
1833 ** A normal control flag
1836 context_userSetFlag (opt, set);
1838 if (flagcode_hasArgument (opt))
1840 if (flagcode_hasNumber (opt))
1842 if (++i < argc)
1844 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1846 else
1848 voptgenerror
1849 (FLG_BADFLAG,
1850 message
1851 ("Flag %s must be followed by a number",
1852 flagcode_unparse (opt)),
1853 g_currentloc);
1856 else if (flagcode_hasChar (opt))
1858 if (++i < argc)
1860 flags_setValueFlag (opt, cstring_fromCharsNew (argv[i]));
1862 else
1864 voptgenerror
1865 (FLG_BADFLAG,
1866 message
1867 ("Flag %s must be followed by a character",
1868 flagcode_unparse (opt)),
1869 g_currentloc);
1872 else if (flagcode_hasString (opt)
1873 || opt == FLG_INIT || opt == FLG_OPTF)
1875 if (++i < argc)
1877 /*drl 10/21/2002
1878 Changed this because arg can be freed when it's passed to
1879 lslinit_setInitFile and freeing argv[i] causes a seg fault
1881 cstring arg = cstring_fromCharsNew (argv[i]);
1883 /* FIXME: memory leak; for opt == FLG_INIT,
1884 * inputStream_create() will take ownership of arg;
1885 * for the rest, the code above just introduced a leak. */
1887 if (opt == FLG_OPTF)
1889 if (inCommandLine)
1891 ; /* -f already processed */
1893 else
1895 (void) rcfiles_read (arg, cppArgs, TRUE);
1898 else if (opt == FLG_INIT)
1900 lslinit_setInitFile (inputStream_create
1901 (arg,
1902 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1903 FALSE));
1904 break;
1906 else
1908 DPRINTF (("String flag: %s / %s",
1909 flagcode_unparse (opt), arg));
1910 if (opt == FLG_MTSFILE)
1913 ** arg identifies mts files
1915 cstring tmp;
1916 cstring pathName;
1918 tmp = cstring_concat (arg, MTS_EXTENSION);
1919 pathName = findLarchPathFile (tmp);
1920 cstring_free (tmp);
1921 if (cstring_isDefined (pathName))
1922 addFile (mtfiles, pathName, FILE_METASTATE);
1923 cstring_free (pathName);
1925 tmp = cstring_concat (arg, XH_EXTENSION);
1926 pathName = findLarchPathFile (tmp);
1927 cstring_free (tmp);
1928 if (cstring_isDefined (pathName))
1929 addFile (cfiles, pathName, FILE_XH);
1930 cstring_free (pathName);
1932 else
1934 flags_setStringFlag (opt, cstring_copy (arg));
1938 else
1940 voptgenerror
1941 (FLG_BADFLAG,
1942 message
1943 ("Flag %s must be followed by a string",
1944 flagcode_unparse (opt)),
1945 g_currentloc);
1948 else
1950 /* no argument */
1955 else /* its a filename */
1957 DPRINTF (("Adding filename: %s", thisarg));
1958 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1963 ** create lists of C and LCL files
1966 if (inCommandLine)
1968 cstringSList_elements (fl, current)
1970 cstring ext = fileLib_getExtension (current);
1972 if (cstring_isUndefined (ext))
1974 /* no extension --- both C and LCL with default extensions */
1975 cstring pathName;
1977 pathName = cstring_concat (current, C_EXTENSION);
1978 addFile (cfiles, pathName, FILE_NORMAL);
1979 cstring_free (pathName);
1981 pathName = cstring_concat (current, LCL_EXTENSION);
1982 addFile (lclfiles, pathName, FILE_LCL);
1983 cstring_free (pathName);
1985 else if (cstring_equal (ext, PP_EXTENSION))
1987 if (!context_getFlag (FLG_NOPP))
1989 voptgenerror
1990 (FLG_FILEEXTENSIONS,
1991 message ("File extension %s used without +nopp flag (will be processed as C source code): %s",
1992 ext, current),
1993 g_currentloc);
1995 addFile (cfiles, current, FILE_NORMAL);
1997 else
1999 addFile (cfiles, current, FILE_PP);
2002 else if (cstring_equal (ext, LCL_EXTENSION))
2004 addFile (lclfiles, current, FILE_LCL);
2006 else if (cstring_equal (ext, MTS_EXTENSION))
2008 cstring pathName;
2009 pathName = findLarchPathFile (current);
2010 if (cstring_isDefined (pathName))
2011 addFile (mtfiles, pathName, FILE_METASTATE);
2012 cstring_free (pathName);
2014 /* fileLib_isCExtension(XH_EXTENSION) is true */
2015 else if (cstring_equal (ext, XH_EXTENSION))
2017 cstring pathName;
2018 pathName = findLarchPathFile (current);
2019 if (cstring_isDefined (pathName))
2020 addFile (cfiles, pathName, FILE_XH);
2021 cstring_free (pathName);
2023 else if (fileLib_isCExtension (ext))
2025 addFile (cfiles, current, FILE_NORMAL);
2027 else
2029 voptgenerror
2030 (FLG_FILEEXTENSIONS,
2031 message ("Unrecognized file extension: %s (assuming %s is C source code)",
2032 current, ext),
2033 g_currentloc);
2035 addFile (cfiles, current, FILE_NORMAL);
2037 } end_cstringSList_elements;
2039 else
2041 if (cstringSList_size (fl) != 0)
2043 /* Cannot list files in .splintrc files */
2044 voptgenerror (FLG_BADFLAG,
2045 message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
2046 cstringSList_unparse (fl)),
2047 g_currentloc);
2051 cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */
2054 int flagcode_priority (/*@unused@*/ flagcode code)
2057 ** For now, we do a really simple prioritization: all are 1
2060 return 1;