X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/abb1cb4309abcd21cdbbab2c4a0af5ca44126b47..a9ec328054b628447830161535f4915f715f49cd:/src/flags.c diff --git a/src/flags.c b/src/flags.c index 37ea7e0..c26a6c6 100644 --- a/src/flags.c +++ b/src/flags.c @@ -1,6 +1,6 @@ /* -** LCLint - annotation-assisted static program checker -** Copyright (C) 1994-2001 University of Virginia, +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2003 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,17 +17,20 @@ ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ** MA 02111-1307, USA. ** -** For information on lclint: lclint-request@cs.virginia.edu -** To report a bug: lclint-bug@cs.virginia.edu -** For more information: http://lclint.cs.virginia.edu +** For information on splint: info@splint.org +** To report a bug: splint-bug@splint.org +** For more information: http://www.splint.org */ /* ** flags.c */ -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" -# include "portab.h" +# include "osd.h" +# include "rcfiles.h" +# include "lslinit.h" +# include "llmain.h" /* ** from the CC man page: @@ -54,10 +57,11 @@ static flagcatinfo categories[] = { FK_ANSI, "ansi", "violations of constraints imposed by ANSI/ISO standard" } , { FK_ARRAY, "arrays", "special checking involving arrays" } , { FK_BOOL, "booleans", "checking and naming of boolean types" } , - { FK_COMMENTS, "comments", "interpretation of semantic comments" } , + { FK_COMMENTS, "comments", "warnings about (normal) comments" } , + { FK_SYNCOMMENTS, "syncomments", "interpretation of annotation comments" } , { FK_COMPLETE, "complete", "completely defined, used, or specified system" } , { FK_CONTROL, "controlflow", "suspicious control structures" } , - { FK_DEBUG, "debug", "flags for debugging lclint" } , + { FK_DEBUG, "debug", "flags for debugging splint" } , { FK_DECL, "declarations", "consistency of declarations" } , { FK_DEF, "definition", "undefined storage errors" } , { FK_DIRECT, "directories", "set directores" } , @@ -66,11 +70,15 @@ static flagcatinfo categories[] = { FK_ERRORS, "errors", "control expected errors, summary reporting" } , { FK_EXPORT, "export", "control what may be exported" } , { FK_EXPOSURE, "exposure", "representation exposure" } , + { FK_EXTENSIBLE, "extensible", "user-defined checks and annotations" }, { FK_FILES, "files", "control system files" } , { FK_FORMAT, "format", "control format of warning messages" } , { FK_GLOBALS, "globals", "use of global and file static variables" }, { FK_HEADERS, "headers", "control inclusion and generation of header files" }, { FK_HELP, "help", "on-line help" }, + { FK_BOUNDS, "memorybounds", "out-of-bounds memory accesses" }, + { FK_HINTS, "hints", "control display of warning hints" }, + { FK_SYSTEMFUNCTIONS, "systemfunctions", "special properties of exit and main" }, { FK_IMPLICIT, "implicit", "control implicit annotations and interpretations" } , { FK_INIT, "initializations", "initialization files" } , { FK_ITER, "iterators", "checking iterator definitions and uses" } , @@ -101,6 +109,7 @@ static flagcatinfo categories[] = { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } , { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } , { FK_WARNUSE, "warnuse", "use of possibly problematic function" } , + { FK_ITS4, "its4", "its4 compatibility flags (report warnings for uses of possibly insecure functions)" } , { FK_SYNTAX, NULL, NULL } , { FK_TYPE, NULL, NULL } , { FK_SECRET, NULL, NULL } , @@ -110,11 +119,41 @@ static flagcatinfo categories[] = typedef enum { ARG_NONE, - ARG_VALUE, - ARG_STRING, - ARG_SPECIAL + ARG_NUMBER, /* number */ + ARG_CHAR, /* char */ + ARG_STRING, /* string */ + ARG_FILE, /* filename (also a string) */ + ARG_DIRECTORY, /* directory (also a string) */ + ARG_PATH, /* path */ + ARG_SPECIAL /* ? */ } argcode; +# ifdef WIN32 +/* Make Microsoft VC++ happy */ +# pragma warning (disable:4715) +# endif + +static /*@observer@*/ cstring argcode_unparse (argcode arg) +{ + switch (arg) + { + case ARG_STRING: return cstring_makeLiteralTemp ("string"); + case ARG_FILE: return cstring_makeLiteralTemp ("filename"); + case ARG_DIRECTORY: return cstring_makeLiteralTemp ("directory"); + case ARG_PATH: return cstring_makeLiteralTemp ("path"); + case ARG_NUMBER: return cstring_makeLiteralTemp ("number"); + case ARG_CHAR: return cstring_makeLiteralTemp ("character"); + case ARG_NONE: + BADBRANCH; + case ARG_SPECIAL: + BADBRANCH; + } +} + +# ifdef WIN32 +# pragma warning (default : 4715) +# endif + typedef struct { flagkind main; flagkind sub; @@ -154,10 +193,16 @@ static bn_mstring mode_names[] = /*@+enumint@*/ +static cstring getFlagModeSettings (flagcode p_flag) /*@modifies internalState@*/ ; static cstring describeFlagCode (flagcode p_flag) /*@*/ ; static cstringSList sortedFlags (void) /*@*/ ; static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ; + +static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ; + +# if 0 static /*@unused@*/ cstring listModes (void) /*@*/ ; +# endif bool flagcode_isSpecialFlag (flagcode f) { @@ -184,6 +229,33 @@ bool flagcode_isNameChecksFlag (flagcode f) return (flags[f].main == FK_NAMES); } +bool flagcode_isHelpFlag (flagcode f) +{ + return f == FLG_HELP; +} + +bool flagcode_isMessageControlFlag (flagcode f) +{ + /* + ** True if opt controls the display of messages. + ** These flags must be processed first. + */ + + return (f == FLG_SHOWSCAN + || f == FLG_WARNRC + || f == FLG_PARENFILEFORMAT + || f == FLG_MESSAGESTREAMSTDERR + || f == FLG_MESSAGESTREAMSTDOUT + || f == FLG_WARNINGSTREAMSTDERR + || f == FLG_WARNINGSTREAMSTDOUT + || f == FLG_ERRORSTREAMSTDERR + || f == FLG_ERRORSTREAMSTDOUT + || f == FLG_MESSAGESTREAM + || f == FLG_WARNINGSTREAM + || f == FLG_ERRORSTREAM + || f == FLG_STREAMOVERWRITE); +} + /* ** Internal consistency check on the flags. */ @@ -233,7 +305,7 @@ summarizeErrors () hadOne = TRUE; } - sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup); + (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (fs), nrep, nsup); sumrep += nrep; sumsup += nsup; @@ -249,7 +321,7 @@ summarizeErrors () llmsglit (" ======== ========="); - sprintf (buf, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup); + (void) snprintf (buf, 128, "%s%7d %9d", cstring_toCharsSafe (ts), sumrep, sumsup); cstring_free (ts); llmsgplain (cstring_copy (cstring_fromChars (buf))); } @@ -379,7 +451,6 @@ void printCategory (flagkind kind) int index = categoryIndex (kind); llassert (index >= 0); - llmsg (message ("%s (%d flags)\n\3%s\n\n", cstring_fromChars (categories[index].name), categorySize (kind), @@ -423,7 +494,10 @@ printAllFlags (bool desc, bool full) cstringSList_elements (fl, el) { - llmsg (message ("%q\n\n", describeFlag (el))); + cstring tmp; + tmp = cstring_copy(el); + llmsg (message ("%q\n\n", describeFlag (tmp))); + cstring_free(tmp); } end_cstringSList_elements ; cstringSList_free (fl); @@ -447,22 +521,244 @@ printAllFlags (bool desc, bool full) } } +void +printFlagManual (bool html) +{ + /* + ** Prints all flags by category, in order they appear in flags.def + */ + + flagkind lastCategory = FK_NONE; + + allFlags (f) { + cstring flagname; + cstring flagtype = cstring_undefined; + + if (f.main != lastCategory) + { + if (html) + { + llmsg (message ("\n

%s

\n", categoryName (f.main))); + } + else + { + llmsg (message ("\n%s\n%s\n", + categoryName (f.main), + cstring_makeLiteralTemp ("==================================="))); + } + + lastCategory = f.main; + } + + if (f.argtype == ARG_NONE || f.argtype == ARG_SPECIAL) + { + if (html) + { + flagname = message ("%s", cstring_fromChars (f.flag)); + } + else + { + flagname = cstring_fromCharsNew (f.flag); + } + } + else + { + if (flagcode_hasString (f.code)) + { + if (html) + { + flagname = message ("%s <%s>", + cstring_fromChars (f.flag), argcode_unparse (f.argtype)); + } + else + { + flagname = message ("%s <%s>", cstring_fromChars (f.flag), argcode_unparse (f.argtype)); + } + + if (cstring_isDefined (context_getString (f.code))) + { + if (html) + { + flagname = message ("%q [%s]", flagname, + context_getString (f.code)); + } + else + { + flagname = message ("%q [%s]", flagname, + context_getString (f.code)); + } + } + } + else if (f.argtype == ARG_CHAR) + { + if (html) + { + flagname = message ("%s <%s> [%c]", + cstring_fromChars (f.flag), argcode_unparse (f.argtype), + (char) context_getValue (f.code)); + } + else + { + flagname = message ("%s <%s> [%c]", cstring_fromChars (f.flag), argcode_unparse (f.argtype), + (char) context_getValue (f.code)); + } + } + else + { + llassert (f.argtype == ARG_NUMBER); + + if (html) + { + flagname = message ("%s <%s> [%d]", + cstring_fromChars (f.flag), argcode_unparse (f.argtype), + context_getValue (f.code)); + } + else + { + flagname = message ("%s <%s> [%d]", cstring_fromChars (f.flag), argcode_unparse (f.argtype), + context_getValue (f.code)); + } + } + } + + if (f.isIdem) + { + if (html) + { + flagtype = message("%q-", flagtype); + } + else + { + flagtype = message("%q<->", flagtype); + } + } + + if (f.isGlobal) + { + if (html) + { + flagtype = message ("%qglobal", flagtype); + } + else + { + flagtype = message ("%q", flagtype); + } + } + + if (f.isSpecial) + { + if (html) + { + flagtype = message ("%qshortcut", flagtype); + } + else + { + flagtype = message("%q", flagtype); + } + } + + if (f.isModeFlag) + { + if (html) + { + flagtype = message ("%q mode:%q>", flagtype, getFlagModeSettings (f.code)); + } + else + { + flagtype = message ("%q", flagtype, getFlagModeSettings (f.code)); + } + } + else /* its a plain flag */ + { + if (html) + { + flagtype = message ("%q plain:%s", flagtype, + cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-")); + } + else + { + flagtype = message ("%q", flagtype, + cstring_makeLiteralTemp (context_getFlag (f.code) ? "+" : "-")); + } + } + + llmsg (message ("%s: %s", flagname, flagtype)); + + if (html) + { + llgenindentmsgnoloc (cstring_makeLiteral ("
")); + } + + if (mstring_isDefined (f.hint)) + { + llgenindentmsgnoloc (cstring_fromCharsNew (f.hint)); + } + else + { + llgenindentmsgnoloc (message ("%q.", cstring_capitalize (cstring_fromChars (f.desc)))); + } + + if (html) + { + llgenindentmsgnoloc (cstring_makeLiteral ("
")); + } + } end_allFlags ; +} + +cstring +describeMode (cstring mode) +{ + cstringSList sflags = sortedFlags (); + cstring res = message ("Predefined mode %s sets: ", mode); + + llassert (flags_isModeName (mode)); + + context_setMode (mode); + + cstringSList_elements (sflags, flagname) + { + flagcode code = flags_identifyFlag (flagname); + fflag currentflag = flags[code]; + + if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code)) + { + if (context_getFlag (code)) + { + res = message ("%q\n +%s", res, cstring_fromChars (currentflag.flag)); + } + else + { + res = message ("%q\n -%s", res, cstring_fromChars (currentflag.flag)); + } + } + } end_cstringSList_elements; + + cstringSList_free (sflags); + + res = cstring_appendChar (res, '\n'); + return (res); +} + cstring describeFlagCode (flagcode flag) { cstring ret = cstring_undefined; fflag f; - + if (flagcode_isInvalid (flag)) { return (cstring_makeLiteral ("")); } + if (flagcode_isModeName (flag)) + { + return (cstring_makeLiteral ("")); + } + context_resetAllFlags (); f = flags[flag]; ret = cstring_copy (cstring_fromChars (f.desc)); - if (f.sub != FK_NONE) { @@ -484,40 +780,19 @@ describeFlagCode (flagcode flag) } } } - + if (f.isModeFlag) { - bool first = TRUE; - - allModes (mname) - { - context_setMode (cstring_fromChars (mname)); - - if (first) - { - ret = message ("%q\nMode Settings: %s %s", - ret, cstring_fromChars (mname), - cstring_makeLiteralTemp - (context_getFlag (flag) ? "+" : "-")); - first = FALSE; - } - else - { - ret = message ("%q, %s %s", - ret, cstring_fromChars (mname), - cstring_makeLiteralTemp - (context_getFlag (flag) ? "+" : "-")); - } - } end_allModes; + ret = message ("%q\nMode Settings: %q", + ret, getFlagModeSettings (flag)); } else { ret = message ("%q\nDefault Setting: %s", ret, - cstring_makeLiteralTemp - (context_getFlag (flag) ? "+" : "-")); + cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-")); } - + if (f.isGlobal) { ret = message("%q\nSet globally only", ret); @@ -526,52 +801,70 @@ describeFlagCode (flagcode flag) { ret = message("%q\nSet locally", ret); } - + switch (f.argtype) { case ARG_NONE: case ARG_SPECIAL: break; - case ARG_VALUE: - if (flag == FLG_COMMENTCHAR) - { - ret = message("%q\nCharacter Argument. Default: %h", - ret, (char) context_getValue (flag)); - } - else - { - ret = message("%q\nNumeric Argument. Default: %d", - ret, - context_getValue (flag)); - } + case ARG_NUMBER: + ret = message("%q\nNumeric Argument. Default: %d", + ret, + context_getValue (flag)); + break; + case ARG_CHAR: + ret = message("%q\nCharacter Argument. Default: %h", + ret, (char) context_getValue (flag)); break; case ARG_STRING: + case ARG_FILE: + case ARG_PATH: + case ARG_DIRECTORY: + { if (cstring_isDefined (context_getString (flag))) { - ret = message("%q\nString Argument. Default: %s", + ret = message("%q\n%q argument. Default: %s", ret, + cstring_capitalize (argcode_unparse (f.argtype)), context_getString (flag)); } else { - ret = message("%q\nString Argument. No default.", ret); + ret = message("%q\n%s argument. No default.", + ret, + cstring_capitalize (argcode_unparse (f.argtype))); } break; + } } - + if (mstring_isDefined (f.hint)) { ret = message("%q\n\3%s", ret, cstring_fromChars (f.hint)); } - + return ret; } + +static cstring getFlagModeSettings (flagcode flag) +{ + cstring res = cstring_undefined; + + allModes (mname) + { + context_setModeNoWarn (cstring_fromChars (mname)); + + res = message ("%q%s", res, cstring_makeLiteralTemp (context_getFlag (flag) ? "+" : "-")); + } end_allModes; + + return res; +} cstring describeFlag (cstring flagname) { cstring oflagname = cstring_copy (flagname); - flagcode f = identifyFlag (flagname); + flagcode f = flags_identifyFlag (flagname); if (flagcode_isSkip (f)) { @@ -593,13 +886,10 @@ describeFlag (cstring flagname) } else { - if (isMode (flagname)) + if (flags_isModeName (flagname)) { cstring_free (oflagname); - - return - (message ("%s: predefined mode (see User's Guide for information)", - flagname)); + return describeMode (flagname); } else { @@ -637,6 +927,11 @@ void printAlphaFlags () /*@observer@*/ cstring flagcode_unparse (flagcode code) { + if (code == INVALID_FLAG) + { + return cstring_makeLiteralTemp (""); + } + return cstring_fromChars (flags[code].flag); } @@ -667,10 +962,11 @@ flagcode_unparse (flagcode code) ** length -> len */ -static void +static /*@only@*/ cstring canonicalizeFlag (cstring s) { int i = 0; + cstring res = cstring_copy (s); static bn_mstring transform[] = { "function", "fcn", @@ -697,23 +993,39 @@ canonicalizeFlag (cstring s) NULL } ; char *current; - + while ((current = transform[i]) != NULL) { - if (cstring_containsLit (s, current)) + if (cstring_containsLit (res, current)) { - cstring_replaceLit (s, current, transform[i+1]); + cstring_replaceLit (res, current, transform[i+1]); } i += 2; } /* remove whitespace, -'s, and _'s */ - cstring_stripChars (s, " -_"); + cstring_stripChars (res, " -_"); + return res; +} + +flagcode +flags_identifyFlag (cstring s) +{ + return flags_identifyFlagAux (s, FALSE); } flagcode -identifyFlag (cstring s) +flags_identifyFlagQuiet (cstring s) +{ + return flags_identifyFlagAux (s, TRUE); +} + +static flagcode +flags_identifyFlagAux (cstring s, bool quiet) { + cstring cflag; + flagcode res; + if (cstring_length (s) == 0) { /* evs 2000-06-25: A malformed flag. */ return INVALID_FLAG; @@ -721,227 +1033,266 @@ identifyFlag (cstring s) if (cstring_firstChar (s) == 'I') { - return FLG_INCLUDEPATH; /* no space after -I */ + return FLG_INCLUDEPATH; /* no space required after -I */ } if (cstring_firstChar (s) == 'S') { - return FLG_SPECPATH; /* no space after -S */ + return FLG_SPECPATH; /* no space required after -S */ } if (cstring_firstChar (s) == 'D') { - return FLG_DEFINE; /* no space after -D */ + return FLG_DEFINE; /* no space required after -D */ } if (cstring_firstChar (s) == 'U') { - return FLG_UNDEFINE; /* no space after -D */ + return FLG_UNDEFINE; /* no space required after -D */ } - canonicalizeFlag (s); + cflag = canonicalizeFlag (s); + res = INVALID_FLAG; allFlags (f) { - if (cstring_equal (cstring_fromChars (f.flag), s)) + if (cstring_equal (cstring_fromChars (f.flag), cflag)) { - return (f.code); + res = f.code; + break; } } end_allFlags; - - /* - ** Synonyms - */ - - if (cstring_equalLit (s, "pred")) - { - return FLG_PREDBOOL; - } - - if (cstring_equalLit (s, "modobserverstrict")) - { - return FLG_MODOBSERVERUNCON; - } - - if (cstring_equalLit (s, "czechnames")) - { - return FLG_CZECH; - } - - if (cstring_equalLit (s, "slovaknames")) - { - return FLG_SLOVAK; - } - - if (cstring_equalLit (s, "czechoslovaknames")) - { - return FLG_CZECHOSLOVAK; - } - - if (cstring_equalLit (s, "globunspec") - || cstring_equalLit (s, "globuncon")) - { - return FLG_GLOBUNSPEC; - } - - if (cstring_equalLit (s, "modglobsunspec") - || cstring_equalLit (s, "modglobsuncon") - || cstring_equalLit (s, "modglobsnomods")) - { - return FLG_MODGLOBSUNSPEC; - } - - if (cstring_equalLit (s, "export")) - { - return FLG_EXPORTANY; - } - - if (cstring_equalLit (s, "macrospec")) - { - return FLG_MACRODECL; - } - if (cstring_equalLit (s, "ansireservedlocal")) - { - return FLG_ANSIRESERVEDLOCAL; - } - - if (cstring_equalLit (s, "warnposix")) - { - return FLG_WARNPOSIX; - } - - if (cstring_equalLit (s, "defuse")) - { - return FLG_USEDEF; - } - - if (cstring_equalLit (s, "macroundef")) - { - return FLG_MACROUNDEF; - } - - if (cstring_equalLit (s, "showcol")) - { - return FLG_SHOWCOL; - } - - if (cstring_equalLit (s, "intbool")) - { - return FLG_BOOLINT; - } - - if (cstring_equalLit (s, "intchar")) - { - return FLG_CHARINT; - } - - if (cstring_equalLit (s, "intenum")) - { - return FLG_ENUMINT; - } - - /* - ** For our European friends... - */ - - if (cstring_equalLit (s, "isolib")) - { - return FLG_ANSILIB; - } - - if (cstring_equalLit (s, "isostrictlib")) - { - return FLG_STRICTLIB; - } - - if (cstring_equalLit (s, "ansistrictlib")) - { - return FLG_STRICTLIB; - } - - if (cstring_equalLit (s, "skipisoheaders")) - { - return FLG_SKIPANSIHEADERS; - } - - if (cstring_equalLit (s, "isoreserved")) - { - return FLG_ANSIRESERVED; - } - - if (cstring_equalLit (s, "isoreservedinternal")) - { - return FLG_ANSIRESERVEDLOCAL; - } - - if (cstring_equalLit (s, "isolimits")) + if (res == INVALID_FLAG) { - return FLG_ANSILIMITS; - } - - /* - ** Obsolete Flags - */ - - if (cstring_equalLit (s, "accessunspec")) - { - llerror_flagWarning - (cstring_makeLiteral - ("accessunspec flag is not supported by LCLint version 2.0 or " - "later. It has been replaced by accessmodule, accessfile and " - "accessfunction to provide more precise control of accessibility " - "of representations. For more information, " - "see lclint -help accessmodule")); - - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "staticmods")) - { - llerror_flagWarning - (cstring_makeLiteral - ("staticmods flag is obsolete. You probably " - "want impcheckmodstatics. For more information, " - "see lclint -help impcheckmodstatics")); + /* + ** Synonyms + */ - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "bool")) - { - llerror_flagWarning - (cstring_makeLiteral ("bool flag is obsolete. It never really " - "made sense in the first place.")); + if (cstring_equalLit (cflag, "pred")) + { + res = FLG_PREDBOOL; + } + else if (cstring_equalLit (cflag, "modobserverstrict")) + { + res = FLG_MODOBSERVERUNCON; + } + else if (cstring_equalLit (cflag, "czechnames")) + { + res = FLG_CZECH; + } + else if (cstring_equalLit (cflag, "slovaknames")) + { + res = FLG_SLOVAK; + } + else if (cstring_equalLit (cflag, "czechoslovaknames")) + { + res = FLG_CZECHOSLOVAK; + } + else if (cstring_equalLit (cflag, "globunspec") + || cstring_equalLit (cflag, "globuncon")) + { + res = FLG_GLOBUNSPEC; + } + else if (cstring_equalLit (cflag, "modglobsunspec") + || cstring_equalLit (cflag, "modglobsuncon") + || cstring_equalLit (cflag, "modglobsnomods")) + { + res = FLG_MODGLOBSUNSPEC; + } + else if (cstring_equalLit (cflag, "export")) + { + res = FLG_EXPORTANY; + } + else if (cstring_equalLit (cflag, "macrospec")) + { + res = FLG_MACRODECL; + } + else if (cstring_equalLit (cflag, "ansireservedlocal")) + { + res = FLG_ISORESERVEDLOCAL; + } + else if (cstring_equalLit (cflag, "warnposix")) + { + res = FLG_WARNPOSIX; + } + else if (cstring_equalLit (cflag, "defuse")) + { + res = FLG_USEDEF; + } + else if (cstring_equalLit (cflag, "macroundef")) + { + res = FLG_MACROUNDEF; + } + else if (cstring_equalLit (cflag, "showcol")) + { + res = FLG_SHOWCOL; + } + else if (cstring_equalLit (cflag, "intbool")) + { + res = FLG_BOOLINT; + } + else if (cstring_equalLit (cflag, "intchar")) + { + res = FLG_CHARINT; + } + else if (cstring_equalLit (cflag, "intenum")) + { + res = FLG_ENUMINT; + } + else if (cstring_equalLit (cflag, "intlong")) + { + res = FLG_LONGINT; + } + else if (cstring_equalLit (cflag, "intshort")) + { + res = FLG_SHORTINT; + } + /* + ** Backwards compatibility for our American friends... + */ - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "ansi")) - { - llerror_flagWarning - (cstring_makeLiteral ("ansi flag is obsolete. You probably " - "want noparams and/or oldstyle.")); + else if (cstring_equalLit (cflag, "ansilib")) + { + res = FLG_ANSILIB; + } + else if (cstring_equalLit (cflag, "ansistrictlib")) + { + res = FLG_STRICTLIB; + } + else if (cstring_equalLit (cflag, "skipansiheaders")) + { + res = FLG_SKIPISOHEADERS; + } + else if (cstring_equalLit (cflag, "ansireserved")) + { + res = FLG_ISORESERVED; + } + else if (cstring_equalLit (cflag, "ansireservedinternal")) + { + res = FLG_ISORESERVEDLOCAL; + } - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "stdio")) - { - llerror_flagWarning - (cstring_makeLiteral - ("stdio flag is obsolete. You may " - "want strictlib or one of the gloabls " - "checking flags. For more information, " - "see lclint -help strictlib or lclint -help flags globals")); + /* + ** Obsolete Flags + */ - return SKIP_FLAG; + else if (cstring_equalLit (cflag, "accessunspec")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral + ("accessunspec flag is no longer supported. It has been replaced by accessmodule, accessfile and " + "accessfunction to provide more precise control of accessibility " + "of representations. For more information, " + "see splint -help accessmodule")); + } + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "ansilimits")) + { + llerror_flagWarning + (cstring_makeLiteral + ("ansilimits flag is no longer supported. It has been replaced by ansi89limits and " + "iso99limits to select either the lower translation limits imposed by the ANSI89 " + "standard or the typically higher limits prescribed by ISO C99.")); + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "staticmods")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral + ("staticmods flag is obsolete. You probably " + "want impcheckmodstatics. For more information, " + "see splint -help impcheckmodstatics")); + } + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "bool")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("bool flag is obsolete. It never really " + "made sense in the first place.")); + } + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "shiftsigned")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably " + "want bitwisesigned, shiftnegative or shiftimplementation.")); + } + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "ansi")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("ansi flag is obsolete. You probably " + "want noparams and/or oldstyle.")); + } + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "usestderr")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral + ("usestderr flag is obsolete. This has been replaced " + "by more precise flags for controlling the warning, " + "status message and fatal error streams independently: message-stream-stdout, " + "message-stream-stderr, message-stream , " + "warning-stream-stdout, warning-stream-stderr, warning-stream , " + "error-stream-stdout, error-stream-stderr, error-stream .")); + } + + res = SKIP_FLAG; + } + + else if (cstring_equalLit (cflag, "stdio")) + { + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral + ("stdio flag is obsolete. You may " + "want strictlib or one of the gloabls " + "checking flags. For more information, " + "see splint -help strictlib or splint -help flags globals")); + } + + res = SKIP_FLAG; + } + else if (flags_isModeName (cflag)) + { + res = MODENAME_FLAG; + } + else + { + res = INVALID_FLAG; + } } - return INVALID_FLAG; + cstring_free (cflag); + return res; } -void setValueFlag (flagcode opt, cstring arg) +void flags_setValueFlag (flagcode opt, cstring arg) { switch (opt) { @@ -950,6 +1301,7 @@ void setValueFlag (flagcode opt, cstring arg) case FLG_LIMIT: case FLG_LINELEN: case FLG_INDENTSPACES: + case FLG_LOCINDENTSPACES: case FLG_BUGSLIMIT: case FLG_EXTERNALNAMELEN: case FLG_INTERNALNAMELEN: @@ -991,11 +1343,11 @@ void setValueFlag (flagcode opt, cstring arg) } } break; - BADDEFAULT; + BADDEFAULT; } } -void setStringFlag (flagcode opt, /*@only@*/ cstring arg) +void flags_setStringFlag (flagcode opt, /*@only@*/ cstring arg) { switch (opt) { @@ -1034,7 +1386,7 @@ describeModes () cstringSList_elements (sflags, flagname) { - flagcode code = identifyFlag (flagname); + flagcode code = flags_identifyFlag (flagname); fflag currentflag = flags[code]; if (mstring_isDefined (currentflag.desc) && flagcode_isModeFlag (code)) @@ -1067,7 +1419,8 @@ describeModes () return (s); } -static cstring +# if 0 +static /*@unused@*/ cstring listModes (void) { cstring s = cstring_makeLiteral ("\t"); @@ -1088,9 +1441,10 @@ listModes (void) return s; } +# endif bool -isMode (cstring s) +flags_isModeName (cstring s) { allModes (modename) { @@ -1111,14 +1465,22 @@ extern bool flagcode_hasArgument (flagcode f) return (flags[f].argtype != ARG_NONE); } -extern bool flagcode_hasValue (flagcode f) +extern bool flagcode_hasNumber (flagcode f) +{ + return (flags[f].argtype == ARG_NUMBER); +} + +extern bool flagcode_hasChar (flagcode f) { - return (flags[f].argtype == ARG_VALUE); + return (flags[f].argtype == ARG_CHAR); } extern bool flagcode_hasString (flagcode f) { - return (flags[f].argtype == ARG_STRING); + return (flags[f].argtype == ARG_STRING + || flags[f].argtype == ARG_FILE + || flags[f].argtype == ARG_DIRECTORY + || flags[f].argtype == ARG_PATH); } extern int flagcode_valueIndex (flagcode f) @@ -1133,7 +1495,7 @@ extern int flagcode_valueIndex (flagcode f) allFlagCodes (code) { - if (flagcode_hasValue (code)) + if (flagcode_hasNumber (code) || flagcode_hasChar (code)) { llassert (nv < NUMVALUEFLAGS); DPRINTF (("Value flag: %s [%d]", flagcode_unparse (code), (int) code)); @@ -1151,7 +1513,8 @@ extern int flagcode_valueIndex (flagcode f) for (i = 0; i < NUMVALUEFLAGS; i++) { /* static valueFlags must be defined */ - /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/ + /*@-usedef@*/ + if (f == valueFlags[i]) /*@=usedef@*/ { return i; } @@ -1225,4 +1588,418 @@ bool flagcode_isNamePrefixFlag (flagcode f) return FALSE; } } - + +static cstring findLarchPathFile (/*@temp@*/ cstring s) +{ + cstring pathName; + filestatus status; + + status = osd_getPath (context_getLarchPath (), s, &pathName); + + if (status == OSD_FILEFOUND) + { + return pathName; + } + else if (status == OSD_FILENOTFOUND) + { + showHerald (); + lldiagmsg (message ("Cannot find file on LARCH_PATH: %s", s)); + } + else if (status == OSD_PATHTOOLONG) + { + /* Directory and filename are too long. Report error. */ + llbuglit ("soure_getPath: Filename plus directory from search path too long"); + } + else + { + BADBRANCH; + } + + return cstring_undefined; +} + +static void addLarchPathFile (fileIdList files, /*@temp@*/ cstring s) +{ + cstring pathName = findLarchPathFile (s); + + if (cstring_isDefined (pathName)) + { + if (fileTable_exists (context_fileTable (), pathName)) + { + showHerald (); + lldiagmsg (message ("File listed multiple times: %s", pathName)); + cstring_free (pathName); + } + else + { + fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), pathName)); + } + } +} + + +static void addFile (fileIdList files, /*@only@*/ cstring s) +{ + if (fileTable_exists (context_fileTable (), s)) + { + showHerald (); + lldiagmsg (message ("File listed multiple times: %s", s)); + cstring_free (s); + } + else + { + fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s)); + } +} + +static void addXHFile (fileIdList files, /*@temp@*/ cstring s) +{ + cstring pathName = findLarchPathFile (s); + + if (cstring_isDefined (pathName)) + { + if (fileTable_exists (context_fileTable (), pathName)) + { + showHerald (); + lldiagmsg (message ("File listed multiple times: %s", s)); + } + else + { + fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName)); + } + } + + cstring_free (pathName); +} + +void +flags_processFlags (bool inCommandLine, + fileIdList xfiles, + fileIdList cfiles, + fileIdList lclfiles, + fileIdList mtfiles, + cstringList *passThroughArgs, + int argc, char **argv) +{ + int i; + cstringSList fl = cstringSList_undefined; + + for (i = 0; i < argc; i++) + { + char *thisarg; + + llassert (argv != NULL); + thisarg = argv[i]; + + DPRINTF (("process thisarg [%d]: %s", i, thisarg)); + + if (*thisarg == '-' || *thisarg == '+') + { + bool set = (*thisarg == '+'); + cstring flagname; + flagcode opt; + + if (*(thisarg + 1) == '-') { /* allow -- before flags */ + flagname = cstring_fromChars (thisarg + 2); + } else { + flagname = cstring_fromChars (thisarg + 1); + } + + opt = flags_identifyFlag (flagname); + DPRINTF (("Flag [%s]: %s", flagname, flagcode_unparse (opt))); + + if (flagcode_isInvalid (opt)) + { + DPRINTF (("Error!")); + voptgenerror (FLG_BADFLAG, + message ("Unrecognized option: %s", + cstring_fromChars (thisarg)), + g_currentloc); + } + else if (flagcode_isHelpFlag (opt)) + { + if (inCommandLine) + { + voptgenerror (FLG_BADFLAG, + message ("Help flag must be first on the command line: %s", + cstring_fromChars (thisarg)), + g_currentloc); + } + else + { + voptgenerror (FLG_BADFLAG, + message ("Help flags can only be used on the command line: %s", + cstring_fromChars (thisarg)), + g_currentloc); + } + } + else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */ + { + /* + ** Following space is optional, don't include the - + */ + + *passThroughArgs = cstringList_add (*passThroughArgs, + cstring_fromCharsNew (thisarg + 1)); + } + else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH) + { + if (mstring_length (thisarg) < 2) { + BADBRANCH; + } else { + if (mstring_equal (thisarg, "-I-")) { + cppAddIncludeDir (cstring_fromChars (thisarg)); /* Need to handle this specially. */ + } else { + cstring dir = cstring_suffix (cstring_fromChars (thisarg), 2); /* skip over -I */ + + DPRINTF (("Length of thisarg [%s] %d", thisarg, cstring_length (thisarg))); + + if (cstring_length (dir) == 0) { + DPRINTF (("space after directory: ")); + if (++i < argc) { + dir = cstring_fromChars (argv[i]); + } else { + voptgenerror + (FLG_BADFLAG, + message + ("Flag %s must be followed by a directory name", + flagcode_unparse (opt)), + g_currentloc); + } + } + + DPRINTF (("Got directory: [%s]", dir)); + + switch (opt) + { + case FLG_INCLUDEPATH: + cppAddIncludeDir (dir); + /*@switchbreak@*/ break; + case FLG_SPECPATH: + /*@-mustfree@*/ + g_localSpecPath = cstring_toCharsSafe + (message ("%s%h%s", + cstring_fromChars (g_localSpecPath), + PATH_SEPARATOR, + dir)); + /*@=mustfree@*/ + /*@switchbreak@*/ break; + BADDEFAULT; + } + } + } + } + else if (flagcode_isModeName (opt)) + { + context_setMode (flagname); + } + else if (inCommandLine && flagcode_isMessageControlFlag (opt)) + { + /* + ** Processed on first pass + */ + + if (flagcode_hasArgument (opt)) + { + ++i; + } + } + else + { + /* + ** A normal control flag + */ + + context_userSetFlag (opt, set); + + if (flagcode_hasArgument (opt)) + { + if (flagcode_hasNumber (opt)) + { + if (++i < argc) + { + flags_setValueFlag (opt, cstring_fromCharsNew (argv[i])); + } + else + { + voptgenerror + (FLG_BADFLAG, + message + ("Flag %s must be followed by a number", + flagcode_unparse (opt)), + g_currentloc); + } + } + else if (flagcode_hasChar (opt)) + { + if (++i < argc) + { + flags_setValueFlag (opt, cstring_fromCharsNew (argv[i])); + } + else + { + voptgenerror + (FLG_BADFLAG, + message + ("Flag %s must be followed by a character", + flagcode_unparse (opt)), + g_currentloc); + } + } + else if (flagcode_hasString (opt) + || opt == FLG_INIT || opt == FLG_OPTF) + { + if (++i < argc) + { + /*drl 10/21/2002 + Changed this because arg can be freed when it's passed to + lslinit_setInitFile and freeing argv[i] causes a seg fault + */ + cstring arg = cstring_fromCharsNew (argv[i]); + + if (opt == FLG_OPTF) + { + if (inCommandLine) + { + ; /* -f already processed */ + } + else + { + (void) rcfiles_read (arg, passThroughArgs, TRUE); + } + } + else if (opt == FLG_INIT) + { + lslinit_setInitFile (inputStream_create + (arg, + cstring_makeLiteralTemp (LCLINIT_SUFFIX), + FALSE)); + break; + } + else + { + DPRINTF (("String flag: %s / %s", + flagcode_unparse (opt), arg)); + if (opt == FLG_MTSFILE) + { + /* + ** arg identifies mts files + */ + cstring tmp = message ("%s%s", arg, MTS_EXTENSION); + addLarchPathFile (mtfiles, tmp); + cstring_free (tmp); + tmp = message ("%s%s", arg, XH_EXTENSION); + addXHFile (xfiles, tmp); + cstring_free (tmp); + } + else + { + flags_setStringFlag (opt, cstring_copy (arg)); + } + } + } + else + { + voptgenerror + (FLG_BADFLAG, + message + ("Flag %s must be followed by a string", + flagcode_unparse (opt)), + g_currentloc); + } + } + else + { + /* no argument */ + } + } + } + } + else /* its a filename */ + { + DPRINTF (("Adding filename: %s", thisarg)); + fl = cstringSList_add (fl, cstring_fromChars (thisarg)); + } + } + + /* + ** create lists of C and LCL files + */ + + if (inCommandLine) + { + cstringSList_elements (fl, current) + { + cstring ext = fileLib_getExtension (current); + + if (cstring_isUndefined (ext)) + { + /* no extension --- both C and LCL with default extensions */ + + addFile (cfiles, message ("%s%s", current, C_EXTENSION)); + addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION)); + } + else if (cstring_equal (ext, XH_EXTENSION)) + { + addXHFile (xfiles, current); + } + else if (cstring_equal (ext, PP_EXTENSION)) + { + if (!context_getFlag (FLG_NOPP)) + { + voptgenerror + (FLG_FILEEXTENSIONS, + message ("File extension %s used without +nopp flag (will be processed as C source code): %s", + ext, current), + g_currentloc); + } + + addFile (cfiles, cstring_copy (current)); + } + else if (cstring_equal (ext, LCL_EXTENSION)) + { + addFile (lclfiles, cstring_copy (current)); + } + else if (fileLib_isCExtension (ext)) + { + addFile (cfiles, cstring_copy (current)); + } + else if (cstring_equal (ext, MTS_EXTENSION)) + { + addLarchPathFile (mtfiles, current); + } + else + { + voptgenerror + (FLG_FILEEXTENSIONS, + message ("Unrecognized file extension: %s (assuming %s is C source code)", + current, ext), + g_currentloc); + + addFile (cfiles, cstring_copy (current)); + } + } end_cstringSList_elements; + } + else + { + if (cstringSList_size (fl) != 0) + { + /* Cannot list files in .splintrc files */ + voptgenerror (FLG_BADFLAG, + message ("Cannot list files in .splintrc files: %s (probable missing + or -)", + cstringSList_unparse (fl)), + g_currentloc); + } + } + + cstringSList_free (fl); /* evans 2002-07-12: why wasn't this reported!?? */ +} + +int flagcode_priority (/*@unused@*/ flagcode code) +{ + /* + ** For now, we do a really simple prioritization: all are 1 + */ + + return 1; +}