]> andersk Git - splint.git/blobdiff - src/llmain.c
Added manual test cases.
[splint.git] / src / llmain.c
index f8f5a6413fc0c81227d17a634d82acaaa2d33675..1d9c6b544f77ccde96134120b2a75cd7361058c2 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** Splint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Copyright (C) 1994-2002 University of Virginia,
 **         Massachusetts Institute of Technology
 **
 ** This program is free software; you can redistribute it and/or modify it
@@ -91,8 +91,14 @@ static void cleanupFiles (void);
 static void showHelp (void);
 static void interrupt (int p_i);
 
+static bool readOptionsFile (cstring p_fname,
+                            cstringSList *p_passThroughArgs,
+                            bool p_report) 
+   /*@modifies fileSystem, internalState, *p_passThroughArgs@*/ ;
+   
 static void loadrc (FILE *p_rcfile, cstringSList *p_passThroughArgs)
-     /*@ensures closed p_rcfile@*/ ;
+   /*@modifies *p_passThroughArgs, p_rcfile@*/
+   /*@ensures closed p_rcfile@*/ ;
 
 static void describeVars (void);
 static bool specialFlagsHelp (char *p_next);
@@ -767,7 +773,6 @@ int main (int argc, char *argv[])
   {
     cstring home = osd_getHomeDir ();
     cstring fname  = cstring_undefined;
-    FILE *rcfile;
     bool defaultf = TRUE;
     bool nof = FALSE;
 
@@ -778,34 +783,36 @@ int main (int argc, char *argv[])
        
        if (*thisarg == '-' || *thisarg == '+')
          {
+           bool set = (*thisarg == '+');
+           flagcode opt;
+
            thisarg++;
 
-           if (mstring_equal (thisarg, "nof"))
+           /*
+           ** Don't report warnings this time
+           */
+
+           opt = flags_identifyFlagQuiet (cstring_fromChars (thisarg));
+
+           if (opt == FLG_NOF)
              {
                nof = TRUE;
              }
-           else if (mstring_equal (thisarg, "f"))
+           else if (opt == FLG_SHOWSCAN || opt == FLG_WARNRC)
+             {
+               /*
+               ** Need to set it immediately, so rc file scan is displayed
+               */
+
+               context_userSetFlag (opt, set);
+             }
+           else if (opt == FLG_OPTF)
              {
                if (++i < argc)
                  {
                    defaultf = FALSE;
                    fname = cstring_fromChars (argv[i]);
-                   rcfile = fileTable_openFile (context_fileTable (), 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", fname));
-                     }
+                   (void) readOptionsFile (fname, &passThroughArgs, TRUE);
                  }
                else
                  llfatalerror
@@ -818,94 +825,75 @@ int main (int argc, char *argv[])
              }
          }
       }
-    
-    if (cstring_isUndefined (fname))
-      {
-       if (!cstring_isEmpty (home)) {
-         fname = message ("%s%h%s", home, CONNECTCHAR,
-                          cstring_fromChars (RCFILE));
-         cstring_markOwned (fname);
-       }
-      }
-
+        
     setCodePoint ();
 
     if (!nof && defaultf)
       {
-       if (!cstring_isEmpty (fname)) 
-         {
-           rcfile = fileTable_openFile (context_fileTable (), fname, "r");
-           
-           if (rcfile != NULL)
-             {
-               fileloc oloc = g_currentloc;
-               
-               g_currentloc = fileloc_createRc (fname);
-               loadrc (rcfile, &passThroughArgs);
-               fileloc_reallyFree (g_currentloc);
-               g_currentloc = oloc;
-             }
-         }
-       
-# if defined(MSDOS) || defined(OS2)
-       fname = message ("%s",cstring_fromChars (RCFILE));
-# else
-       fname = message ("./%s", cstring_fromChars (RCFILE));
-# endif
-       
-       rcfile = fileTable_openFile (context_fileTable (), fname, "r");
-
        /*
-       ** If no RCFILE, try ALTRCFILE
+       ** No explicit rc file, first try reading ~/.splintrc
        */
 
-       if (rcfile == NULL)
+       if (cstring_isUndefined (fname))
          {
-           cstring_free (fname);
-# if defined(MSDOS) || defined(OS2)
-           fname = message ("%s", cstring_fromChars (ALTRCFILE));
-# else
-           fname = message ("./%s", cstring_fromChars (ALTRCFILE));
-# endif
-           rcfile = fileTable_openFile (context_fileTable (), fname, "r");
-         }
-       else
-         {
-           /*
-           ** Warn if ALTRCFILE also exists
-           */
-           cstring afname;
-           FILE *arcfile;
-           
-# if defined(MSDOS) || defined(OS2)
-           afname = message ("%s", cstring_fromChars (ALTRCFILE));
-# else
-           afname = message ("./%s", cstring_fromChars (ALTRCFILE));
-# endif
-           arcfile = fileTable_openFile (context_fileTable (), afname, "r");
-           
-           if (arcfile != NULL)
+           if (!cstring_isEmpty (home)) 
              {
-               voptgenerror (FLG_WARNRC,
-                             message ("Found both %s and %s files.  Using %s file only.",
-                                      fname, afname, fname),
-                             g_currentloc);
+               bool readhomerc, readaltrc;
+               cstring homename, altname;
+
+               homename = message ("%s%h%s", home, CONNECTCHAR,
+                                cstring_fromChars (RCFILE));
+               readhomerc = readOptionsFile (homename, &passThroughArgs, FALSE);
                
-               fileTable_closeFile (context_fileTable (), arcfile);
+               /*
+               ** Try ~/.lclintrc also for historical accuracy
+               */
+               
+               altname = message ("%s%h%s", home, CONNECTCHAR,
+                                cstring_fromChars (ALTRCFILE));
+               readaltrc = readOptionsFile (altname, &passThroughArgs, FALSE);
+
+               if (readhomerc && readaltrc)
+                 {
+
+                   voptgenerror 
+                     (FLG_WARNRC,
+                      message ("Found both %s and %s files. Using both files, "
+                               "but recommend using only %s to avoid confusion.",
+                               homename, altname, homename),
+                      g_currentloc);
+                 }
+
+               cstring_free (homename);
+               cstring_free (altname);
              }
          }
        
-       if (rcfile != NULL)
-         {
-           fileloc oloc = g_currentloc;
-
-           g_currentloc = fileloc_createRc (cstring_fromChars (fname));
-           loadrc (rcfile, &passThroughArgs);
-           fileloc_reallyFree (g_currentloc);
-           g_currentloc = oloc;
-         }
+       /*
+       ** 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);
+       }
       }
   }
   
@@ -1017,11 +1005,12 @@ int main (int argc, char *argv[])
              flagname = cstring_fromChars (thisarg);
 
              DPRINTF (("Flag: %s", flagname));
-             opt = identifyFlag (flagname);
+             opt = flags_identifyFlag (flagname);
              DPRINTF (("Flag: %s", flagcode_unparse (opt)));
 
-             if (flagcode_isSkip (opt))
+             if (flagcode_isSkip (opt) || opt == FLG_SHOWSCAN || opt == FLG_WARNRC)
                {
+                 /* showscan already processed */
                  DPRINTF (("Skipping!"));
                }
              else if (flagcode_isInvalid (opt))
@@ -1158,7 +1147,8 @@ int main (int argc, char *argv[])
     }
 
   setCodePoint ();  
-
+  showHerald (); 
+  
   /*
   ** create lists of C and LCL files
   */
@@ -1215,8 +1205,6 @@ int main (int argc, char *argv[])
        }
     } end_cstringSList_elements;
   
-    showHerald (); /*@i723 move earlier? */
-  
   if (showhelp)
     {
       if (allhelp)
@@ -1549,7 +1537,7 @@ int main (int argc, char *argv[])
              }
            else
              {
-               specErrors = message ("%d spec warning%& found\n       ",
+               specErrors = message ("%d spec warning%&\n       ",
                                      nspecErrors);
                expsuccess = FALSE;
              }
@@ -1596,7 +1584,7 @@ int main (int argc, char *argv[])
                  if (!isQuiet)
                    {
                      llmsg (message ("Finished checking --- "
-                                     "%s%d code warning%& found", 
+                                     "%s%d code warning%&", 
                                      specErrors, context_numErrors ()));
                    }
 
@@ -1630,11 +1618,13 @@ int main (int argc, char *argv[])
                        } 
                    }
                  else
+                   {
                      if (!isQuiet) 
                        {
                          llmsg (message ("Finished checking --- %sno code warnings",
                                          specErrors));
                        }
+                   }
                }
              else
                {
@@ -1809,7 +1799,7 @@ printParseErrors (void)
            "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 ("");
@@ -1946,11 +1936,11 @@ printAnnotations (void)
   llmsglit ("   /*@falsenull@*/ - if result is TRUE, first parameter is not NULL");
   llmsglit ("");
   llmsglit ("Execution:");
-  llmsglit ("   /*@exits@*/ - function never returns");
-  llmsglit ("   /*@mayexit@*/ - function may or may not return");
-  llmsglit ("   /*@trueexit@*/ - function does not return if first parameter is TRUE");
-  llmsglit ("   /*@falseexit@*/ - function does not return if first parameter if FALSE");
-  llmsglit ("   /*@neverexit@*/ - function always returns");
+  llmsglit ("   /*@noreturn@*/ - function never returns");
+  llmsglit ("   /*@maynotreturn@*/ - function may or may not return");
+  llmsglit ("   /*@noreturnwhentrue@*/ - function does not return if first parameter is TRUE");
+  llmsglit ("   /*@noreturnwhenfalse@*/ - function does not return if first parameter if FALSE");
+  llmsglit ("   /*@alwaysreturns@*/ - function always returns");
   llmsglit ("");
   llmsglit ("Side-Effects:");
   llmsglit ("   /*@sef@*/ - corresponding actual parameter has no side effects");
@@ -2233,7 +2223,7 @@ cleanupFiles (void)
 ** cleans up temp files (if necessary) and exits
 */
 
-/*@exits@*/ void
+/*@noreturn@*/ void
 llexit (int status)
 {
   DPRINTF (("llexit: %d", status));
@@ -2264,17 +2254,67 @@ llexit (int status)
   exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
+bool readOptionsFile (cstring fname, cstringSList *passThroughArgs, bool report)
+{
+  bool res = FALSE;
+
+  if (fileTable_exists (context_fileTable (), fname))
+    {
+      if (report)
+       {
+         voptgenerror
+           (FLG_WARNRC, 
+            message ("Multiple attempts to read options file: %s", fname),
+            g_currentloc);
+       }
+    }
+  else
+    {
+      FILE *innerf = fileTable_openFile (context_fileTable (), fname, "r");
+      
+      if (innerf != NULL)
+       {
+         fileloc fc = g_currentloc;
+         g_currentloc = fileloc_createRc (fname);
+
+         if (context_getFlag (FLG_SHOWSCAN))
+           {
+             lldiagmsg (message ("< reading options from %q >", 
+                                 fileloc_outputFilename (g_currentloc)));
+           }
+         
+         loadrc (innerf, passThroughArgs);
+         fileloc_reallyFree (g_currentloc);
+         g_currentloc = fc;
+         res = TRUE;
+       }
+      else 
+       {
+         if (report)
+           {
+             voptgenerror
+               (FLG_WARNRC, 
+                message ("Cannot open options file: %s", fname),
+                g_currentloc);
+           }
+       }
+    }
+
+  return res;
+}
+
 /*
 ** This shouldn't be necessary, but Apple Darwin can't handle '"''s.
 */
 
 void
 loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs)
+   /*@modifies rcfile@*/
    /*@ensures closed rcfile@*/
 {
   char *s = mstring_create (MAX_LINE_LENGTH);
   char *os = s;
-
+  
   DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
 
   s = os;
@@ -2379,7 +2419,7 @@ loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs)
 
          DPRINTF (("Flag: %s", thisflag));
 
-         opt = identifyFlag (cstring_fromChars (thisflag));
+         opt = flags_identifyFlag (cstring_fromChars (thisflag));
          
          if (flagcode_isSkip (opt))
            {
@@ -2495,30 +2535,10 @@ loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs)
                            {
                              DPRINTF (("Set value flag: %s", extra));
                              setValueFlag (opt, extra);
-                             cstring_free (extra);
                            }
                          else if (opt == FLG_OPTF)
                            {
-                             FILE *innerf = fileTable_openFile (context_fileTable (), extra, "r");
-                             cstring_markOwned (extra);
-                             
-                             if (innerf != NULL)
-                               {
-                                 fileloc fc = g_currentloc;
-                                 g_currentloc = fileloc_createRc (extra);
-                                 loadrc (innerf, passThroughArgs);
-                                 fileloc_reallyFree (g_currentloc);
-                                 g_currentloc = fc;
-                               }
-                             else 
-                               {
-                                 showHerald ();
-                                 voptgenerror
-                                   (FLG_BADFLAG, 
-                                    message ("Options file not found: %s", 
-                                             extra),
-                                    g_currentloc);
-                               }
+                             (void) readOptionsFile (extra, passThroughArgs, TRUE);
                            }
                          else if (opt == FLG_INIT)
                            {
@@ -2526,25 +2546,30 @@ loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs)
                              llassert (inputStream_isUndefined (initFile));
                              
                              initFile = inputStream_create 
-                               (extra
+                               (cstring_copy (extra)
                                 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
                                 FALSE);
-# else
-                             cstring_free (extra);
 # endif
                            }
                          else if (flagcode_hasString (opt))
                            {
+                             DPRINTF (("Here: %s", extra));
+
+                             /*
+                             ** If it has "'s, we need to remove them.
+                             */
+
                              if (cstring_firstChar (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 quotes: %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
                                    {
@@ -2553,17 +2578,24 @@ loadrc (/*:open:*/ FILE *rcfile, cstringSList *passThroughArgs)
                                         message ("Unmatched \" in option string: %s", 
                                                  extra),
                                         g_currentloc);
+                                     setStringFlag (opt, extra);
                                    }
                                }
-                             
-                             setStringFlag (opt, extra);
+                             else
+                               {
+                                 DPRINTF (("No quotes: %s", extra));
+                                 setStringFlag (opt, extra);
+                               }
+
+                             extra = cstring_undefined;
                            }
                          else
                            {
-                             cstring_free (extra);
                              BADEXIT;
                            }
                        }
+
+                     cstring_free (extra); 
                    }
                  else
                    {
@@ -2606,7 +2638,7 @@ static fileIdList preprocessFiles (fileIdList fl, bool xhfiles)
 
       if (!(osd_fileIsReadable (ppfname)))
        {
-         lldiagmsg (message ("Cannot open file: %s", osd_outputPath (ppfname)));
+         lldiagmsg (message ("Cannot open file: %q", osd_outputPath (ppfname)));
          ppfname = cstring_undefined;
        }
 
This page took 0.06042 seconds and 4 git commands to generate.