X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/b37cf05e81a9ef7fc429327a75dfad628f86c809..27c9e6405d13abd5a1f1f0bae1ec7bb873abadea:/src/llmain.c diff --git a/src/llmain.c b/src/llmain.c index 38f9426..1d9c6b5 100644 --- a/src/llmain.c +++ b/src/llmain.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-2002 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -19,16 +19,16 @@ ** ** 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 more information: http://www.splint.org */ /* ** llmain.c ** -** Main module for LCLint checker +** Main module for Splint annotation-assisted program checker */ # include - +# include /* ** Ensure that WIN32 and _WIN32 are both defined or both undefined. */ @@ -70,15 +70,12 @@ # endif # include "version.h" -# include "herald.h" # include "fileIdList.h" # include "lcllib.h" # include "cgrammar.h" # include "llmain.h" # include "portab.h" -# include "cpp.h" -# include "mtreader.h" -# include + extern /*@external@*/ int yydebug; @@ -94,7 +91,13 @@ static void cleanupFiles (void); static void showHelp (void); static void interrupt (int p_i); -static void loadrc (/*@open@*/ FILE *p_rcfile, cstringSList *p_passThroughArgs) +static bool readOptionsFile (cstring p_fname, + cstringSList *p_passThroughArgs, + bool p_report) + /*@modifies fileSystem, internalState, *p_passThroughArgs@*/ ; + +static void loadrc (FILE *p_rcfile, cstringSList *p_passThroughArgs) + /*@modifies *p_passThroughArgs, p_rcfile@*/ /*@ensures closed p_rcfile@*/ ; static void describeVars (void); @@ -327,12 +330,12 @@ lslProcess (fileIdList lclfiles) { if (mstring_equal (g_localSpecPath, ".")) { - lldiagmsg (message ("Spec file not found: %s", fname)); + lldiagmsg (message ("Spec file not found: %q", osd_outputPath (fname))); } else { - lldiagmsg (message ("Spec file not found: %s (on %s)", - fname, + lldiagmsg (message ("Spec file not found: %q (on %s)", + osd_outputPath (fname), cstring_fromChars (g_localSpecPath))); } } @@ -370,8 +373,8 @@ lslProcess (fileIdList lclfiles) if (!inputStream_open (specFile)) { - lldiagmsg (message ("Cannot open file: %s", - inputStream_fileName (specFile))); + lldiagmsg (message ("Cannot open file: %q", + osd_outputPath (inputStream_fileName (specFile)))); inputStream_free (specFile); } else @@ -488,9 +491,10 @@ static void handlePassThroughFlag (char *arg) if (open) { showHerald (); - llerror (FLG_BADFLAG, - message ("Unclosed quote in flag: %s", - cstring_fromChars (arg))); + voptgenerror (FLG_BADFLAG, + message ("Unclosed quote in flag: %s", + cstring_fromChars (arg)), + g_currentloc); } else { @@ -523,27 +527,61 @@ void showHerald (void) else { - fprintf (g_msgstream, "%s\n\n", LCL_VERSION); + fprintf (g_msgstream, "%s\n\n", SPLINT_VERSION); hasShownHerald = TRUE; llflush (); } } -static void addFile (fileIdList files, /*@only@*/ cstring s) +static cstring findLarchPathFile (/*@temp@*/ cstring s) { - if (fileTable_exists (context_fileTable (), 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 ("File listed multiple times: %s", s)); - cstring_free (s); + lldiagmsg (message ("Cannot find file on LARCHPATH: %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 { - fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s)); + BADBRANCH; } + + return cstring_undefined; } -static void addXHFile (fileIdList files, /*@only@*/ cstring s) +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)) { @@ -553,11 +591,30 @@ static void addXHFile (fileIdList files, /*@only@*/ cstring s) } else { - fileIdList_add (files, fileTable_addXHFile (context_fileTable (), s)); - cstring_free (s); + 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); +} + /* ** Disable MSVC++ warning about return value. Methinks humbly lclint control ** comments are a mite more legible. @@ -604,6 +661,10 @@ int main (int argc, char *argv[]) clock_t before, lcltime, libtime, pptime, cptime, rstime; int i = 0; +# ifdef __EMX__ + _wildcard (&argc, &argv); +# endif + g_msgstream = stdout; (void) signal (SIGINT, interrupt); @@ -618,6 +679,8 @@ int main (int argc, char *argv[]) clabstract_initMod (); typeIdSet_initMod (); cppReader_initMod (); + osd_initMod (); + setCodePoint (); g_currentloc = fileloc_createBuiltin (); @@ -641,8 +704,7 @@ int main (int argc, char *argv[]) */ { - cstring incval = cstring_copy - (osd_getEnvironmentVariable (cstring_makeLiteralTemp (INCLUDE_VAR))); + cstring incval = cstring_copy (osd_getEnvironmentVariable (INCLUDEPATH_VAR)); cstring oincval = incval; if (cstring_isDefined (incval)) @@ -657,7 +719,7 @@ int main (int argc, char *argv[]) while (cstring_isDefined (incval)) { /*@access cstring@*/ - char *nextsep = strchr (incval, SEPCHAR); + char *nextsep = strchr (incval, PATH_SEPARATOR); if (nextsep != NULL) { @@ -678,7 +740,7 @@ int main (int argc, char *argv[]) cppAddIncludeDir (dir); } - *nextsep = SEPCHAR; + *nextsep = PATH_SEPARATOR; incval = cstring_fromChars (nextsep + 1); cstring_free (dir); } @@ -690,6 +752,16 @@ int main (int argc, char *argv[]) /*@noaccess cstring@*/ } } + else /* 2001-09-09: herbert */ + { + /* Put C_INCLUDE_PATH directories in sysdirs */ + cstring cincval = osd_getEnvironmentVariable (cstring_makeLiteralTemp ("C_INCLUDE_PATH")); + if (cstring_isDefined (cincval)) + { + context_setString (FLG_SYSTEMDIRS, cstring_copy (cincval)); + } + } + /* /herbert */ cstring_free (oincval); } @@ -700,8 +772,7 @@ int main (int argc, char *argv[]) { cstring home = osd_getHomeDir (); - char *fname = NULL; - FILE *rcfile; + cstring fname = cstring_undefined; bool defaultf = TRUE; bool nof = FALSE; @@ -712,35 +783,36 @@ int main (int argc, char *argv[]) if (*thisarg == '-' || *thisarg == '+') { + bool set = (*thisarg == '+'); + flagcode opt; + thisarg++; - if (mstring_equal (thisarg, "nof")) + /* + ** Don't report warnings this time + */ + + opt = flags_identifyFlagQuiet (cstring_fromChars (thisarg)); + + if (opt == FLG_NOF) { nof = TRUE; } - else if (mstring_equal (thisarg, "f")) + else if (opt == FLG_SHOWSCAN || opt == FLG_WARNRC) + { + /* + ** Need to set it immediately, so rc file scan is displayed + */ + + context_userSetFlag (opt, set); + } + else if (opt == FLG_OPTF) { if (++i < argc) { defaultf = FALSE; - fname = argv[i]; - rcfile = fopen (fname, "r"); - - if (rcfile != NULL) - { - fileloc oloc = g_currentloc; - - g_currentloc = fileloc_createRc (cstring_fromChars (fname)); - loadrc (rcfile, &passThroughArgs); - fileloc_reallyFree (g_currentloc); - g_currentloc = oloc; - } - else - { - showHerald (); - lldiagmsg (message ("Options file not found: %s", - cstring_fromChars (fname))); - } + fname = cstring_fromChars (argv[i]); + (void) readOptionsFile (fname, &passThroughArgs, TRUE); } else llfatalerror @@ -753,55 +825,75 @@ int main (int argc, char *argv[]) } } } - - if (fname == NULL) - { - if (!cstring_isEmpty (home)) { - fname = cstring_toCharsSafe (message ("%s%h%s", home, CONNECTCHAR, - cstring_fromChars (RCFILE))); - mstring_markFree (fname); - } - } - + setCodePoint (); if (!nof && defaultf) { - if (!mstring_isEmpty (fname)) { - rcfile = fopen (fname, "r"); - - if (rcfile != NULL) - { - fileloc oloc = g_currentloc; - - g_currentloc = fileloc_createRc (cstring_fromChars (fname)); - loadrc (rcfile, &passThroughArgs); - fileloc_reallyFree (g_currentloc); - g_currentloc = oloc; - } - } - -# if defined(MSDOS) || defined(OS2) - fname = cstring_toCharsSafe (message ("%s", - cstring_fromChars (RCFILE))); -# else - fname = cstring_toCharsSafe (message ("./%s", - cstring_fromChars (RCFILE))); -# endif - - rcfile = fopen (fname, "r"); + /* + ** No explicit rc file, first try reading ~/.splintrc + */ - if (rcfile != NULL) + if (cstring_isUndefined (fname)) { - fileloc oloc = g_currentloc; + if (!cstring_isEmpty (home)) + { + bool readhomerc, readaltrc; + cstring homename, altname; + + homename = message ("%s%h%s", home, CONNECTCHAR, + cstring_fromChars (RCFILE)); + readhomerc = readOptionsFile (homename, &passThroughArgs, FALSE); + + /* + ** Try ~/.lclintrc also for historical accuracy + */ + + altname = message ("%s%h%s", home, CONNECTCHAR, + cstring_fromChars (ALTRCFILE)); + readaltrc = readOptionsFile (altname, &passThroughArgs, FALSE); + + if (readhomerc && readaltrc) + { + + voptgenerror + (FLG_WARNRC, + message ("Found both %s and %s files. Using both files, " + "but recommend using only %s to avoid confusion.", + homename, altname, homename), + g_currentloc); + } - g_currentloc = fileloc_createRc (cstring_fromChars (fname)); - loadrc (rcfile, &passThroughArgs); - fileloc_reallyFree (g_currentloc); - g_currentloc = oloc; + cstring_free (homename); + cstring_free (altname); + } } + + /* + ** Next, read .splintrc in the current working directory + */ + + { + cstring rcname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (RCFILE)); + cstring altname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (ALTRCFILE)); + bool readrc, readaltrc; + + readrc = readOptionsFile (rcname, &passThroughArgs, FALSE); + readaltrc = readOptionsFile (altname, &passThroughArgs, FALSE); + + if (readrc && readaltrc) + { + voptgenerror (FLG_WARNRC, + message ("Found both %s and %s files. Using both files, " + "but recommend using only %s to avoid confusion.", + rcname, altname, rcname), + g_currentloc); + + } - sfree (fname); + cstring_free (rcname); + cstring_free (altname); + } } } @@ -913,11 +1005,12 @@ int main (int argc, char *argv[]) flagname = cstring_fromChars (thisarg); DPRINTF (("Flag: %s", flagname)); - opt = identifyFlag (flagname); + opt = flags_identifyFlag (flagname); DPRINTF (("Flag: %s", flagcode_unparse (opt))); - if (flagcode_isSkip (opt)) + if (flagcode_isSkip (opt) || opt == FLG_SHOWSCAN || opt == FLG_WARNRC) { + /* showscan already processed */ DPRINTF (("Skipping!")); } else if (flagcode_isInvalid (opt)) @@ -931,8 +1024,10 @@ int main (int argc, char *argv[]) else { DPRINTF (("Error!")); - llgloberror (message ("Unrecognized option: %s", - cstring_fromChars (thisarg))); + voptgenerror (FLG_BADFLAG, + message ("Unrecognized option: %s", + cstring_fromChars (thisarg)), + g_currentloc); } } else @@ -978,7 +1073,7 @@ int main (int argc, char *argv[]) g_localSpecPath = cstring_toCharsSafe (message ("%s%h%s", cstring_fromChars (g_localSpecPath), - SEPCHAR, + PATH_SEPARATOR, dir)); /*@=mustfree@*/ /*@switchbreak@*/ break; @@ -1015,9 +1110,12 @@ int main (int argc, char *argv[]) /* ** arg identifies mts files */ - - addFile (mtfiles, message ("%s%s", arg, MTS_EXTENSION)); - addXHFile (xfiles, message ("%s%s", arg, XH_EXTENSION)); + 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 { @@ -1049,7 +1147,8 @@ int main (int argc, char *argv[]) } setCodePoint (); - + showHerald (); + /* ** create lists of C and LCL files */ @@ -1067,7 +1166,20 @@ int main (int argc, char *argv[]) } else if (cstring_equal (ext, XH_EXTENSION)) { - addXHFile (xfiles, cstring_copy (current)); + 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)) { @@ -1079,7 +1191,7 @@ int main (int argc, char *argv[]) } else if (cstring_equal (ext, MTS_EXTENSION)) { - addFile (mtfiles, cstring_copy (current)); + addLarchPathFile (mtfiles, current); } else { @@ -1093,8 +1205,6 @@ int main (int argc, char *argv[]) } } end_cstringSList_elements; - showHerald (); /*@i723 move earlier? */ - if (showhelp) { if (allhelp) @@ -1181,7 +1291,7 @@ int main (int argc, char *argv[]) if (anylcl) { # ifdef NOLCL - llfatalerror (cstring_makeLiteral ("This version of LCLint does not handle LCL files.")); + llfatalerror (cstring_makeLiteral ("This version of Splint does not handle LCL files.")); # else lslProcess (lclfiles); # endif @@ -1296,7 +1406,7 @@ int main (int argc, char *argv[]) if (context_getFlag (FLG_SHOWSCAN)) { - lldiagmsg (message ("< checking %s >", rootFileName (fid))); + lldiagmsg (message ("< checking %q >", osd_outputPath (rootFileName (fid)))); } /* @@ -1413,7 +1523,7 @@ int main (int argc, char *argv[]) if (nspecErrors == context_getLCLExpect ()) { specErrors = - message ("%d spec error%& found, as expected\n ", + message ("%d spec warning%&, as expected\n ", nspecErrors); } else @@ -1421,13 +1531,13 @@ int main (int argc, char *argv[]) if (context_getLCLExpect () > 0) { specErrors = - message ("%d spec error%& found, expected %d\n ", + message ("%d spec warning%&, expected %d\n ", nspecErrors, (int) context_getLCLExpect ()); } else { - specErrors = message ("%d spec error%& found\n ", + specErrors = message ("%d spec warning%&\n ", nspecErrors); expsuccess = FALSE; } @@ -1437,7 +1547,7 @@ int main (int argc, char *argv[]) { if (context_getLCLExpect () > 0) { - specErrors = message ("No spec errors found, expected %d\n ", + specErrors = message ("No spec warnings, expected %d\n ", (int) context_getLCLExpect ()); expsuccess = FALSE; } @@ -1449,8 +1559,8 @@ int main (int argc, char *argv[]) if (context_numErrors () == context_getExpect ()) { if (!isQuiet) { - llmsg (message ("Finished LCLint checking --- " - "%s%d code error%& found, as expected", + llmsg (message ("Finished checking --- " + "%s%d code warning%&, as expected", specErrors, context_numErrors ())); } } @@ -1460,8 +1570,8 @@ int main (int argc, char *argv[]) { if (!isQuiet) { llmsg (message - ("Finished LCLint checking --- " - "%s%d code error%& found, expected %d", + ("Finished checking --- " + "%s%d code warning%&, expected %d", specErrors, context_numErrors (), (int) context_getExpect ())); } @@ -1473,8 +1583,8 @@ int main (int argc, char *argv[]) if (!isQuiet) { - llmsg (message ("Finished LCLint checking --- " - "%s%d code error%& found", + llmsg (message ("Finished checking --- " + "%s%d code warning%&", specErrors, context_numErrors ())); } @@ -1488,8 +1598,8 @@ int main (int argc, char *argv[]) { if (!isQuiet) { llmsg (message - ("Finished LCLint checking --- " - "%sno code errors found, expected %d", + ("Finished checking --- " + "%sno code warnings, expected %d", specErrors, (int) context_getExpect ())); } @@ -1500,15 +1610,26 @@ int main (int argc, char *argv[]) { if (context_getLinesProcessed () > 0) { - if (!isQuiet) { - llmsg (message ("Finished LCLint checking --- %sno code errors found", - specErrors)); - } + if (cstring_isEmpty (specErrors)) + { + if (!isQuiet) + { + llmsg (message ("Finished checking --- no warnings")); + } + } + else + { + if (!isQuiet) + { + llmsg (message ("Finished checking --- %sno code warnings", + specErrors)); + } + } } else { if (!isQuiet) { - llmsg (message ("Finished LCLint checking --- %sno code processed", + llmsg (message ("Finished checking --- %sno code processed", specErrors)); } } @@ -1580,6 +1701,7 @@ int main (int argc, char *argv[]) } llexit (expsuccess ? LLSUCCESS : LLFAILURE); + BADBRANCHRET (LLFAILURE); } # ifdef WIN32 @@ -1596,9 +1718,9 @@ showHelp (void) llmsg (message ("Source files are .c, .h and %s files. If there is no suffix,", LCL_EXTENSION)); - llmsg (message (" LCLint will look for .c and %s.", LCL_EXTENSION)); + llmsg (message (" Splint will look for .c and %s.", LCL_EXTENSION)); llmsglit (""); - llmsglit ("Use lclint -help for more information"); + llmsglit ("Use splint -help for more information"); llmsglit (""); llmsglit ("Topics:"); llmsglit (""); @@ -1672,12 +1794,12 @@ printParseErrors (void) "it is not advisible to use these, oftentimes one has no choice " "when the system header files use compiler extensions. "); llmsglit (""); - llmsglit ("LCLint supports some of the GNU (gcc) compiler extensions, " + llmsglit ("Splint supports some of the GNU (gcc) compiler extensions, " "if the +gnuextensions flag is set. You may be able to workaround " "other compiler extensions by using a pre-processor define. " "Alternately, you can surround the unparseable code with"); llmsglit (""); - llmsglit (" # ifndef __LCLINT__"); + llmsglit (" # ifndef S_SPLINT_S"); llmsglit (" ..."); llmsglit (" # endif"); llmsglit (""); @@ -1685,7 +1807,7 @@ printParseErrors (void) llmsglit ("Missing type definitions --- an undefined type name will usually " "lead to a parse error. This often occurs when a standard header " "file defines some type that is not part of the standard library. "); - llmsglit ("By default, LCLint does not process the local files corresponding " + llmsglit ("By default, Splint does not process the local files corresponding " "to standard library headers, but uses a library specification " "instead so dependencies on local system headers can be detected. " "If another system header file that does not correspond to a " @@ -1693,7 +1815,7 @@ printParseErrors (void) "a parse error will result."); llmsglit (""); llmsglit ("If the parse error is inside a posix standard header file, the " - "first thing to try is +posixlib. This make LCLint use " + "first thing to try is +posixlib. This makes Splint use " "the posix library specification instead of reading the posix " "header files."); llmsglit (""); @@ -1713,9 +1835,9 @@ printParseErrors (void) llmsglit (" /*@=skipposixheaders@*/"); llmsglit (" # include "); llmsglit (""); - llmsglit ("to force LCLint to process ."); + llmsglit ("to force Splint to process ."); llmsglit (""); - llmsglit ("At last resort, +trytorecover can be used to make LCLint attempt " + llmsglit ("At last resort, +trytorecover can be used to make Splint attempt " "to continue after a parse error. This is usually not successful " "and the author does not consider assertion failures when +trytorecover " "is used to be bugs."); @@ -1814,11 +1936,11 @@ printAnnotations (void) llmsglit (" /*@falsenull@*/ - if result is TRUE, first parameter is not NULL"); llmsglit (""); llmsglit ("Execution:"); - llmsglit (" /*@exits@*/ - function never returns"); - llmsglit (" /*@mayexit@*/ - function may or may not return"); - llmsglit (" /*@trueexit@*/ - function does not return if first parameter is TRUE"); - llmsglit (" /*@falseexit@*/ - function does not return if first parameter if FALSE"); - llmsglit (" /*@neverexit@*/ - function always returns"); + llmsglit (" /*@noreturn@*/ - function never returns"); + llmsglit (" /*@maynotreturn@*/ - function may or may not return"); + llmsglit (" /*@noreturnwhentrue@*/ - function does not return if first parameter is TRUE"); + llmsglit (" /*@noreturnwhenfalse@*/ - function does not return if first parameter if FALSE"); + llmsglit (" /*@alwaysreturns@*/ - function always returns"); llmsglit (""); llmsglit ("Side-Effects:"); llmsglit (" /*@sef@*/ - corresponding actual parameter has no side effects"); @@ -1873,7 +1995,7 @@ printComments (void) llmsglit ("/*@i@*/"); llgenindentmsgnoloc (cstring_makeLiteral - ("No errors will be reported from an /*@i@*/ (e.g., /*@i3@*/) comment to the end of the line. If there are not exactly n errors suppressed from the comment point to the end of the line, LCLint will report an error.")); + ("No errors will be reported from an /*@i@*/ (e.g., /*@i3@*/) comment to the end of the line. If there are not exactly n errors suppressed from the comment point to the end of the line, Splint will report an error.")); llmsglit ("/*@t@*/, /*@t@*/"); llgenindentmsgnoloc (cstring_makeLiteral @@ -1921,7 +2043,7 @@ printMail (void) llmsglit ("Mailing Lists"); llmsglit ("-------------"); llmsglit (""); - llmsglit ("There are two mailing lists associated with LCLint: "); + llmsglit ("There are two mailing lists associated with Splint: "); llmsglit (""); llmsglit (" lclint-announce@virginia.edu"); llmsglit (""); @@ -1942,24 +2064,7 @@ printReferences (void) llmsglit ("References"); llmsglit ("----------"); llmsglit (""); - llmsglit ("The LCLint web site is http://lclint.cs.virginia.edu"); - llmsglit (""); - llmsglit ("Technical papers relating to LCLint include:"); - llmsglit (""); - llmsglit (" David Evans. \"Static Detection of Dynamic Memory Errors\"."); - llmsglit (" SIGPLAN Conference on Programming Language Design and "); - llmsglit (" Implementation (PLDI '96), Philadelphia, PA, May 1996."); - llmsglit (""); - llmsglit (" David Evans, John Guttag, Jim Horning and Yang Meng Tan. "); - llmsglit (" \"LCLint: A Tool for Using Specifications to Check Code\"."); - llmsglit (" SIGSOFT Symposium on the Foundations of Software Engineering,"); - llmsglit (" December 1994."); - llmsglit (""); - llmsglit ("A general book on Larch is:"); - llmsglit (""); - llmsglit (" Guttag, John V., Horning, James J., (with Garland, S. J., Jones, "); - llmsglit (" K. D., Modet, A., and Wing, J. M.), \"Larch: Languages and Tools "); - llmsglit (" for Formal Specification\", Springer-Verlag, 1993."); + llmsglit ("For more information, see the Splint web site: http://www.splint.org"); } void @@ -2020,13 +2125,18 @@ describeVars (void) llmsglit (" --- directory containing lcl standard library files " "(import with < ... >)");; - { - cstring dirs = context_getString (FLG_SYSTEMDIRS); - llmsg (message - ("systemdirs = %s (set by include envirnoment variable or -systemdirs)", - dirs)); + llmsg (message + ("include path = %q (set by environment variable %s and -I flags)", + cppReader_getIncludePath (), INCLUDEPATH_VAR)); - } + llmsglit (" --- path used to find #include'd files"); + + llmsg (message + ("systemdirs = %s (set by -systemdirs or environment variable %s)", /*@i413223@*/ + context_getString (FLG_SYSTEMDIRS), + INCLUDEPATH_VAR)); + + llmsglit (" --- if file is found on this path, it is treated as a system file for error reporting"); } void @@ -2081,6 +2191,13 @@ cleanupFiles (void) setCodePoint (); + /* + ** Close all open files + ** (There should only be open files, if we exited after a fatal error.) + */ + + fileTable_closeAll (context_fileTable ()); + if (context_getFlag (FLG_KEEP)) { check (fputs ("Temporary files kept:\n", stderr) != EOF); @@ -2103,11 +2220,10 @@ cleanupFiles (void) } /* -** cleans up temp files (if necessary) -** exits lclint +** cleans up temp files (if necessary) and exits */ -/*@exits@*/ void +/*@noreturn@*/ void llexit (int status) { DPRINTF (("llexit: %d", status)); @@ -2138,13 +2254,67 @@ llexit (int status) exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE); } +bool readOptionsFile (cstring fname, cstringSList *passThroughArgs, bool report) +{ + bool res = FALSE; + + if (fileTable_exists (context_fileTable (), fname)) + { + if (report) + { + voptgenerror + (FLG_WARNRC, + message ("Multiple attempts to read options file: %s", fname), + g_currentloc); + } + } + else + { + FILE *innerf = fileTable_openFile (context_fileTable (), fname, "r"); + + if (innerf != NULL) + { + fileloc fc = g_currentloc; + g_currentloc = fileloc_createRc (fname); + + if (context_getFlag (FLG_SHOWSCAN)) + { + lldiagmsg (message ("< reading options from %q >", + fileloc_outputFilename (g_currentloc))); + } + + loadrc (innerf, passThroughArgs); + fileloc_reallyFree (g_currentloc); + g_currentloc = fc; + res = TRUE; + } + else + { + if (report) + { + voptgenerror + (FLG_WARNRC, + message ("Cannot open options file: %s", fname), + g_currentloc); + } + } + } + + return res; +} + +/* +** This shouldn't be necessary, but Apple Darwin can't handle '"''s. +*/ + void -loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) - /*@ensures closed rcfile@*/ +loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs) + /*@modifies rcfile@*/ + /*@ensures closed rcfile@*/ { char *s = mstring_create (MAX_LINE_LENGTH); char *os = s; - + DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs))); s = os; @@ -2187,10 +2357,11 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) else { showHerald (); - llerror (FLG_SYNTAX, - message ("Bad flag syntax (+ or - expected, " - "+ is assumed): %s", - cstring_fromChars (s))); + voptgenerror (FLG_BADFLAG, + message ("Bad flag syntax (+ or - expected, " + "+ is assumed): %s", + cstring_fromChars (s)), + g_currentloc); s--; set = TRUE; } @@ -2248,7 +2419,7 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) DPRINTF (("Flag: %s", thisflag)); - opt = identifyFlag (cstring_fromChars (thisflag)); + opt = flags_identifyFlag (cstring_fromChars (thisflag)); if (flagcode_isSkip (opt)) { @@ -2264,9 +2435,10 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) } else { - llerror (FLG_BADFLAG, - message ("Unrecognized option: %s", - cstring_fromChars (thisflag))); + voptgenerror (FLG_BADFLAG, + message ("Unrecognized option: %s", + cstring_fromChars (thisflag)), + g_currentloc); } } else @@ -2278,8 +2450,9 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) if (opt == FLG_HELP) { showHerald (); - llerror (FLG_BADFLAG, - message ("Cannot use help in rc files")); + voptgenerror (FLG_BADFLAG, + message ("Cannot use help in rc files"), + g_currentloc); } else if (flagcode_isPassThrough (opt)) /* -D or -U */ { @@ -2345,11 +2518,12 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) if (cstring_isUndefined (extra)) { showHerald (); - llerror + voptgenerror (FLG_BADFLAG, message ("Flag %s must be followed by an argument", - flagcode_unparse (opt))); + flagcode_unparse (opt)), + g_currentloc); } else { @@ -2361,29 +2535,10 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) { DPRINTF (("Set value flag: %s", extra)); setValueFlag (opt, extra); - cstring_free (extra); } else if (opt == FLG_OPTF) { - FILE *innerf = fopen (cstring_toCharsSafe (extra), "r"); - cstring_markOwned (extra); - - if (innerf != NULL) - { - fileloc fc = g_currentloc; - g_currentloc = fileloc_createRc (extra); - loadrc (innerf, passThroughArgs); - fileloc_reallyFree (g_currentloc); - g_currentloc = fc; - } - else - { - showHerald (); - llerror - (FLG_SYNTAX, - message ("Options file not found: %s", - extra)); - } + (void) readOptionsFile (extra, passThroughArgs, TRUE); } else if (opt == FLG_INIT) { @@ -2391,43 +2546,56 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) llassert (inputStream_isUndefined (initFile)); initFile = inputStream_create - (extra, + (cstring_copy (extra), cstring_makeLiteralTemp (LCLINIT_SUFFIX), FALSE); -# else - cstring_free (extra); # endif } else if (flagcode_hasString (opt)) { - if (cstring_firstChar (extra) == '"') + DPRINTF (("Here: %s", extra)); + + /* + ** If it has "'s, we need to remove them. + */ + + if (cstring_firstChar (extra) == '\"') { - if (cstring_lastChar (extra) == '"') + if (cstring_lastChar (extra) == '\"') { - char *extras = cstring_toCharsSafe (extra); - - llassert (extras[strlen(extras) - 1] == '"'); - extras[strlen(extras) - 1] = '\0'; - extra = cstring_fromChars (extras + 1); - DPRINTF (("Remove quites: %s", extra)); + cstring unquoted = cstring_copyLength + (cstring_toCharsSafe (cstring_suffix (extra, 1)), + cstring_length (extra) - 2); + + DPRINTF (("string flag: %s -> %s", extra, unquoted)); + setStringFlag (opt, unquoted); + cstring_free (extra); } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_BADFLAG, message ("Unmatched \" in option string: %s", - extra)); + extra), + g_currentloc); + setStringFlag (opt, extra); } } - - setStringFlag (opt, extra); + else + { + DPRINTF (("No quotes: %s", extra)); + setStringFlag (opt, extra); + } + + extra = cstring_undefined; } else { - cstring_free (extra); BADEXIT; } } + + cstring_free (extra); } else { @@ -2450,7 +2618,7 @@ loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs) DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs))); sfree (os); - check (fclose (rcfile) == 0); + check (fileTable_closeFile (context_fileTable (), rcfile)); } static fileIdList preprocessFiles (fileIdList fl, bool xhfiles) @@ -2468,43 +2636,21 @@ static fileIdList preprocessFiles (fileIdList fl, bool xhfiles) { cstring ppfname = fileName (fid); - if (xhfiles) + if (!(osd_fileIsReadable (ppfname))) { - cstring fpath; - - if (osd_findOnLarchPath (ppfname, &fpath) == OSD_FILEFOUND) - { - if (cstring_equal (ppfname, fpath)) - { - ; - } - else - { - DPRINTF (("xh file: %s", fpath)); - ppfname = fpath; - fileTable_setFilePath (context_fileTable (), fid, fpath); - } - } - else - { - lldiagmsg (message ("Cannot find .xh file on LARCH_PATH: %s", ppfname)); - lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable.")); - ppfname = cstring_undefined; - } - } - else - { - if (!(osd_fileIsReadable (ppfname))) - { - lldiagmsg (message ("Cannot open file: %s", ppfname)); - ppfname = cstring_undefined; - } + lldiagmsg (message ("Cannot open file: %q", osd_outputPath (ppfname))); + ppfname = cstring_undefined; } if (cstring_isDefined (ppfname)) { fileId dfile = fileTable_addCTempFile (context_fileTable (), fid); - + + if (xhfiles) + { + llassert (fileTable_isXHFile (context_fileTable (), dfile)); + } + llassert (cstring_isNonEmpty (ppfname)); if (msg)