]> andersk Git - splint.git/blobdiff - src/llmain.c
Fixed state clauses. Added obvious loop exec checking.
[splint.git] / src / llmain.c
index cc3652c58f17c40fcc6c5d5057251b3e85bc8e36..5bf2b57dde01c930d53a5585f8f1a4e0882a2232 100644 (file)
@@ -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
 **
 ** 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 <signal.h>
-
+# include <time.h>
 /*
 ** Ensure that WIN32 and _WIN32 are both defined or both undefined.
 */
 # 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 <time.h>
+
 
 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 <file>.c and <file>.lcl.");
+  llmsg (message ("Source files are .c, .h and %s files.  If there is no suffix,",
+                 LCL_EXTENSION));
+  llmsg (message ("   Splint will look for <file>.c and <file>%s.", LCL_EXTENSION));
   llmsglit ("");
-  llmsglit ("Use lclint -help <topic or flag name> for more information");
+  llmsglit ("Use splint -help <topic or flag name> 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 <sys/local.h>");
   llmsglit ("");
-  llmsglit ("to force LCLint to process <sys/types.h>.");
+  llmsglit ("to force Splint to process <sys/types.h>.");
   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<n>@*/");
   llgenindentmsgnoloc
     (cstring_makeLiteral 
-     ("No errors will be reported from an /*@i<n>@*/ (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<n>@*/ (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<n>@*/");
   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
This page took 0.120091 seconds and 4 git commands to generate.