X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/616915ddfdcba888735f45cbd9c26c9b5383ee2c..2a3f24b83026515b6a9ce54a2ff4fb1eab2fe2f9:/src/flags.c diff --git a/src/flags.c b/src/flags.c index 4b70fa6..27e018e 100644 --- a/src/flags.c +++ b/src/flags.c @@ -1,6 +1,6 @@ /* -** LCLint - annotation-assisted static program checker -** Copyright (C) 1994-2000 University of Virginia, +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2002 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 "osd.h" # include "portab.h" +# include "rcfiles.h" +# include "lslinit.h" /* ** from the CC man page: @@ -54,9 +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 stylized 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 splint" } , { FK_DECL, "declarations", "consistency of declarations" } , { FK_DEF, "definition", "undefined storage errors" } , { FK_DIRECT, "directories", "set directores" } , @@ -65,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" } , @@ -92,13 +101,15 @@ static flagcatinfo categories[] = { FK_PROTOS, "prototypes", "function prototypes" } , { FK_DEAD, "released", "using storage that has been deallocated" } , { FK_IGNORERET, "returnvals", "ignored return values" }, + { FK_SECURITY, "security", "possible security vulnerability" }, { FK_SPEC, "specifications", "checks involving .lcl specifications" } , { FK_SUPPRESS, "suppress", "local and global suppression of messages" } , { FK_TYPEEQ, "typeequivalence", "control what types are equivalent" } , { FK_BEHAVIOR, "undefined", "code with undefined or implementation-defined behavior" } , { FK_UNRECOG, "unrecognized", "unrecognized identifiers" } , { FK_UNSPEC, "unconstrained", "checking in the presence of unconstrained functions" } , - { FK_DEBUG, NULL, NULL } , + { 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 } , @@ -108,11 +119,36 @@ 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; +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 +/* Make Microsoft VC++ happy */ +# pragma warning (disable:4715) +# endif +} + typedef struct { flagkind main; flagkind sub; @@ -152,10 +188,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) { @@ -182,6 +224,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. */ @@ -193,6 +262,11 @@ void flags_initMod () /*@+enumint@*/ if (flags[code].code != code) { + fprintf (stderr, + "*** ERROR: inconsistent flag %s / %d / %d", + flags[code].flag, + flags[code].code, code); + llbug (message ("*** ERROR: inconsistent flag %s / %d / %d", cstring_fromChars (flags[code].flag), flags[code].code, code)); @@ -263,6 +337,8 @@ flagcode_recordError (flagcode f) } else { + /*drl bee: ec*/ + /*drl bee: ec*/ flags[f].nreported = flags[f].nreported + 1; } } @@ -277,7 +353,8 @@ flagcode_recordSuppressed (flagcode f) { llassertprint (f != INVALID_FLAG, ("flagcode: %s", flagcode_unparse (f))); - flags[f].nsuppressed = flags[f].nsuppressed + 1; + /*drl bee: ec*/ + /*drl bee: ec*/ flags[f].nsuppressed = flags[f].nsuppressed + 1; } int @@ -293,6 +370,7 @@ flagcodeHint (flagcode f) { llassert (f != INVALID_FLAG); + /*drl bee: ec*/ if (mstring_isDefined (flags[f].hint)) { return (cstring_fromChars (flags[f].hint)); @@ -325,6 +403,7 @@ flagkind identifyCategory (cstring s) for (i = 0; categories[i].kind != FK_NONE; i++) { + /*drl bee: mRug*/ if (mstring_isDefined (categories[i].name)) { if (cstring_equalLit (s, categories[i].name)) @@ -343,6 +422,7 @@ static /*@observer@*/ cstring categoryName (flagkind kind) for (i = 0; categories[i].kind != FK_NONE; i++) { + /*drl bee: mrUg*/ if (categories[i].kind == kind) { return (cstring_fromChars (categories[i].name)); @@ -358,6 +438,7 @@ static int categoryIndex (flagkind kind) for (i = 0; categories[i].kind != FK_NONE; i++) { + /*drl bee: mRug*/ if (categories[i].kind == kind) { return i; @@ -372,7 +453,7 @@ void printCategory (flagkind kind) int index = categoryIndex (kind); llassert (index >= 0); - + /*drl bee: mRug*/ llmsg (message ("%s (%d flags)\n\3%s\n\n", cstring_fromChars (categories[index].name), categorySize (kind), @@ -395,6 +476,7 @@ listAllCategories (void) for (i = 0; categories[i].kind != FK_NONE; i++) { + /*drl bee: mRug*/ flagkind kind = categories[i].kind ; if (categories[i].describe != NULL) @@ -416,7 +498,11 @@ printAllFlags (bool desc, bool full) cstringSList_elements (fl, el) { - llmsg (message ("%q\n\n", describeFlag (el))); + /*@i22@*/ /*find out why this is necessary*/ + cstring tmp; + tmp = cstring_copy(el); + llmsg (message ("%q\n\n", describeFlag (tmp))); + cstring_free(tmp); } end_cstringSList_elements ; cstringSList_free (fl); @@ -440,12 +526,196 @@ 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 describeFlagCode (flagcode flag) { cstring ret = cstring_undefined; fflag f; - + if (flagcode_isInvalid (flag)) { return (cstring_makeLiteral ("")); @@ -453,9 +723,9 @@ describeFlagCode (flagcode flag) context_resetAllFlags (); + /*drl bee: mRug*/ f = flags[flag]; ret = cstring_copy (cstring_fromChars (f.desc)); - if (f.sub != FK_NONE) { @@ -477,40 +747,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); @@ -519,52 +768,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)) { @@ -586,12 +853,12 @@ 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)", + (message ("%s: predefined mode (see Manual for information)", flagname)); } else @@ -626,9 +893,15 @@ void printAlphaFlags () cstringSList_printSpaced (fl, 3, 1, context_getLineLen () - 25); cstringSList_free (fl); } + /*@observer@*/ cstring -flagcode_name (flagcode code) +flagcode_unparse (flagcode code) { + if (code == INVALID_FLAG) + { + return cstring_makeLiteralTemp (""); + } + return cstring_fromChars (flags[code].flag); } @@ -659,10 +932,11 @@ flagcode_name (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", @@ -689,23 +963,40 @@ canonicalizeFlag (cstring s) NULL } ; char *current; - + + /*drl bee: ia*/ 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; @@ -713,224 +1004,255 @@ 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")) + if (res == INVALID_FLAG) { - 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")) - { - return FLG_ANSILIMITS; - } - - /* - ** Obsolete Flags - */ - - if (cstring_equalLit (s, "accessunspec")) - { - flagWarning - (cstring_makeLiteralTemp - ("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")); + /* + ** Synonyms + */ - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "staticmods")) - { - flagWarning - (cstring_makeLiteralTemp - ("staticmods flag is obsolete. You probably " - "want impcheckmodstatics. For more information, " - "see lclint -help impcheckmodstatics")); - - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "bool")) - { - flagWarning - (cstring_makeLiteralTemp ("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; + } + /* + ** Backwards compatibility for our American friends... + */ - return SKIP_FLAG; - } - - if (cstring_equalLit (s, "ansi")) - { - flagWarning - (cstring_makeLiteralTemp ("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")) - { - flagWarning - (cstring_makeLiteralTemp - ("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) @@ -941,6 +1263,8 @@ void setValueFlag (flagcode opt, cstring arg) case FLG_LCLEXPECT: case FLG_LIMIT: case FLG_LINELEN: + case FLG_INDENTSPACES: + case FLG_BUGSLIMIT: case FLG_EXTERNALNAMELEN: case FLG_INTERNALNAMELEN: case FLG_CONTROLNESTDEPTH: @@ -962,7 +1286,7 @@ void setValueFlag (flagcode opt, cstring arg) } else { - context_setValueAndFlag (opt, val); + context_setValueAndFlag (opt, val); } } break; @@ -1024,7 +1348,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)) @@ -1057,7 +1381,8 @@ describeModes () return (s); } -static cstring +# if 0 +static /*@unused@*/ cstring listModes (void) { cstring s = cstring_makeLiteral ("\t"); @@ -1078,9 +1403,10 @@ listModes (void) return s; } +# endif bool -isMode (cstring s) +flags_isModeName (cstring s) { allModes (modename) { @@ -1101,14 +1427,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_VALUE); + return (flags[f].argtype == ARG_NUMBER); +} + +extern bool flagcode_hasChar (flagcode f) +{ + 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) @@ -1116,7 +1450,6 @@ extern int flagcode_valueIndex (flagcode f) /*@unchecked@*/ static bool initialized = FALSE; int i; /*@unchecked@*/ static flagcode valueFlags[NUMVALUEFLAGS]; - if (!initialized) { @@ -1124,30 +1457,38 @@ 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)); valueFlags[nv] = code; - nv++; + nv++; } } end_allFlagCodes; llassertprint (nv == NUMVALUEFLAGS, - ("number of value flags: %d (expected %d)", - nv, NUMVALUEFLAGS)); + ("Number of value flags: %d (expected %d)", + nv, (int) NUMVALUEFLAGS)); initialized = TRUE; } for (i = 0; i < NUMVALUEFLAGS; i++) { /* static valueFlags must be defined */ - /*@-usedef@*/ if (f == valueFlags[i]) /*@=usedef@*/ + /*@-usedef@*/ + /*drl bee: sta*/ + if (f == valueFlags[i]) /*@=usedef@*/ { return i; } } + fprintf (stderr, "Cannot find value flag: %d", (int) f); + exit (EXIT_FAILURE); + /* Cannot do this...might call recursively... + llfatalbug (message ("Cannot fine value flag: %d", (int) f)); BADEXIT; + */ } extern int flagcode_stringIndex (flagcode f) @@ -1179,6 +1520,7 @@ extern int flagcode_stringIndex (flagcode f) for (i = 0; i < NUMSTRINGFLAGS; i++) { + /*drl bee: sta*/ /*@-usedef@*/ if (f == stringFlags[i]) /*@=usedef@*/ { return i; @@ -1210,4 +1552,374 @@ 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, + cstringSList *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 (("thisarg: %s", thisarg)); + + if (*thisarg == '-' || *thisarg == '+') + { + bool set = (*thisarg == '+'); + cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */ + flagcode opt = flags_identifyFlag (flagname); + + DPRINTF (("Flag: %s", 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 = cstringSList_add (*passThroughArgs, + cstring_fromChars (thisarg + 1)); + } + else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH) + { + cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */ + + DPRINTF (("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 (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) + { + setValueFlag (opt, cstring_fromChars (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) + { + setValueFlag (opt, cstring_fromChars (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) + { + cstring arg = cstring_fromChars (argv[i]); + + if (opt == FLG_OPTF) + { + if (inCommandLine) + { + ; /* -f already processed */ + } + else + { + (void) rcfiles_read (arg, passThroughArgs, TRUE); + } + } + else if (opt == FLG_INIT) + { +# ifndef NOLCL + lslinit_setInitFile (inputStream_create + (arg, + cstring_makeLiteralTemp (LCLINIT_SUFFIX), + FALSE)); +# endif + 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 + { + 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); + } + } +}