X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/06418c9be6102447488610751def5864d566aae7..16c024b587f5ddc115928d5cca7095508aa208d9:/src/flags.c diff --git a/src/flags.c b/src/flags.c index eb68c11..6738754 100644 --- a/src/flags.c +++ b/src/flags.c @@ -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: @@ -146,6 +149,10 @@ static /*@observer@*/ cstring argcode_unparse (argcode arg) # endif } +# ifdef WIN32 +# pragma warning (enable:4715) +# endif + typedef struct { flagkind main; flagkind sub; @@ -190,7 +197,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) /*@*/ ; @@ -221,6 +228,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. */ @@ -270,7 +304,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; @@ -286,7 +320,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))); } @@ -823,7 +857,7 @@ describeFlag (cstring flagname) } else { - if (isMode (flagname)) + if (flags_isModeName (flagname)) { cstring_free (oflagname); @@ -974,22 +1008,22 @@ 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 */ } cflag = canonicalizeFlag (s); @@ -1051,7 +1085,7 @@ flags_identifyFlagAux (cstring s, bool quiet) } else if (cstring_equalLit (cflag, "ansireservedlocal")) { - res = FLG_ANSIRESERVEDLOCAL; + res = FLG_ISORESERVEDLOCAL; } else if (cstring_equalLit (cflag, "warnposix")) { @@ -1081,6 +1115,14 @@ flags_identifyFlagAux (cstring s, bool quiet) { 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... */ @@ -1095,15 +1137,15 @@ flags_identifyFlagAux (cstring s, bool quiet) } else if (cstring_equalLit (cflag, "skipansiheaders")) { - res = FLG_SKIPANSIHEADERS; + res = FLG_SKIPISOHEADERS; } else if (cstring_equalLit (cflag, "ansireserved")) { - res = FLG_ANSIRESERVED; + res = FLG_ISORESERVED; } else if (cstring_equalLit (cflag, "ansireservedinternal")) { - res = FLG_ANSIRESERVEDLOCAL; + res = FLG_ISORESERVEDLOCAL; } /* @@ -1180,6 +1222,23 @@ flags_identifyFlagAux (cstring s, bool quiet) 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) @@ -1194,6 +1253,10 @@ flags_identifyFlagAux (cstring s, bool quiet) res = SKIP_FLAG; } + else if (flags_isModeName (cflag)) + { + res = MODENAME_FLAG; + } else { res = INVALID_FLAG; @@ -1204,7 +1267,7 @@ flags_identifyFlagAux (cstring s, bool quiet) return res; } -void setValueFlag (flagcode opt, cstring arg) +void flags_setValueFlag (flagcode opt, cstring arg) { switch (opt) { @@ -1213,6 +1276,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: @@ -1254,11 +1318,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) { @@ -1355,7 +1419,7 @@ listModes (void) # endif bool -isMode (cstring s) +flags_isModeName (cstring s) { allModes (modename) { @@ -1501,4 +1565,411 @@ 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 = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */ + flagcode 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; +}