2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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
28 # include "splintMacros.nf"
33 ** from the CC man page:
35 ** -Idir Search for #include files whose names do not begin with a
36 ** slash (/) in the following order: (1) in the directory of
37 ** the dir argument, (2) in the directories specified by -I
38 ** options, (3) in the standard directory (/usr/include).
41 /* needed for string literals literals */
45 /*@null@*/ /*@observer@*/ char *name;
46 /*@null@*/ /*@observer@*/ char *describe;
49 static flagcatinfo categories[] =
51 { FK_ABSTRACT, "abstract", "abstraction violations, representation access" } ,
52 { FK_ALIAS, "aliasing", "unexpected or dangerous aliasing" } ,
53 { FK_USE, "alluse", "all declarations are used" } ,
54 { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } ,
55 { FK_ARRAY, "arrays", "special checking involving arrays" } ,
56 { FK_BOOL, "booleans", "checking and naming of boolean types" } ,
57 { FK_COMMENTS, "comments", "warnings about (normal) comments" } ,
58 { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } ,
59 { FK_COMPLETE, "complete", "completely defined, used, or specified system" } ,
60 { FK_CONTROL, "controlflow", "suspicious control structures" } ,
61 { FK_DEBUG, "debug", "flags for debugging splint" } ,
62 { FK_DECL, "declarations", "consistency of declarations" } ,
63 { FK_DEF, "definition", "undefined storage errors" } ,
64 { FK_DIRECT, "directories", "set directores" } ,
65 { FK_DISPLAY, "display", "control what is displayed" } ,
66 { FK_EFFECT, "effect", "statements with no effects" } ,
67 { FK_ERRORS, "errors", "control expected errors, summary reporting" } ,
68 { FK_EXPORT, "export", "control what may be exported" } ,
69 { FK_EXPOSURE, "exposure", "representation exposure" } ,
70 { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" },
71 { FK_FILES, "files", "control system files" } ,
72 { FK_FORMAT, "format", "control format of warning messages" } ,
73 { FK_GLOBALS, "globals", "use of global and file static variables" },
74 { FK_HEADERS, "headers", "control inclusion and generation of header files" },
75 { FK_HELP, "help", "on-line help" },
76 { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" },
77 { FK_HINTS, "hints", "control display of warning hints" },
78 { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" },
79 { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } ,
80 { FK_INIT, "initializations", "initialization files" } ,
81 { FK_ITER, "iterators", "checking iterator definitions and uses" } ,
82 { FK_LEAK, "leaks", "memory leaks" } ,
83 { FK_LIBS, "libraries", "loading and dumping of user and standard libraries" } ,
84 { FK_LIMITS, "limits", "violations of set limits" } ,
85 { FK_MACROS, "macros", "expansion, definition and use of macros" },
86 { FK_MEMORY, "memory", "memory management" } ,
87 { FK_MODIFIES, "modification", "modification errors" } ,
88 { FK_NAMES, "names", "naming conventions and limits" } ,
89 { FK_NULL, "null", "misuses of null pointers" } ,
90 { FK_NUMBERS, "numbers", "control type-checking of numeric types" } ,
91 { FK_OPS, "operations", "checking of primitive operations" } ,
92 { FK_PARAMS, "parameters", "function and macro parameters" } ,
93 { FK_SPEED, "performance", "speeding up checking" } ,
94 { FK_POINTER, "pointers", "pointers" } ,
95 { FK_PRED, "predicates", "condition test expressions" } ,
96 { FK_PREFIX, "prefixes", "set naming prefixes and control checking" } ,
97 { FK_PREPROC, "preproc", "defines and undefines for the preprocessor" } ,
98 { FK_PROTOS, "prototypes", "function prototypes" } ,
99 { FK_DEAD, "released", "using storage that has been deallocated" } ,
100 { FK_IGNORERET, "returnvals", "ignored return values" },
101 { FK_SECURITY, "security", "possible security vulnerability" },
102 { FK_SPEC, "specifications", "checks involving .lcl specifications" } ,
103 { FK_SUPPRESS, "suppress", "local and global suppression of messages" } ,
104 { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } ,
105 { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } ,
106 { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } ,
107 { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } ,
108 { FK_WARNUSE, "warnuse", "use of possibly problematic function" } ,
109 { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } ,
110 { FK_SYNTAX, NULL, NULL } ,
111 { FK_TYPE, NULL, NULL } ,
112 { FK_SECRET, NULL, NULL } ,
113 { FK_OBSOLETE, NULL, NULL } ,
114 { FK_NONE, NULL, NULL } /* must be last */
119 ARG_NUMBER, /* number */
121 ARG_STRING, /* string */
122 ARG_FILE, /* filename (also a string) */
123 ARG_DIRECTORY, /* directory (also a string) */
128 static /*@observer@*/ cstring argcode_unparse (argcode arg)
132 case ARG_STRING: return cstring_makeLiteralTemp ("string");
133 case ARG_FILE: return cstring_makeLiteralTemp ("filename");
134 case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory");
135 case ARG_PATH: return cstring_makeLiteralTemp ("path");
136 case ARG_NUMBER: return cstring_makeLiteralTemp ("number");
137 case ARG_CHAR: return cstring_makeLiteralTemp ("character");
144 /* Make Microsoft VC++ happy */
145 # pragma warning (disable:4715)
152 bool isSpecial; /* setting this flag may set other flags (or values) */
153 bool isIdem; /* idempotent - always sets to TRUE */
154 bool isGlobal; /* cannot be set locally (using control comments) */
155 bool isModeFlag; /* set by modes */
157 /*@observer@*/ char *flag;
159 /*@observer@*/ /*@null@*/ char *desc;
165 typedef fflag flaglist[];
167 # include "flags.def"
169 /*@iter allFlags (yield observer fflag f); @*/
170 # define allFlags(m_f) \
171 { /*@+enumint@*/ flagcode m_i; for (m_i = 0; m_i < NUMFLAGS; m_i++) { fflag m_f = flags[m_i]; /*@=enumint@*/
172 # define end_allFlags }}
174 static bn_mstring mode_names[] =
176 "weak", "standard", "checks", "strict", NULL,
179 /*@iter allModes (yield bn_mstring modename)@*/
180 # define allModes(m_m) \
181 { int m_ii = 0; while (mstring_isDefined (mode_names[m_ii])) \
182 { bn_mstring m_m = mode_names[m_ii]; m_ii++;
184 # define end_allModes }}
188 static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ;
189 static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
190 static cstringSList sortedFlags (void) /*@*/ ;
191 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
193 static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_msgstream@*/ ;
196 static /*@unused@*/ cstring listModes (void) /*@*/ ;
199 bool flagcode_isSpecialFlag (flagcode f)
201 return (flags[f].isSpecial);
204 bool flagcode_isGlobalFlag (flagcode f)
206 return (flags[f].isGlobal);
209 bool flagcode_isIdemFlag (flagcode f)
211 return (flags[f].isIdem);
214 bool flagcode_isModeFlag (flagcode f)
216 return (flags[f].isModeFlag);
219 bool flagcode_isNameChecksFlag (flagcode f)
221 return (flags[f].main == FK_NAMES);
225 ** Internal consistency check on the flags.
228 void flags_initMod ()
233 if (flags[code].code != code)
236 "*** ERROR: inconsistent flag %s / %d / %d",
238 flags[code].code, code);
240 llbug (message ("*** ERROR: inconsistent flag %s / %d / %d",
241 cstring_fromChars (flags[code].flag),
242 flags[code].code, code));
255 char *buf = mstring_create (128);
259 if (f.nreported > 0 || f.nsuppressed > 0)
261 int nrep = f.nreported;
262 int nsup = f.nsuppressed;
263 cstring fs = cstring_fill (cstring_fromChars (f.flag), 23);
267 llmsgplain (cstring_makeLiteral
268 ("\nError Type Reported Suppressed\n"
269 "=================== ======== ========="));
273 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup);
279 llmsg (cstring_copy (cstring_fromChars (buf)));
285 cstring ts = cstring_fill (cstring_makeLiteralTemp ("Total"), 23);
287 llmsglit (" ======== =========");
289 sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup);
291 llmsgplain (cstring_copy (cstring_fromChars (buf)));
300 flagcode_recordError (flagcode f)
302 if (f != INVALID_FLAG)
304 if (f == FLG_WARNFLAGS)
306 ; /* don't count these */
312 flags[f].nreported = flags[f].nreported + 1;
317 llcontbug (message ("flagcode_recordError: invalid flag: %d", (int) f));
322 flagcode_recordSuppressed (flagcode f)
324 llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f)));
327 /*drl bee: ec*/ flags[f].nsuppressed = flags[f].nsuppressed + 1;
331 flagcode_numReported (flagcode f)
333 llassert (f != INVALID_FLAG);
335 return (flags[f].nreported);
338 /*@observer@*/ cstring
339 flagcodeHint (flagcode f)
341 llassert (f != INVALID_FLAG);
344 if (mstring_isDefined (flags[f].hint))
346 return (cstring_fromChars (flags[f].hint));
350 return (cstring_fromChars (flags[f].desc));
354 static int categorySize (flagkind kind) /*@*/
361 if (f.main == kind || f.sub == kind)
370 flagkind identifyCategory (cstring s)
374 for (i = 0; categories[i].kind != FK_NONE; i++)
377 if (mstring_isDefined (categories[i].name))
379 if (cstring_equalLit (s, categories[i].name))
381 return categories[i].kind;
389 static /*@observer@*/ cstring categoryName (flagkind kind)
393 for (i = 0; categories[i].kind != FK_NONE; i++)
396 if (categories[i].kind == kind)
398 return (cstring_fromChars (categories[i].name));
402 return (cstring_makeLiteralTemp ("<No Category>"));
405 static int categoryIndex (flagkind kind)
409 for (i = 0; categories[i].kind != FK_NONE; i++)
412 if (categories[i].kind == kind)
421 void printCategory (flagkind kind)
423 int index = categoryIndex (kind);
425 llassert (index >= 0);
427 llmsg (message ("%s (%d flags)\n\3%s\n\n",
428 cstring_fromChars (categories[index].name),
430 cstring_fromChars (categories[index].describe)));
434 if (f.main == kind || f.sub == kind)
436 llmsg (message (" %s\n\6%q", cstring_fromChars (f.flag),
437 describeFlagCode (f.code)));
443 listAllCategories (void)
447 for (i = 0; categories[i].kind != FK_NONE; i++)
450 flagkind kind = categories[i].kind ;
452 if (categories[i].describe != NULL)
454 llmsg (message ("%s (%d flags)\n\3%s",
457 cstring_fromChars (categories[i].describe)));
463 printAllFlags (bool desc, bool full)
467 cstringSList fl = sortedFlags ();
469 cstringSList_elements (fl, el)
471 /*@i22@*/ /*find out why this is necessary*/
473 tmp = cstring_copy(el);
474 llmsg (message ("%q\n\n", describeFlag (tmp)));
476 } end_cstringSList_elements ;
478 cstringSList_free (fl);
484 if (f.code != INVALID_FLAG && f.main != FK_OBSOLETE)
486 if (mstring_isDefined (f.desc))
490 llmsg (message ("%s --- %s", cstring_fromChars (f.flag),
491 cstring_fromChars (f.desc)));
500 printFlagManual (bool html)
503 ** Prints all flags by category, in order they appear in flags.def
506 flagkind lastCategory = FK_NONE;
510 cstring flagtype = cstring_undefined;
512 if (f.main != lastCategory)
516 llmsg (message ("\n<h4>%s</h4>\n", categoryName (f.main)));
520 llmsg (message ("\n%s\n%s\n",
521 categoryName (f.main),
522 cstring_makeLiteralTemp ("===================================")));
525 lastCategory = f.main;
528 if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL)
532 flagname = message ("<tt>%s</tt>", cstring_fromChars (f.flag));
536 flagname = cstring_fromCharsNew (f.flag);
541 if (flagcode_hasString (f.code))
545 flagname = message ("<tt>%s <em><%s></em></tt>",
546 cstring_fromChars (f.flag), argcode_unparse (f.argtype));
550 flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype));
553 if (cstring_isDefined (context_getString (f.code)))
557 flagname = message ("%q <font color=\"blue\">[%s]</font>", flagname,
558 context_getString (f.code));
562 flagname = message ("%q [%s]", flagname,
563 context_getString (f.code));
567 else if (f.argtype == ARG_CHAR)
571 flagname = message ("<tt>%s <em><%s></em></tt> <font color=\"blue\">[%c]</font>",
572 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
573 (char) context_getValue (f.code));
577 flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
578 (char) context_getValue (f.code));
583 llassert (f.argtype == ARG_NUMBER);
587 flagname = message ("<tt>%s <em><%s></em> <font color=\"blue\">[%d]</font>",
588 cstring_fromChars (f.flag), argcode_unparse (f.argtype),
589 context_getValue (f.code));
593 flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype),
594 context_getValue (f.code));
603 flagtype = message("%q<font color=\"green\">-</font>", flagtype);
607 flagtype = message("%q<->", flagtype);
615 flagtype = message ("%q<font color=\"green\"><em>global</em></font>", flagtype);
619 flagtype = message ("%q<G>", flagtype);
627 flagtype = message ("%q<font color=\"orange\"><em>shortcut</em></font>", flagtype);
631 flagtype = message("%q<S>", flagtype);
639 flagtype = message ("%q mode:<tt>%q</tt>>", flagtype, getFlagModeSettings (f.code));
643 flagtype = message ("%q<M:%q>", flagtype, getFlagModeSettings (f.code));
646 else /* its a plain flag */
650 flagtype = message ("%q plain:<tt>%s</tt>", flagtype,
651 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
655 flagtype = message ("%q<P:%s>", flagtype,
656 cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-"));
660 llmsg (message ("%s: %s", flagname, flagtype));
664 llgenindentmsgnoloc (cstring_makeLiteral ("<blockquote>"));
667 if (mstring_isDefined (f.hint))
669 llgenindentmsgnoloc (cstring_fromCharsNew (f.hint));
673 llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc))));
678 llgenindentmsgnoloc (cstring_makeLiteral ("</blockquote>"));
684 describeFlagCode (flagcode flag)
686 cstring ret = cstring_undefined;
689 if (flagcode_isInvalid (flag))
691 return (cstring_makeLiteral ("<invalid>"));
694 context_resetAllFlags ();
698 ret = cstring_copy (cstring_fromChars (f.desc));
700 if (f.sub != FK_NONE)
702 ret = message ("%q\nCategories: %s, %s",
704 categoryName (f.main),
705 categoryName (f.sub));
709 if (f.main != FK_NONE)
711 cstring cname = categoryName (f.main);
713 if (cstring_isDefined (cname))
715 ret = message ("%q\nCategory: %s",
723 ret = message ("%q\nMode Settings: %q",
724 ret, getFlagModeSettings (flag));
728 ret = message ("%q\nDefault Setting: %s",
730 cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
735 ret = message("%q\nSet globally only", ret);
739 ret = message("%q\nSet locally", ret);
748 ret = message("%q\nNumeric Argument. Default: %d",
750 context_getValue (flag));
753 ret = message("%q\nCharacter Argument. Default: %h",
754 ret, (char) context_getValue (flag));
761 if (cstring_isDefined (context_getString (flag)))
763 ret = message("%q\n%q argument. Default: %s",
765 cstring_capitalize (argcode_unparse (f.argtype)),
766 context_getString (flag));
770 ret = message("%q\n%s argument. No default.",
772 cstring_capitalize (argcode_unparse (f.argtype)));
778 if (mstring_isDefined (f.hint))
780 ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint));
786 static cstring getFlagModeSettings (flagcode flag)
788 cstring res = cstring_undefined;
792 context_setModeNoWarn (cstring_fromChars (mname));
794 res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-"));
801 describeFlag (cstring flagname)
803 cstring oflagname = cstring_copy (flagname);
804 flagcode f = flags_identifyFlag (flagname);
806 if (flagcode_isSkip (f))
808 cstring_free (oflagname);
809 return cstring_undefined;
811 else if (flagcode_isValid (f))
813 if (cstring_equal (flagname, oflagname))
815 cstring_free (oflagname);
816 return (message ("%s\n\3%q", flagname, describeFlagCode (f)));
820 return (message ("%q (standardized name: %s)\n\3%q",
821 oflagname, flagname, describeFlagCode (f)));
826 if (isMode (flagname))
828 cstring_free (oflagname);
831 (message ("%s: predefined mode (see Manual for information)",
836 return (message ("%q: <invalid flag>", oflagname));
844 cstringSList s = cstringSList_new ();
850 s = cstringSList_add (s, cstring_fromChars (f.flag));
854 cstringSList_alphabetize (s);
859 void printAlphaFlags ()
861 cstringSList fl = sortedFlags ();
863 cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25);
864 cstringSList_free (fl);
867 /*@observer@*/ cstring
868 flagcode_unparse (flagcode code)
870 if (code == INVALID_FLAG)
872 return cstring_makeLiteralTemp ("<invalid flag>");
875 return cstring_fromChars (flags[code].flag);
879 ** Transforms a flag into its cannonical form.
881 ** The following transformations are made:
887 ** parameter -> param
888 ** unrecognized -> unrecog
890 ** declaration -> decl
891 ** globalias -> (no change)
899 ** unconstrained -> unspec
905 static /*@only@*/ cstring
906 canonicalizeFlag (cstring s)
909 cstring res = cstring_copy (s);
910 static bn_mstring transform[] =
916 "parameter", "param",
917 "unrecognized", "unrecog",
919 "declaration", "decl",
927 "unconstrained", "uncon",
938 while ((current = transform[i]) != NULL)
940 if (cstring_containsLit (res, current))
942 cstring_replaceLit (res, current, transform[i+1]);
947 /* remove whitespace, -'s, and _'s */
948 cstring_stripChars (res, " -_");
953 flags_identifyFlag (cstring s)
955 return flags_identifyFlagAux (s, FALSE);
959 flags_identifyFlagQuiet (cstring s)
961 return flags_identifyFlagAux (s, TRUE);
965 flags_identifyFlagAux (cstring s, bool quiet)
970 if (cstring_length (s) == 0) {
971 /* evs 2000-06-25: A malformed flag. */
975 if (cstring_firstChar (s) == 'I')
977 return FLG_INCLUDEPATH; /* no space after -I */
980 if (cstring_firstChar (s) == 'S')
982 return FLG_SPECPATH; /* no space after -S */
985 if (cstring_firstChar (s) == 'D')
987 return FLG_DEFINE; /* no space after -D */
990 if (cstring_firstChar (s) == 'U')
992 return FLG_UNDEFINE; /* no space after -D */
995 cflag = canonicalizeFlag (s);
1000 if (cstring_equal (cstring_fromChars (f.flag), cflag))
1007 if (res == INVALID_FLAG)
1013 if (cstring_equalLit (cflag, "pred"))
1017 else if (cstring_equalLit (cflag, "modobserverstrict"))
1019 res = FLG_MODOBSERVERUNCON;
1021 else if (cstring_equalLit (cflag, "czechnames"))
1025 else if (cstring_equalLit (cflag, "slovaknames"))
1029 else if (cstring_equalLit (cflag, "czechoslovaknames"))
1031 res = FLG_CZECHOSLOVAK;
1033 else if (cstring_equalLit (cflag, "globunspec")
1034 || cstring_equalLit (cflag, "globuncon"))
1036 res = FLG_GLOBUNSPEC;
1038 else if (cstring_equalLit (cflag, "modglobsunspec")
1039 || cstring_equalLit (cflag, "modglobsuncon")
1040 || cstring_equalLit (cflag, "modglobsnomods"))
1042 res = FLG_MODGLOBSUNSPEC;
1044 else if (cstring_equalLit (cflag, "export"))
1046 res = FLG_EXPORTANY;
1048 else if (cstring_equalLit (cflag, "macrospec"))
1050 res = FLG_MACRODECL;
1052 else if (cstring_equalLit (cflag, "ansireservedlocal"))
1054 res = FLG_ANSIRESERVEDLOCAL;
1056 else if (cstring_equalLit (cflag, "warnposix"))
1058 res = FLG_WARNPOSIX;
1060 else if (cstring_equalLit (cflag, "defuse"))
1064 else if (cstring_equalLit (cflag, "macroundef"))
1066 res = FLG_MACROUNDEF;
1068 else if (cstring_equalLit (cflag, "showcol"))
1072 else if (cstring_equalLit (cflag, "intbool"))
1076 else if (cstring_equalLit (cflag, "intchar"))
1080 else if (cstring_equalLit (cflag, "intenum"))
1085 ** Backwards compatibility for our American friends...
1088 else if (cstring_equalLit (cflag, "ansilib"))
1092 else if (cstring_equalLit (cflag, "ansistrictlib"))
1094 res = FLG_STRICTLIB;
1096 else if (cstring_equalLit (cflag, "skipansiheaders"))
1098 res = FLG_SKIPANSIHEADERS;
1100 else if (cstring_equalLit (cflag, "ansireserved"))
1102 res = FLG_ANSIRESERVED;
1104 else if (cstring_equalLit (cflag, "ansireservedinternal"))
1106 res = FLG_ANSIRESERVEDLOCAL;
1113 else if (cstring_equalLit (cflag, "accessunspec"))
1118 (cstring_makeLiteral
1119 ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and "
1120 "accessfunction to provide more precise control of accessibility "
1121 "of representations. For more information, "
1122 "see splint -help accessmodule"));
1127 else if (cstring_equalLit (cflag, "ansilimits"))
1130 (cstring_makeLiteral
1131 ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and "
1132 "iso99limits to select either the lower translation limits imposed by the ANSI89 "
1133 "standard or the typically higher limits prescribed by ISO C99."));
1137 else if (cstring_equalLit (cflag, "staticmods"))
1142 (cstring_makeLiteral
1143 ("staticmods flag is obsolete. You probably "
1144 "want impcheckmodstatics. For more information, "
1145 "see splint -help impcheckmodstatics"));
1150 else if (cstring_equalLit (cflag, "bool"))
1155 (cstring_makeLiteral ("bool flag is obsolete. It never really "
1156 "made sense in the first place."));
1161 else if (cstring_equalLit (cflag, "shiftsigned"))
1166 (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably "
1167 "want bitwisesigned, shiftnegative or shiftsize."));
1172 else if (cstring_equalLit (cflag, "ansi"))
1177 (cstring_makeLiteral ("ansi flag is obsolete. You probably "
1178 "want noparams and/or oldstyle."));
1183 else if (cstring_equalLit (cflag, "stdio"))
1188 (cstring_makeLiteral
1189 ("stdio flag is obsolete. You may "
1190 "want strictlib or one of the gloabls "
1191 "checking flags. For more information, "
1192 "see splint -help strictlib or splint -help flags globals"));
1203 cstring_free (cflag);
1207 void setValueFlag (flagcode opt, cstring arg)
1215 case FLG_INDENTSPACES:
1217 case FLG_EXTERNALNAMELEN:
1218 case FLG_INTERNALNAMELEN:
1219 case FLG_CONTROLNESTDEPTH:
1220 case FLG_STRINGLITERALLEN:
1221 case FLG_NUMSTRUCTFIELDS:
1222 case FLG_NUMENUMMEMBERS:
1223 case FLG_INCLUDENEST:
1225 int val = cstring_toPosInt (arg);
1232 ("Flag %s must be followed by a positive number number. "
1234 flagcode_unparse (opt), arg));
1238 context_setValueAndFlag (opt, val);
1242 case FLG_COMMENTCHAR:
1244 if (cstring_length (arg) != 1)
1248 ("Flag %s should be followed by a single character. Followed by %s",
1249 flagcode_unparse (opt), arg));
1253 context_setCommentMarkerChar (cstring_firstChar (arg));
1261 void setStringFlag (flagcode opt, /*@only@*/ cstring arg)
1267 if (cstring_lastChar (arg) == CONNECTCHAR)
1269 context_setString (opt, arg);
1273 context_setString (opt, cstring_appendChar (arg, CONNECTCHAR));
1279 context_setString (opt, arg);
1288 cstring s = cstring_makeLiteral ("Flag ");
1289 cstringSList sflags = sortedFlags ();
1293 s = message ("%q%9s", s, cstring_fromChars (modename));
1296 s = message ("%q\n", s);
1298 cstringSList_elements (sflags, flagname)
1300 flagcode code = flags_identifyFlag (flagname);
1301 fflag currentflag = flags[code];
1303 if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code))
1305 s = message ("%q\n%27s", s,
1306 cstring_fromChars (currentflag.flag));
1310 context_setMode (cstring_fromChars (modename));
1312 if (context_getFlag (code))
1314 s = message ("%q%9s", s, cstring_makeLiteralTemp ("+"));
1318 s = message ("%q%9s", s, cstring_makeLiteralTemp (" "));
1321 context_resetModeFlags ();
1324 } end_cstringSList_elements;
1326 cstringSList_free (sflags);
1328 s = cstring_appendChar (s, '\n');
1334 static /*@unused@*/ cstring
1337 cstring s = cstring_makeLiteral ("\t");
1342 if (i != 0 && (i % 4 == 0))
1344 s = message ("%q\n\t%15s", s, cstring_fromChars (modename));
1348 s = message ("%q%15s", s, cstring_fromChars (modename));
1362 if (mstring_isDefined (modename))
1364 if (cstring_equalLit (s, modename))
1374 extern bool flagcode_hasArgument (flagcode f)
1376 return (flags[f].argtype != ARG_NONE);
1379 extern bool flagcode_hasNumber (flagcode f)
1381 return (flags[f].argtype == ARG_NUMBER);
1384 extern bool flagcode_hasChar (flagcode f)
1386 return (flags[f].argtype == ARG_CHAR);
1389 extern bool flagcode_hasString (flagcode f)
1391 return (flags[f].argtype == ARG_STRING
1392 || flags[f].argtype == ARG_FILE
1393 || flags[f].argtype == ARG_DIRECTORY
1394 || flags[f].argtype == ARG_PATH);
1397 extern int flagcode_valueIndex (flagcode f)
1399 /*@unchecked@*/ static bool initialized = FALSE;
1401 /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS];
1409 if (flagcode_hasNumber (code) || flagcode_hasChar (code))
1411 llassert (nv < NUMVALUEFLAGS);
1412 DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code));
1413 valueFlags[nv] = code;
1418 llassertprint (nv == NUMVALUEFLAGS,
1419 ("Number of value flags: %d (expected %d)",
1420 nv, (int) NUMVALUEFLAGS));
1424 for (i = 0; i < NUMVALUEFLAGS; i++)
1426 /* static valueFlags must be defined */
1429 if (f == valueFlags[i]) /*@=usedef@*/
1435 fprintf (stderr, "Cannot find value flag: %d", (int) f);
1436 exit (EXIT_FAILURE);
1437 /* Cannot do this...might call recursively...
1438 llfatalbug (message ("Cannot fine value flag: %d", (int) f));
1443 extern int flagcode_stringIndex (flagcode f)
1445 /*@unchecked@*/ static bool initialized = FALSE;
1446 /*@unchecked@*/ static flagcode stringFlags[NUMSTRINGFLAGS];
1456 if (flagcode_hasString (code))
1458 llassertprint (nv < NUMSTRINGFLAGS, ("Incorrect number of string flags: %d (need at least %d)", NUMSTRINGFLAGS, nv));
1459 stringFlags[nv] = code;
1464 llassertprint (nv == NUMSTRINGFLAGS,
1465 ("number of string flags: %d (expected %d)",
1466 nv, NUMSTRINGFLAGS));
1470 for (i = 0; i < NUMSTRINGFLAGS; i++)
1473 /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/
1479 llbug (message ("Bad string flag: %s", flagcode_unparse (f)));
1483 bool flagcode_isNamePrefixFlag (flagcode f)
1487 case FLG_MACROVARPREFIX:
1489 case FLG_ENUMPREFIX:
1490 case FLG_FILESTATICPREFIX:
1491 case FLG_GLOBPREFIX:
1492 case FLG_TYPEPREFIX:
1493 case FLG_EXTERNALPREFIX:
1494 case FLG_LOCALPREFIX:
1495 case FLG_UNCHECKEDMACROPREFIX:
1496 case FLG_CONSTPREFIX:
1497 case FLG_ITERPREFIX:
1498 case FLG_DECLPARAMPREFIX: