X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/68de3f33cfd8b4bd66fe22f6069e2658082bdf58..27c9e6405d13abd5a1f1f0bae1ec7bb873abadea:/src/llmain.c diff --git a/src/llmain.c b/src/llmain.c index 5027191..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,12 +19,12 @@ ** ** 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 @@ -70,7 +70,6 @@ # endif # include "version.h" -# include "herald.h" # include "fileIdList.h" # include "lcllib.h" # include "cgrammar.h" @@ -92,8 +91,14 @@ static void cleanupFiles (void); static void showHelp (void); static void interrupt (int p_i); +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) - /*@ensures closed p_rcfile@*/ ; + /*@modifies *p_passThroughArgs, p_rcfile@*/ + /*@ensures closed p_rcfile@*/ ; static void describeVars (void); static bool specialFlagsHelp (char *p_next); @@ -325,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))); } } @@ -368,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 @@ -522,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)) { @@ -552,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. @@ -603,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); @@ -617,6 +679,8 @@ int main (int argc, char *argv[]) clabstract_initMod (); typeIdSet_initMod (); cppReader_initMod (); + osd_initMod (); + setCodePoint (); g_currentloc = fileloc_createBuiltin (); @@ -708,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; @@ -720,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 @@ -761,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) + { - g_currentloc = fileloc_createRc (cstring_fromChars (fname)); - loadrc (rcfile, &passThroughArgs); - fileloc_reallyFree (g_currentloc); - g_currentloc = oloc; + 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); + } + + 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); + } } } @@ -921,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)) @@ -1025,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 { @@ -1059,7 +1147,8 @@ int main (int argc, char *argv[]) } setCodePoint (); - + showHerald (); + /* ** create lists of C and LCL files */ @@ -1077,7 +1166,7 @@ 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)) { @@ -1102,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 { @@ -1116,8 +1205,6 @@ int main (int argc, char *argv[]) } } end_cstringSList_elements; - showHerald (); /*@i723 move earlier? */ - if (showhelp) { if (allhelp) @@ -1204,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 @@ -1319,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)))); } /* @@ -1436,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 @@ -1444,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; } @@ -1460,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; } @@ -1472,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 ())); } } @@ -1483,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 ())); } @@ -1496,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 ())); } @@ -1511,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 ())); } @@ -1523,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)); } } @@ -1603,6 +1701,7 @@ int main (int argc, char *argv[]) } llexit (expsuccess ? LLSUCCESS : LLFAILURE); + BADBRANCHRET (LLFAILURE); } # ifdef WIN32 @@ -1619,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 (""); @@ -1695,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 (""); @@ -1708,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 " @@ -1716,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 (""); @@ -1736,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."); @@ -1837,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"); @@ -1896,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 @@ -1944,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 (""); @@ -1965,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 @@ -2109,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); @@ -2131,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)); @@ -2166,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) + /*@modifies rcfile@*/ /*@ensures closed rcfile@*/ { char *s = mstring_create (MAX_LINE_LENGTH); char *os = s; - + DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs))); s = os; @@ -2277,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)) { @@ -2393,30 +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 (); - voptgenerror - (FLG_BADFLAG, - message ("Options file not found: %s", - extra), - g_currentloc); - } + (void) readOptionsFile (extra, passThroughArgs, TRUE); } else if (opt == FLG_INIT) { @@ -2424,25 +2546,30 @@ 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 { @@ -2451,17 +2578,24 @@ loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs) message ("Unmatched \" in option string: %s", 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 { @@ -2484,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) @@ -2502,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)