X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/885824d34f6f6626fde2fb041801408cbaf1f6f1..3e3ec46998ea67d6742eb30afc16058c5537004e:/src/llmain.c?ds=sidebyside diff --git a/src/llmain.c b/src/llmain.c index cc3652c..5bf2b57 100644 --- a/src/llmain.c +++ b/src/llmain.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 @@ -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,14 +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 + extern /*@external@*/ int yydebug; @@ -92,17 +90,28 @@ static void describePrefixCodes (void); static void cleanupFiles (void); static void showHelp (void); static void interrupt (int p_i); -static void loadrc (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); static bool specialFlagsHelp (char *p_next); static bool hasShownHerald = FALSE; +static char *specFullName (char *p_specfile, /*@out@*/ char **p_inpath) + /*@modifies *p_inpath@*/ ; static bool anylcl = FALSE; static clock_t inittime; -static /*@only@*/ /*@null@*/ tsource *initFile = (tsource *) 0; +static /*@only@*/ /*@null@*/ inputStream initFile = inputStream_undefined; -static fileIdList preprocessFiles (fileIdList) +static fileIdList preprocessFiles (fileIdList, bool) /*@modifies fileSystem@*/ ; # ifndef NOLCL @@ -150,34 +159,36 @@ static */ cstring larchpath = context_getLarchPath (); - tsource *LSLinitFile = (tsource *) 0; + inputStream LSLinitFile = inputStream_undefined; setCodePoint (); - if (initFile == (tsource *) 0) + if (inputStream_isUndefined (initFile)) { - initFile = tsource_create (INITFILENAME, LCLINIT_SUFFIX, FALSE); + initFile = inputStream_create (cstring_makeLiteral (INITFILENAME), + cstring_makeLiteralTemp (LCLINIT_SUFFIX), + FALSE); - if (!tsource_getPath (cstring_toCharsSafe (larchpath), initFile)) + if (!inputStream_getPath (larchpath, initFile)) { lldiagmsg (message ("Continuing without LCL init file: %s", - cstring_fromChars (tsource_fileName (initFile)))); + inputStream_fileName (initFile))); } else { - if (!tsource_open (initFile)) + if (!inputStream_open (initFile)) { lldiagmsg (message ("Continuing without LCL init file: %s", - cstring_fromChars (tsource_fileName (initFile)))); + inputStream_fileName (initFile))); } } } else { - if (!tsource_open (initFile)) + if (!inputStream_open (initFile)) { lldiagmsg (message ("Continuing without LCL init file: %s", - cstring_fromChars (tsource_fileName (initFile)))); + inputStream_fileName (initFile))); } } @@ -202,9 +213,9 @@ static setCodePoint (); /* need this to initialize LCL checker */ - llassert (initFile != NULL); - - if (tsource_isOpen (initFile)) + + llassert (inputStream_isDefined (initFile)); + if (inputStream_isOpen (initFile)) { setCodePoint (); @@ -217,24 +228,26 @@ static LCLProcessInitFileCleanup (); setCodePoint (); - check (tsource_close (initFile)); + check (inputStream_close (initFile)); } /* Initialize LSL init files, for parsing LSL signatures from LSL */ - LSLinitFile = tsource_create ("lslinit.lsi", ".lsi", FALSE); + LSLinitFile = inputStream_create (cstring_makeLiteral ("lslinit.lsi"), + cstring_makeLiteralTemp (".lsi"), + FALSE); - if (!tsource_getPath (cstring_toCharsSafe (larchpath), LSLinitFile)) + if (!inputStream_getPath (larchpath, LSLinitFile)) { lldiagmsg (message ("Continuing without LSL init file: %s", - cstring_fromChars (tsource_fileName (LSLinitFile)))); + inputStream_fileName (LSLinitFile))); } else { - if (!tsource_open (LSLinitFile)) + if (!inputStream_open (LSLinitFile)) { lldiagmsg (message ("Continuing without LSL init file: %s", - cstring_fromChars (tsource_fileName (LSLinitFile)))); + inputStream_fileName (LSLinitFile))); } } @@ -250,7 +263,7 @@ static lscanLineReset (); LSLScanInit (); - if (tsource_isOpen (LSLinitFile)) + if (inputStream_isOpen (LSLinitFile)) { setCodePoint (); LSLScanReset (LSLinitFile); @@ -258,10 +271,10 @@ static setCodePoint (); LSLProcessInitFile (); setCodePoint (); - check (tsource_close (LSLinitFile)); + check (inputStream_close (LSLinitFile)); } - tsource_free (LSLinitFile); + inputStream_free (LSLinitFile); if (lclHadError ()) { @@ -309,38 +322,42 @@ lslProcess (fileIdList lclfiles) fileIdList_elements (lclfiles, fid) { - char *actualName = (char *) dmalloc (sizeof (*actualName)); - char *oactualName = actualName; - char *fname = cstring_toCharsSafe (fileName (fid)); + cstring actualName = cstring_undefined; + cstring fname = fileName (fid); - if (osd_getPath (g_localSpecPath, fname, &actualName) == OSD_FILENOTFOUND) + if (osd_getPath (cstring_fromChars (g_localSpecPath), + fname, &actualName) == OSD_FILENOTFOUND) { if (mstring_equal (g_localSpecPath, ".")) { - lldiagmsg (message ("Spec file not found: %s", - cstring_fromChars (fname))); + lldiagmsg (message ("Spec file not found: %q", osd_outputPath (fname))); } else { - lldiagmsg (message ("Spec file not found: %s (on %s)", - cstring_fromChars (fname), + lldiagmsg (message ("Spec file not found: %q (on %s)", + osd_outputPath (fname), cstring_fromChars (g_localSpecPath))); } } else { - tsource *specFile; - - while (*actualName == '.' && *(actualName + 1) == CONNECTCHAR) + inputStream specFile; + /*@access cstring@*/ + char *namePtr = actualName; + + while (*namePtr == '.' && *(namePtr + 1) == CONNECTCHAR) { - actualName += 2; + namePtr += 2; } + /*@noaccess cstring@*/ + + g_currentSpec = cstring_fromCharsNew (namePtr); + + specFile = inputStream_create (cstring_copy (g_currentSpec), + LCL_EXTENSION, TRUE); - specFile = tsource_create (actualName, LCL_SUFFIX, TRUE); - llassert (specFile != (tsource *) 0); + llassert (inputStream_isDefined (specFile)); - g_currentSpec = cstring_fromChars (mstring_copy (actualName)); - g_currentSpecName = specFullName (cstring_toCharsSafe (g_currentSpec), &path); @@ -354,11 +371,11 @@ lslProcess (fileIdList lclfiles) /* Open source file */ - if (!tsource_open (specFile)) + if (!inputStream_open (specFile)) { - lldiagmsg (message ("Cannot open file: %s", - cstring_fromChars (tsource_fileName (specFile)))); - tsource_free (specFile); + lldiagmsg (message ("Cannot open file: %q", + osd_outputPath (inputStream_fileName (specFile)))); + inputStream_free (specFile); } else { @@ -387,32 +404,31 @@ lslProcess (fileIdList lclfiles) { if (overallStatus) { - outputLCSFile (path, "%%FAILED Output from ", + outputLCSFile (path, "%FAILED Output from ", g_currentSpecName); } else { - outputLCSFile (path, "%%PASSED Output from ", + outputLCSFile (path, "%PASSED Output from ", g_currentSpecName); } } - (void) tsource_close (specFile); - tsource_free (specFile); + (void) inputStream_close (specFile); + inputStream_free (specFile); symtable_exitScope (g_symtab); - } + } } - - sfree (oactualName); + cstring_free (actualName); } end_fileIdList_elements; - + /* Can cleanup lsl stuff right away */ - - lslCleanup (); - - g_currentSpec = cstring_undefined; - g_currentSpecName = NULL; + + lslCleanup (); + + g_currentSpec = cstring_undefined; + g_currentSpecName = NULL; } # endif @@ -422,6 +438,7 @@ static void handlePassThroughFlag (char *arg) char *quotechar = strchr (curarg, '\"'); int offset = 0; bool open = FALSE; + char *freearg = NULL; while (quotechar != NULL) { @@ -444,6 +461,7 @@ static void handlePassThroughFlag (char *arg) } } + llassert (quotechar != NULL); *quotechar = '\0'; offset = (quotechar - arg) + 2; @@ -453,6 +471,7 @@ static void handlePassThroughFlag (char *arg) (message ("%s\"\'%s", cstring_fromChars (arg), cstring_fromChars (quotechar + 1))); + freearg = arg; open = FALSE; } else @@ -461,6 +480,7 @@ static void handlePassThroughFlag (char *arg) (message ("%s\'\"%s", cstring_fromChars (arg), cstring_fromChars (quotechar + 1))); + freearg = arg; open = TRUE; } @@ -471,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 { @@ -485,7 +506,7 @@ static void handlePassThroughFlag (char *arg) ** them. This is an artifact of UNIX command line? */ - def = osd_fixDefine (arg + 1); + def = osd_fixDefine (cstring_fromChars (arg + 1)); DPRINTF (("Do define: %s", def)); cppDoDefine (def); DPRINTF (("After define")); @@ -496,6 +517,8 @@ static void handlePassThroughFlag (char *arg) BADBRANCH; } } + + sfree (freearg); } void showHerald (void) @@ -504,12 +527,60 @@ void showHerald (void) else { - fprintf (g_msgstream, "%s\n\n", LCL_VERSION); + fprintf (g_msgstream, "%s\n\n", SPLINT_VERSION); hasShownHerald = TRUE; llflush (); } } +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 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 + { + 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)) @@ -524,6 +595,26 @@ static void addFile (fileIdList files, /*@only@*/ cstring 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. @@ -560,34 +651,43 @@ int main (int argc, char *argv[]) bool first_time = TRUE; bool showhelp = FALSE; bool allhelp = TRUE; - tsource *sourceFile = (tsource *) 0; + bool expsuccess; + inputStream sourceFile = inputStream_undefined; fileIdList dercfiles; cstringSList fl = cstringSList_undefined; cstringSList passThroughArgs = cstringSList_undefined; - fileIdList cfiles; - fileIdList lclfiles; + fileIdList cfiles, xfiles, lclfiles, mtfiles; clock_t before, lcltime, libtime, pptime, cptime, rstime; int i = 0; +# ifdef __EMX__ + _wildcard (&argc, &argv); +# endif + g_msgstream = stdout; (void) signal (SIGINT, interrupt); (void) signal (SIGSEGV, interrupt); cfiles = fileIdList_create (); + xfiles = fileIdList_create (); lclfiles = fileIdList_create (); + mtfiles = fileIdList_create (); flags_initMod (); + clabstract_initMod (); typeIdSet_initMod (); cppReader_initMod (); + osd_initMod (); setCodePoint (); - + g_currentloc = fileloc_createBuiltin (); - + before = clock (); context_initMod (); + context_setInCommandLine (); if (argc <= 1) @@ -604,26 +704,28 @@ int main (int argc, char *argv[]) */ { - char *incval = mstring_copy (osd_getEnvironmentVariable (INCLUDE_VAR)); + cstring incval = cstring_copy (osd_getEnvironmentVariable (INCLUDEPATH_VAR)); + cstring oincval = incval; - if (incval != NULL) + if (cstring_isDefined (incval)) { /* ** Each directory on the include path is a system include directory. */ DPRINTF (("include: %s", incval)); - context_setString (FLG_SYSTEMDIRS, cstring_fromCharsNew (incval)); + context_setString (FLG_SYSTEMDIRS, cstring_copy (incval)); - while (incval != NULL) + while (cstring_isDefined (incval)) { - char *nextsep = strchr (incval, SEPCHAR); + /*@access cstring@*/ + char *nextsep = strchr (incval, PATH_SEPARATOR); if (nextsep != NULL) { cstring dir; *nextsep = '\0'; - dir = cstring_fromCharsNew (incval); + dir = cstring_copy (incval); if (cstring_length (dir) == 0 || !isalpha ((int) cstring_firstChar (dir))) @@ -635,20 +737,33 @@ int main (int argc, char *argv[]) } else { - DPRINTF (("Add include: %s", dir)); cppAddIncludeDir (dir); } - *nextsep = SEPCHAR; - incval = nextsep + 1; + *nextsep = PATH_SEPARATOR; + incval = cstring_fromChars (nextsep + 1); cstring_free (dir); } else { break; } + + /*@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); } /* @@ -656,9 +771,8 @@ int main (int argc, char *argv[]) */ { - cstring home = cstring_fromChars (osd_getHomeDir ()); - char *fname = NULL; - FILE *rcfile; + cstring home = osd_getHomeDir (); + cstring fname = cstring_undefined; bool defaultf = TRUE; bool nof = FALSE; @@ -669,35 +783,31 @@ int main (int argc, char *argv[]) if (*thisarg == '-' || *thisarg == '+') { + bool set = (*thisarg == '+'); + flagcode opt; + thisarg++; + opt = identifyFlag (cstring_fromChars (thisarg)); - if (mstring_equal (thisarg, "nof")) + 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 @@ -710,55 +820,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); + } } } @@ -868,23 +998,31 @@ int main (int argc, char *argv[]) thisarg++; /* skip '-' */ flagname = cstring_fromChars (thisarg); - + + DPRINTF (("Flag: %s", flagname)); opt = identifyFlag (flagname); - - if (flagcode_isSkip (opt)) + DPRINTF (("Flag: %s", flagcode_unparse (opt))); + + if (flagcode_isSkip (opt) || opt == FLG_SHOWSCAN || opt == FLG_WARNRC) { - ; + /* showscan already processed */ + DPRINTF (("Skipping!")); } else if (flagcode_isInvalid (opt)) { + DPRINTF (("Invalid: %s", flagname)); + if (isMode (flagname)) { context_setMode (flagname); } else { - llgloberror (message ("Unrecognized option: %s", - cstring_fromChars (thisarg))); + DPRINTF (("Error!")); + voptgenerror (FLG_BADFLAG, + message ("Unrecognized option: %s", + cstring_fromChars (thisarg)), + g_currentloc); } } else @@ -930,7 +1068,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; @@ -951,15 +1089,33 @@ int main (int argc, char *argv[]) else if (opt == FLG_INIT) { # ifndef NOLCL - initFile = tsource_create - (cstring_toCharsSafe (arg), - LCLINIT_SUFFIX, FALSE); + initFile = inputStream_create + (arg, + cstring_makeLiteralTemp (LCLINIT_SUFFIX), + FALSE); # endif break; } else { - setStringFlag (opt, arg); + 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, arg); + } } } else @@ -979,49 +1135,71 @@ int main (int argc, char *argv[]) } else /* its a filename */ { + DPRINTF (("Adding filename: %s", thisarg)); fl = cstringSList_add (fl, cstring_fromChars (thisarg)); } } } setCodePoint (); - + showHerald (); + /* ** create lists of C and LCL files */ cstringSList_elements (fl, current) { - char *fname = cstring_toCharsSafe (current); - char *ext = strrchr (fname, '.'); - - if (ext == NULL) + cstring ext = fileLib_getExtension (current); + + if (cstring_isUndefined (ext)) { /* no extension --- both C and LCL with default extensions */ - addFile (cfiles, message ("%s.c", cstring_fromChars (fname))); - addFile (lclfiles, message ("%s.lcl", cstring_fromChars (fname))); + addFile (cfiles, message ("%s%s", current, C_EXTENSION)); + addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION)); } - else if (isCext (ext)) + else if (cstring_equal (ext, XH_EXTENSION)) { - addFile (cfiles, cstring_fromCharsNew (fname)); + addXHFile (xfiles, current); } - else + else if (cstring_equal (ext, PP_EXTENSION)) { - if (!mstring_equal (ext, ".lcl")) + if (!context_getFlag (FLG_NOPP)) { - lldiagmsg (message ("Unrecognized file extension: %s (assuming lcl)", - cstring_fromChars (ext))); + voptgenerror + (FLG_FILEEXTENSIONS, + message ("File extension %s used without +nopp flag (will be processed as C source code): %s", + ext, current), + g_currentloc); } - - addFile (lclfiles, cstring_fromCharsNew (fname)); + + 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; - - showHerald (); - - if (showhelp) { if (allhelp) @@ -1031,6 +1209,7 @@ int main (int argc, char *argv[]) fprintf (g_msgstream, "\n"); fileIdList_free (cfiles); + fileIdList_free (xfiles); fileIdList_free (lclfiles); llexit (LLSUCCESS); @@ -1086,17 +1265,35 @@ int main (int argc, char *argv[]) fileloc_free (g_currentloc); g_currentloc = fileloc_createBuiltin (); + /* + ** Read metastate files (must happen before loading libraries) + */ + + fileIdList_elements (mtfiles, mtfile) + { + context_setFileId (mtfile); + + if (context_getFlag (FLG_SHOWSCAN)) + { + lldiagmsg (message ("< processing %s >", rootFileName (mtfile))); + } + + mtreader_readFile (cstring_copy (fileName (mtfile))); + } end_fileIdList_elements; + libtime = clock (); - + 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 } + usymtab_initGlobalMarker (); + /* ** pre-processing ** @@ -1107,8 +1304,6 @@ int main (int argc, char *argv[]) context_setInCommandLine (); - cppReader_initialize (); - DPRINTF (("Pass through: %s", cstringSList_unparse (passThroughArgs))); cstringSList_elements (passThroughArgs, thisarg) { @@ -1119,12 +1314,16 @@ int main (int argc, char *argv[]) cleanupMessages (); + DPRINTF (("Initializing cpp reader!")); + cppReader_initialize (); cppReader_saveDefinitions (); context_clearInCommandLine (); if (!context_getFlag (FLG_NOPP)) { + fileIdList tfiles; + llflush (); if (context_getFlag (FLG_SHOWSCAN)) @@ -1135,7 +1334,11 @@ int main (int argc, char *argv[]) lcltime = clock (); context_setPreprocessing (); - dercfiles = preprocessFiles (cfiles); + dercfiles = preprocessFiles (xfiles, TRUE); + tfiles = preprocessFiles (cfiles, FALSE); + dercfiles = fileIdList_append (dercfiles, tfiles); + fileIdList_free (tfiles); + context_clearPreprocessing (); fileIdList_free (cfiles); @@ -1150,10 +1353,10 @@ int main (int argc, char *argv[]) else { lcltime = clock (); - dercfiles = cfiles; + dercfiles = fileIdList_append (cfiles, xfiles); pptime = clock (); } - + /* ** now, check all the corresponding C files ** @@ -1172,30 +1375,33 @@ int main (int argc, char *argv[]) # endif } + DPRINTF (("Initializing...")); + exprNode_initMod (); + DPRINTF (("Okay...")); + fileIdList_elements (dercfiles, fid) { - sourceFile = tsource_create (cstring_toCharsSafe (fileName (fid)), - C_SUFFIX, TRUE); + sourceFile = inputStream_create (cstring_copy (fileName (fid)), C_EXTENSION, TRUE); context_setFileId (fid); /* Open source file */ - if (sourceFile == (tsource *) 0 || (!tsource_open (sourceFile))) + if (inputStream_isUndefined (sourceFile) || (!inputStream_open (sourceFile))) { /* previously, this was ignored ?! */ llbug (message ("Could not open temp file: %s", fileName (fid))); } else { - yyin = sourceFile->file; /*< shared <- only */ + yyin = inputStream_getFile (sourceFile); /*< shared <- only */ llassert (yyin != NULL); if (context_getFlag (FLG_SHOWSCAN)) { - lldiagmsg (message ("< checking %s >", rootFileName (fid))); + lldiagmsg (message ("< checking %q >", osd_outputPath (rootFileName (fid)))); } /* @@ -1212,13 +1418,13 @@ int main (int argc, char *argv[]) first_time = FALSE; } + DPRINTF (("Entering...")); context_enterFile (); (void) yyparse (); - context_exitFile (); + context_exitCFile (); - (void) tsource_close (sourceFile); - } - + (void) inputStream_close (sourceFile); + } } end_fileIdList_elements; cptime = clock (); @@ -1293,47 +1499,52 @@ int main (int argc, char *argv[]) summarizeErrors (); } - if (!context_getFlag (FLG_QUIET)) - { - cstring specErrors = cstring_undefined; + + { + bool isQuiet = context_getFlag (FLG_QUIET); + cstring specErrors = cstring_undefined; # ifndef NOLCL - int nspecErrors = lclNumberErrors (); + int nspecErrors = lclNumberErrors (); # endif + + expsuccess = TRUE; - if (context_neednl ()) - fprintf (g_msgstream, "\n"); + if (context_neednl ()) + fprintf (g_msgstream, "\n"); # ifndef NOLCL - if (nspecErrors > 0) - { - if (nspecErrors == context_getLCLExpect ()) - { - specErrors = - message ("%d spec error%p found, as expected\n ", - nspecErrors); - } - else - { - if (context_getLCLExpect () > 0) - { - specErrors = - message ("%d spec error%p found, expected %d\n ", - nspecErrors, - (int) context_getLCLExpect ()); - } - else - { - specErrors = message ("%d spec error%p found\n ", - nspecErrors); - } - } - } - else + if (nspecErrors > 0) + { + if (nspecErrors == context_getLCLExpect ()) + { + specErrors = + message ("%d spec warning%&, as expected\n ", + nspecErrors); + } + else + { + if (context_getLCLExpect () > 0) + { + specErrors = + message ("%d spec warning%&, expected %d\n ", + nspecErrors, + (int) context_getLCLExpect ()); + } + else + { + specErrors = message ("%d spec warning%& found\n ", + nspecErrors); + expsuccess = FALSE; + } + } + } + else { 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; } } # endif @@ -1342,25 +1553,37 @@ int main (int argc, char *argv[]) { if (context_numErrors () == context_getExpect ()) { - llmsg (message ("Finished LCLint checking --- " - "%s%d code error%p found, as expected", - specErrors, context_numErrors ())); + if (!isQuiet) { + llmsg (message ("Finished checking --- " + "%s%d code warning%&, as expected", + specErrors, context_numErrors ())); + } } else { if (context_getExpect () > 0) { - llmsg (message - ("Finished LCLint checking --- " - "%s%d code error%p found, expected %d", - specErrors, context_numErrors (), - (int) context_getExpect ())); + if (!isQuiet) { + llmsg (message + ("Finished checking --- " + "%s%d code warning%&, expected %d", + specErrors, context_numErrors (), + (int) context_getExpect ())); + } + + expsuccess = FALSE; } else { - llmsg (message ("Finished LCLint checking --- " - "%s%d code error%p found", - specErrors, context_numErrors ())); + + if (!isQuiet) + { + llmsg (message ("Finished checking --- " + "%s%d code warning%& found", + specErrors, context_numErrors ())); + } + + expsuccess = FALSE; } } } @@ -1368,42 +1591,61 @@ int main (int argc, char *argv[]) { if (context_getExpect () > 0) { - llmsg (message - ("Finished LCLint checking --- " - "%sno code errors found, expected %d", - specErrors, - (int) context_getExpect ())); + if (!isQuiet) { + llmsg (message + ("Finished checking --- " + "%sno code warnings, expected %d", + specErrors, + (int) context_getExpect ())); + } + + expsuccess = FALSE; } else { if (context_getLinesProcessed () > 0) { - 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 { - llmsg (message ("Finished LCLint checking --- %sno code processed", - specErrors)); + if (!isQuiet) { + llmsg (message ("Finished checking --- %sno code processed", + specErrors)); + } } } } cstring_free (specErrors); - } - + } + if (context_getFlag (FLG_STATS)) { clock_t ttime = clock () - before; int specLines = context_getSpecLinesProcessed (); - + rstime = clock (); - + if (specLines > 0) { fprintf (g_msgstream, "%d spec, ", specLines); } - + # ifndef CLOCKS_PER_SEC fprintf (g_msgstream, "%d source lines in %ld time steps (steps/sec unknown)\n", context_getLinesProcessed (), @@ -1422,11 +1664,11 @@ int main (int argc, char *argv[]) if (context_getFlag (FLG_TIMEDIST)) { clock_t ttime = clock () - before; - + if (ttime > 0) { char *msg = (char *) dmalloc (256 * sizeof (*msg)); - + if (anylcl) { sprintf (msg, @@ -1448,29 +1690,32 @@ int main (int argc, char *argv[]) (100.0 * (double) (cptime - pptime) / ttime), (100.0 * (double) (rstime - cptime) / ttime)); } - + llgenindentmsgnoloc (cstring_fromCharsO (msg)); } } - llexit (LLSUCCESS); + llexit (expsuccess ? LLSUCCESS : LLFAILURE); + BADBRANCHRET (LLFAILURE); } +# ifdef WIN32 /* ** Reenable return value warnings. */ - -#pragma warning (default:4035) +# pragma warning (default:4035) +# endif void showHelp (void) { showHerald (); - llmsglit ("Source files are .c, .h and .lcl files. If there is no suffix,"); - llmsglit (" LCLint will look for .c and .lcl."); + llmsg (message ("Source files are .c, .h and %s files. If there is no suffix,", + 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 (""); @@ -1544,19 +1789,20 @@ 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 (""); + /* evans 2000-12-21 fixed typo reported by Jeroen Ruigrok/Asmodai */ llmsglit ("Missing type definitions --- an undefined type name will usually " - "lead to a parse error. This ofter occurs when a standard header " + "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 " @@ -1564,7 +1810,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 (""); @@ -1584,9 +1830,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."); @@ -1598,7 +1844,7 @@ printAnnotations (void) llmsglit ("Annotations"); llmsglit ("-----------"); llmsglit (""); - llmsglit ("Annotations are stylized comments that document certain " + llmsglit ("Annotations are semantic comments that document certain " "assumptions about functions, variables, parameters, and types. "); llmsglit (""); llmsglit ("They may be used to indicate where the representation of a " @@ -1744,7 +1990,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 @@ -1792,7 +2038,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 (""); @@ -1813,24 +2059,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 @@ -1856,12 +2085,12 @@ void describeVars (void) { cstring eval; - char *def; + cstring def; eval = context_getLarchPath (); def = osd_getEnvironmentVariable (LARCH_PATH); - if (def != NULL || + if (cstring_isDefined (def) || !cstring_equal (eval, cstring_fromChars (DEFAULT_LARCHPATH))) { llmsg (message ("LARCH_PATH = %s", eval)); @@ -1875,9 +2104,9 @@ describeVars (void) llmsglit (" --- path used to find larch initialization files and LSL traits"); eval = context_getLCLImportDir (); - def = osd_getEnvironmentVariable (LCLIMPORTDIR); + def = osd_getEnvironmentVariable (cstring_makeLiteralTemp (LCLIMPORTDIR)); - if (def != NULL || + if (cstring_isDefined (def) || !cstring_equal (eval, cstring_fromChars (DEFAULT_LCLIMPORTDIR))) { llmsg (message ("%q = %s", cstring_makeLiteral (LCLIMPORTDIR), eval)); @@ -1891,13 +2120,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 @@ -1952,6 +2186,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); @@ -1974,13 +2215,14 @@ cleanupFiles (void) } /* -** cleans up temp files (if necessary) -** exits lclint +** cleans up temp files (if necessary) and exits */ /*@exits@*/ void llexit (int status) { + DPRINTF (("llexit: %d", status)); + # ifdef WIN32 if (status == LLFAILURE) { @@ -2007,17 +2249,72 @@ 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 (FILE *rcfile, cstringSList *passThroughArgs) +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; - while (fgets (s, MAX_LINE_LENGTH, rcfile) != NULL) + while (reader_readLine (rcfile, s, MAX_LINE_LENGTH) != NULL) { char c; bool set = FALSE; @@ -2026,9 +2323,8 @@ loadrc (FILE *rcfile, cstringSList *passThroughArgs) DPRINTF (("Line: %s", s)); DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs))); - incLine (); - while (*s == ' ' || *s == '\t' || *s == '\n') + while (*s == ' ' || *s == '\t') { s++; incColumn (); @@ -2056,10 +2352,11 @@ loadrc (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; } @@ -2125,15 +2422,18 @@ loadrc (FILE *rcfile, cstringSList *passThroughArgs) } else if (flagcode_isInvalid (opt)) { + DPRINTF (("Invalid: %s", thisflag)); + if (isMode (cstring_fromChars (thisflag))) { context_setMode (cstring_fromChars (thisflag)); } else { - llerror (FLG_BADFLAG, - message ("Unrecognized option: %s", - cstring_fromChars (thisflag))); + voptgenerror (FLG_BADFLAG, + message ("Unrecognized option: %s", + cstring_fromChars (thisflag)), + g_currentloc); } } else @@ -2145,8 +2445,9 @@ loadrc (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 */ { @@ -2212,11 +2513,12 @@ loadrc (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 { @@ -2228,73 +2530,67 @@ loadrc (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) { # ifndef NOLCL - llassert (initFile == NULL); + llassert (inputStream_isUndefined (initFile)); - initFile = tsource_create - (cstring_toCharsSafe (extra), - LCLINIT_SUFFIX, FALSE); - cstring_markOwned (extra); -# else - cstring_free (extra); + initFile = inputStream_create + (cstring_copy (extra), + cstring_makeLiteralTemp (LCLINIT_SUFFIX), + FALSE); # 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 { @@ -2317,10 +2613,10 @@ loadrc (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) +static fileIdList preprocessFiles (fileIdList fl, bool xhfiles) /*@modifies fileSystem@*/ { bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10); @@ -2333,18 +2629,24 @@ static fileIdList preprocessFiles (fileIdList fl) fileIdList_elements (fl, fid) { - char *ppfname = cstring_toCharsSafe (fileName (fid)); + cstring ppfname = fileName (fid); if (!(osd_fileIsReadable (ppfname))) { - lldiagmsg (message ("Cannot open file: %s", - cstring_fromChars (ppfname))); + lldiagmsg (message ("Cannot open file: %q", osd_outputPath (ppfname))); + ppfname = cstring_undefined; } - else + + if (cstring_isDefined (ppfname)) { - fileId dfile = fileTable_addCTempFile (context_fileTable (), fid); - - llassert (!mstring_isEmpty (ppfname)); + fileId dfile = fileTable_addCTempFile (context_fileTable (), fid); + + if (xhfiles) + { + llassert (fileTable_isXHFile (context_fileTable (), dfile)); + } + + llassert (cstring_isNonEmpty (ppfname)); if (msg) { @@ -2362,8 +2664,7 @@ static fileIdList preprocessFiles (fileIdList fl) filesprocessed++; } - if (cppProcess (cstring_fromChars (ppfname), - fileName (dfile)) != 0) + if (cppProcess (ppfname, fileName (dfile)) != 0) { llfatalerror (message ("Preprocessing error for file: %s", rootFileName (fid))); @@ -2375,3 +2676,75 @@ static fileIdList preprocessFiles (fileIdList fl) return dfiles; } + +/* This should be in an lclUtils.c file... */ +# ifndef NOLCL +char *specFullName (char *specfile, /*@out@*/ char **inpath) +{ + /* extract the path and the specname associated with the given file */ + char *specname = (char *) dmalloc (sizeof (*specname) + * (strlen (specfile) + 9)); + char *ospecname = specname; + char *path = (char *) dmalloc (sizeof (*path) * (strlen (specfile))); + size_t size; + long int i, j; + + /* initialized path to empty string or may have accidental garbage */ + *path = '\0'; + + /*@-mayaliasunique@*/ + strcpy (specname, specfile); + /*@=mayaliasunique@*/ + + /* trim off pathnames in specfile */ + size = strlen (specname); + + for (i = size_toInt (size) - 1; i >= 0; i--) + { + if (specname[i] == CONNECTCHAR) + { + /* strcpy (specname, (char *)specname+i+1); */ + for (j = 0; j <= i; j++) /* include '/' */ + { + path[j] = specname[j]; + } + + path[i + 1] = '\0'; + specname += i + 1; + break; + } + } + + /* + ** also remove .lcl file extension, assume it's the last extension + ** of the file name + */ + + size = strlen (specname); + + for (i = size_toInt (size) - 1; i >= 0; i--) + { + if (specname[i] == '.') + { + specname[i] = '\0'; + break; + } + } + + *inpath = path; + + /* + ** If specname no longer points to the original char, + ** we need to allocate a new pointer and copy the string. + */ + + if (specname != ospecname) { + char *rspecname = (char *) dmalloc (sizeof (*rspecname) * (strlen (specname) + 1)); + strcpy (rspecname, specname); /* evs 2000-05-16: Bug: was ospecname! */ + sfree (ospecname); + return rspecname; + } + + return specname; +} +# endif