X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/86d93ed383c14be2a4548bd8ab98e4c1a79cb1f0..2a3f24b83026515b6a9ce54a2ff4fb1eab2fe2f9:/src/flags.c diff --git a/src/flags.c b/src/flags.c index 6594881..27e018e 100644 --- a/src/flags.c +++ b/src/flags.c @@ -17,8 +17,8 @@ ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ** MA 02111-1307, USA. ** -** For information on splint: splint@cs.virginia.edu -** To report a bug: splint-bug@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 */ /* @@ -27,7 +27,10 @@ # include "splintMacros.nf" # include "basic.h" +# include "osd.h" # include "portab.h" +# include "rcfiles.h" +# include "lslinit.h" /* ** from the CC man page: @@ -140,6 +143,10 @@ static /*@observer@*/ cstring argcode_unparse (argcode arg) case ARG_SPECIAL: BADBRANCH; } +# ifdef WIN32 +/* Make Microsoft VC++ happy */ +# pragma warning (disable:4715) +# endif } typedef struct { @@ -186,7 +193,7 @@ 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_msgstream@*/ ; +static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ; # if 0 static /*@unused@*/ cstring listModes (void) /*@*/ ; @@ -217,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. */ @@ -464,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); @@ -815,7 +853,7 @@ describeFlag (cstring flagname) } else { - if (isMode (flagname)) + if (flags_isModeName (flagname)) { cstring_free (oflagname); @@ -894,10 +932,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", @@ -928,15 +967,16 @@ canonicalizeFlag (cstring s) /*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 @@ -954,6 +994,9 @@ flags_identifyFlagQuiet (cstring s) 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; @@ -961,247 +1004,255 @@ flags_identifyFlagAux (cstring s, bool quiet) 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")) + if (res == INVALID_FLAG) { - 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; - } - - /* - ** Backwards compatibility for our American friends... - */ - - if (cstring_equalLit (s, "ansilib")) - { - return FLG_ANSILIB; - } - - if (cstring_equalLit (s, "ansistrictlib")) - { - return FLG_STRICTLIB; - } - - if (cstring_equalLit (s, "skipansiheaders")) - { - return FLG_SKIPANSIHEADERS; - } - - if (cstring_equalLit (s, "ansireserved")) - { - return FLG_ANSIRESERVED; - } - - if (cstring_equalLit (s, "ansireservedinternal")) - { - return FLG_ANSIRESERVEDLOCAL; - } - - /* - ** Obsolete Flags - */ - - if (cstring_equalLit (s, "accessunspec")) - { - if (!quiet) + /* + ** Synonyms + */ + + if (cstring_equalLit (cflag, "pred")) { - 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 = 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; - } - else if (cstring_equalLit (s, "ansilimits")) - { + 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; + } + + /* + ** Obsolete Flags + */ + + 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.")); - - return SKIP_FLAG; - } - else if (cstring_equalLit (s, "staticmods")) - { - if (!quiet) + + res = SKIP_FLAG; + } + else if (cstring_equalLit (cflag, "staticmods")) { - llerror_flagWarning - (cstring_makeLiteral - ("staticmods flag is obsolete. You probably " - "want impcheckmodstatics. For more information, " - "see splint -help impcheckmodstatics")); + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral + ("staticmods flag is obsolete. You probably " + "want impcheckmodstatics. For more information, " + "see splint -help impcheckmodstatics")); + } + + res = SKIP_FLAG; } - - return SKIP_FLAG; - } - else if (cstring_equalLit (s, "bool")) - { - if (!quiet) + else if (cstring_equalLit (cflag, "bool")) { - llerror_flagWarning - (cstring_makeLiteral ("bool flag is obsolete. It never really " - "made sense in the first place.")); + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("bool flag is obsolete. It never really " + "made sense in the first place.")); + } + + res = SKIP_FLAG; } - - return SKIP_FLAG; - } - else if (cstring_equalLit (s, "shiftsigned")) - { - if (!quiet) + else if (cstring_equalLit (cflag, "shiftsigned")) { - llerror_flagWarning - (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably " - "want bitwisesigned, shiftnegative or shiftsize.")); + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("shiftsigned flag is obsolete. You probably " + "want bitwisesigned, shiftnegative or shiftimplementation.")); + } + + res = SKIP_FLAG; } - - return SKIP_FLAG; - } - else if (cstring_equalLit (s, "ansi")) - { - if (!quiet) + else if (cstring_equalLit (cflag, "ansi")) { - llerror_flagWarning - (cstring_makeLiteral ("ansi flag is obsolete. You probably " - "want noparams and/or oldstyle.")); + if (!quiet) + { + llerror_flagWarning + (cstring_makeLiteral ("ansi flag is obsolete. You probably " + "want noparams and/or oldstyle.")); + } + + res = SKIP_FLAG; } - - return SKIP_FLAG; - } - else if (cstring_equalLit (s, "stdio")) - { - if (!quiet) + else if (cstring_equalLit (cflag, "usestderr")) { - 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")); + 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 SKIP_FLAG; - } - else - { - return INVALID_FLAG; } + + cstring_free (cflag); + return res; } void setValueFlag (flagcode opt, cstring arg) @@ -1355,7 +1406,7 @@ listModes (void) # endif bool -isMode (cstring s) +flags_isModeName (cstring s) { allModes (modename) { @@ -1501,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); + } + } +}