]> andersk Git - splint.git/blobdiff - src/flags.c
Fixed annotations on struct iovec and struct msghdr in unix.h
[splint.git] / src / flags.c
index eb68c11d6dd04df7cdff17ce7484de08953b9efa..27e018e523f4f99c7f8a3cd851f2cf6b42712a8f 100644 (file)
 
 # include "splintMacros.nf"
 # include "basic.h"
+# include "osd.h"
 # include "portab.h"
+# include "rcfiles.h"
+# include "lslinit.h"
 
 /*
 ** from the CC man page:
@@ -190,7 +193,7 @@ static cstring describeFlagCode (flagcode p_flag) /*@*/ ;
 static cstringSList sortedFlags (void) /*@*/ ;
 static /*@observer@*/ cstring categoryName (flagkind p_kind) /*@*/ ;
 
-static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_msgstream@*/ ;
+static flagcode flags_identifyFlagAux (cstring p_s, bool p_quiet) /*@modifies g_warningstream@*/ ;
 
 # if 0
 static /*@unused@*/ cstring listModes (void) /*@*/ ;
@@ -221,6 +224,33 @@ bool flagcode_isNameChecksFlag (flagcode f)
   return (flags[f].main == FK_NAMES);
 }
 
+bool flagcode_isHelpFlag (flagcode f)
+{
+  return f == FLG_HELP;
+}
+
+bool flagcode_isMessageControlFlag (flagcode f)
+{
+  /*
+  ** True if opt controls the display of messages.
+  ** These flags must be processed first.
+  */
+
+  return (f == FLG_SHOWSCAN 
+         || f == FLG_WARNRC 
+         || f == FLG_PARENFILEFORMAT
+         || f == FLG_MESSAGESTREAMSTDERR
+         || f == FLG_MESSAGESTREAMSTDOUT
+         || f == FLG_WARNINGSTREAMSTDERR
+         || f == FLG_WARNINGSTREAMSTDOUT
+         || f == FLG_ERRORSTREAMSTDERR
+         || f == FLG_ERRORSTREAMSTDOUT
+         || f == FLG_MESSAGESTREAM
+         || f == FLG_WARNINGSTREAM
+         || f == FLG_ERRORSTREAM
+         || f == FLG_STREAMOVERWRITE);
+}
+
 /*
 ** Internal consistency check on the flags.
 */
@@ -823,7 +853,7 @@ describeFlag (cstring flagname)
     }
   else
     {
-      if (isMode (flagname))
+      if (flags_isModeName (flagname))
        {
          cstring_free (oflagname);
 
@@ -974,22 +1004,22 @@ flags_identifyFlagAux (cstring s, bool quiet)
 
   if (cstring_firstChar (s) == 'I')
     {
-      return FLG_INCLUDEPATH; /* no space after -I */
+      return FLG_INCLUDEPATH; /* no space required after -I */
     }
 
   if (cstring_firstChar (s) == 'S') 
     {
-      return FLG_SPECPATH;    /* no space after -S */
+      return FLG_SPECPATH;    /* no space required after -S */
     }
 
   if (cstring_firstChar (s) == 'D') 
     {
-      return FLG_DEFINE;      /* no space after -D */
+      return FLG_DEFINE;      /* no space required after -D */
     }
 
   if (cstring_firstChar (s) == 'U') 
     {
-      return FLG_UNDEFINE;    /* no space after -D */
+      return FLG_UNDEFINE;    /* no space required after -D */
     }
 
   cflag = canonicalizeFlag (s);
@@ -1051,7 +1081,7 @@ flags_identifyFlagAux (cstring s, bool quiet)
        }
       else if (cstring_equalLit (cflag, "ansireservedlocal"))
        {
-         res = FLG_ANSIRESERVEDLOCAL;
+         res = FLG_ISORESERVEDLOCAL;
        }
       else if (cstring_equalLit (cflag, "warnposix"))
        {
@@ -1095,15 +1125,15 @@ flags_identifyFlagAux (cstring s, bool quiet)
        }
       else if (cstring_equalLit (cflag, "skipansiheaders"))
        {
-         res = FLG_SKIPANSIHEADERS;
+         res = FLG_SKIPISOHEADERS;
        }
       else if (cstring_equalLit (cflag, "ansireserved"))
        {
-         res = FLG_ANSIRESERVED;
+         res = FLG_ISORESERVED;
        }
       else if (cstring_equalLit (cflag, "ansireservedinternal"))
        {
-         res = FLG_ANSIRESERVEDLOCAL;
+         res = FLG_ISORESERVEDLOCAL;
        }
       
       /*
@@ -1180,6 +1210,23 @@ flags_identifyFlagAux (cstring s, bool quiet)
          
          res = SKIP_FLAG;
        }
+      else if (cstring_equalLit (cflag, "usestderr"))
+       {
+         if (!quiet)
+           {
+             llerror_flagWarning 
+               (cstring_makeLiteral
+                ("usestderr flag is obsolete. This has been replaced "
+                 "by more precise flags for controlling the warning, "
+                 "status message and fatal error streams independently: message-stream-stdout, "
+                 "message-stream-stderr, message-stream <file>, "
+                 "warning-stream-stdout, warning-stream-stderr, warning-stream <file>, "
+                 "error-stream-stdout, error-stream-stderr, error-stream <file>."));
+           }
+         
+         res = SKIP_FLAG;
+       }
+
       else if (cstring_equalLit (cflag, "stdio"))
        {
          if (!quiet) 
@@ -1194,6 +1241,10 @@ flags_identifyFlagAux (cstring s, bool quiet)
          
          res = SKIP_FLAG;
        }
+      else if (flags_isModeName (cflag))
+       {
+         res = MODENAME_FLAG;
+       }
       else
        {
          res = INVALID_FLAG;
@@ -1355,7 +1406,7 @@ listModes (void)
 # endif
 
 bool
-isMode (cstring s)
+flags_isModeName (cstring s)
 {
   allModes (modename)
     {
@@ -1501,4 +1552,374 @@ bool flagcode_isNamePrefixFlag (flagcode f)
       return FALSE;
     }
 }
-       
+
+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 LARCH_PATH: %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))
+    {
+      showHerald ();
+      lldiagmsg (message ("File listed multiple times: %s", s));
+      cstring_free (s);
+    }
+  else
+    {
+      fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
+    }
+}
+
+static void addXHFile (fileIdList files, /*@temp@*/ cstring s)
+{
+  cstring pathName = findLarchPathFile (s);
+
+  if (cstring_isDefined (pathName))
+    {
+      if (fileTable_exists (context_fileTable (), pathName))
+       {
+         showHerald ();
+         lldiagmsg (message ("File listed multiple times: %s", s));
+       }
+      else
+       {
+         fileIdList_add (files, fileTable_addXHFile (context_fileTable (), pathName));
+       }
+    }
+
+  cstring_free (pathName);
+}
+
+void
+flags_processFlags (bool inCommandLine, 
+                   fileIdList xfiles,
+                   fileIdList cfiles,
+                   fileIdList lclfiles,
+                   fileIdList mtfiles,
+                   cstringSList *passThroughArgs,
+                   int argc, char **argv)
+{
+  int i;
+  cstringSList fl = cstringSList_undefined;
+    
+  for (i = 0; i < argc; i++)
+    {
+      char *thisarg;
+
+      llassert (argv != NULL);
+      thisarg = argv[i];
+
+      DPRINTF (("thisarg: %s", thisarg));
+
+      if (*thisarg == '-' || *thisarg == '+')
+       {
+         bool set = (*thisarg == '+');
+         cstring flagname = cstring_fromChars (thisarg + 1); /* skip '-' or '+' */
+         flagcode opt = flags_identifyFlag (flagname);
+
+         DPRINTF (("Flag: %s", flagcode_unparse (opt)));
+         
+         if (flagcode_isInvalid (opt))
+           {
+             DPRINTF (("Error!"));
+             voptgenerror (FLG_BADFLAG,
+                           message ("Unrecognized option: %s", 
+                                    cstring_fromChars (thisarg)),
+                           g_currentloc);
+           }
+         else if (flagcode_isHelpFlag (opt))
+           {
+             if (inCommandLine)
+               {
+                 voptgenerror (FLG_BADFLAG,
+                               message ("Help flag must be first on the command line: %s", 
+                                        cstring_fromChars (thisarg)),
+                               g_currentloc);
+               }
+             else
+               {
+                 voptgenerror (FLG_BADFLAG,
+                               message ("Help flags can only be used on the command line: %s", 
+                                        cstring_fromChars (thisarg)),
+                               g_currentloc);
+               }
+           }
+         else if (flagcode_isPassThrough (opt)) /* preprocessor flag: -D or -U */
+           { 
+             /*
+             ** Following space is optional, don't include the -
+             */
+             
+             *passThroughArgs = cstringSList_add (*passThroughArgs, 
+                                                  cstring_fromChars (thisarg + 1));
+           }
+         else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
+           {
+             cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
+             
+             DPRINTF (("Directory: %s", dir));
+             
+             switch (opt)
+               {
+               case FLG_INCLUDEPATH:
+                 cppAddIncludeDir (dir);
+                 /*@switchbreak@*/ break;
+               case FLG_SPECPATH:
+                 /*@-mustfree@*/
+                 g_localSpecPath = cstring_toCharsSafe
+                   (message ("%s%h%s", 
+                             cstring_fromChars (g_localSpecPath), 
+                             PATH_SEPARATOR,
+                             dir));
+                 /*@=mustfree@*/
+                 /*@switchbreak@*/ break;
+                 BADDEFAULT;
+               }
+           }
+         else if (flagcode_isModeName (opt))
+           {
+             context_setMode (flagname);
+           }
+         else if (flagcode_isMessageControlFlag (opt))
+           {
+             /*
+             ** Processed on first pass
+             */
+             
+             if (flagcode_hasArgument (opt))
+               {
+                 ++i;
+               }
+           }
+         else
+           {
+             /*
+             ** A normal control flag
+             */
+
+             context_userSetFlag (opt, set);
+             
+             if (flagcode_hasArgument (opt))
+               {
+                 if (flagcode_hasNumber (opt))
+                   {
+                     if (++i < argc)
+                       {
+                         setValueFlag (opt, cstring_fromChars (argv[i]));
+                       }
+                     else
+                       {
+                         voptgenerror
+                           (FLG_BADFLAG,
+                            message
+                            ("Flag %s must be followed by a number",
+                             flagcode_unparse (opt)),
+                            g_currentloc);
+                       }
+                   } 
+                 else if (flagcode_hasChar (opt))
+                   {
+                     if (++i < argc)
+                       {
+                         setValueFlag (opt, cstring_fromChars (argv[i]));
+                       }
+                     else
+                       {
+                         voptgenerror
+                           (FLG_BADFLAG,
+                            message
+                            ("Flag %s must be followed by a character",
+                             flagcode_unparse (opt)),
+                            g_currentloc);
+                       }
+                   } 
+                 else if (flagcode_hasString (opt)
+                          || opt == FLG_INIT || opt == FLG_OPTF)
+                   {
+                     if (++i < argc)
+                       {
+                         cstring arg = cstring_fromChars (argv[i]);
+                         
+                         if (opt == FLG_OPTF)
+                           {
+                             if (inCommandLine)
+                               {
+                                 ; /* -f already processed */
+                               }
+                             else
+                               {
+                                 (void) rcfiles_read (arg, passThroughArgs, TRUE);
+                               }
+                           }
+                         else if (opt == FLG_INIT)
+                           {
+# ifndef NOLCL
+                             lslinit_setInitFile (inputStream_create 
+                                                  (arg, 
+                                                   cstring_makeLiteralTemp (LCLINIT_SUFFIX),
+                                                   FALSE));
+# endif
+                             break;
+                           }
+                         else
+                           {
+                             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, cstring_copy (arg));
+                               }
+                           }
+                       }
+                     else
+                       {
+                         voptgenerror
+                           (FLG_BADFLAG,
+                            message
+                            ("Flag %s must be followed by a string",
+                             flagcode_unparse (opt)),
+                            g_currentloc);
+                       }
+                   }
+                 else
+                   {
+                     /* no argument */
+                   }
+               }
+           }
+       }
+      else /* its a filename */
+       {
+         DPRINTF (("Adding filename: %s", thisarg));
+         fl = cstringSList_add (fl, cstring_fromChars (thisarg));
+       }
+    }
+  
+  /*
+  ** create lists of C and LCL files
+  */
+  
+  if (inCommandLine)
+    {
+      cstringSList_elements (fl, current)
+       {
+         cstring ext = fileLib_getExtension (current);
+         
+         if (cstring_isUndefined (ext))
+           {
+             /* no extension --- both C and LCL with default extensions */
+             
+             addFile (cfiles, message ("%s%s", current, C_EXTENSION));
+             addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
+           }
+         else if (cstring_equal (ext, XH_EXTENSION))
+           {
+             addXHFile (xfiles, current);
+           }
+         else if (cstring_equal (ext, PP_EXTENSION))
+           {
+             if (!context_getFlag (FLG_NOPP))
+               {
+                 voptgenerror 
+                   (FLG_FILEEXTENSIONS,
+                    message ("File extension %s used without +nopp flag (will be processed as C source code): %s", 
+                             ext, current),
+                    g_currentloc);
+               }
+             
+             addFile (cfiles, cstring_copy (current));
+           }
+         else if (cstring_equal (ext, LCL_EXTENSION)) 
+           {
+             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;
+    }
+  else
+    {
+      if (cstringSList_size (fl) != 0)
+       {
+         /* Cannot list files in .splintrc files */
+         voptgenerror (FLG_BADFLAG, 
+                       message ("Cannot list files in .splintrc files: %s (probable missing + or -)",
+                                cstringSList_unparse (fl)),
+                       g_currentloc);
+       }
+    }
+}
This page took 0.051296 seconds and 4 git commands to generate.