shithub: sox

Download patch

ref: b14587a37c96ccd255c4d8d71d866f694ff42b7b
parent: 2e15982e42e393b26f468b770236f8488863f0f3
author: robs <robs>
date: Sun Feb 8 15:28:09 EST 2009

combine strtoargv code, add escaping; change volume keys

--- a/src/sox.c
+++ b/src/sox.c
@@ -24,6 +24,7 @@
 #include "sox.h"
 #include "util.h"
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <math.h>
@@ -121,6 +122,7 @@
   {0, 0}};
 static rg_mode replay_gain_mode = RG_default;
 static sox_option_t show_progress = SOX_OPTION_DEFAULT;
+#define SOX_OPTS "SOX_OPTS"
 
 
 /* Input & output files */
@@ -204,6 +206,11 @@
 {
   size_t i;
 
+  if (!success) {
+    char const * env_opts = getenv(SOX_OPTS);
+    if (env_opts)
+      lsx_report(SOX_OPTS"=%s", env_opts);
+  }
   /* Close the input and output files before exiting. */
   for (i = 0; i < input_count; i++) {
     if (files[i]->ft) {
@@ -693,12 +700,12 @@
 
 static sox_bool is_pseudo_effect(char *s)
 {
+  if (s)
   if (strcmp("newfile", s) == 0 ||
       strcmp("restart", s) == 0 ||
       strcmp(":", s) == 0)
     return sox_true;
-  else
-    return sox_false;
+  return sox_false;
 } /* is_pseudo_effect */
 
 static void parse_effects(int argc, char **argv)
@@ -776,67 +783,42 @@
   }
 } /* parse_effects */
 
-static int strtoargv(char *s, char *(*argv)[])
+static char * * strtoargv(char * s, int * argc)
 {
-    int argc = 0;
+  sox_bool quote = sox_false;    /* Quote mode (") is in effect. */
+  sox_bool esc = sox_false;      /* Escape mode (\) is in effect. */
+  char * t, * * argv = NULL;
 
-    if (!s) return 0;
+  for (*argc = 0; *s; ++*argc) {
+    for (; isspace(*s); ++s);    /* Skip past any white space. */
+    if (!*s)                     /* All done? */
+      break;
 
-    while (*s)
-    {
-        int quote_mode;
+    lsx_revalloc(argv, *argc + 1);
+    argv[*argc] = s;
 
-        /* Skip past any white space */
-        while (*s == ' ' || *s == '\t')
-            s++;
-
-        /* Stop processing if no more data */
-        if (!*s)
-            break;
-
-        /* If starts with quote then start quote mode.  This
-         * will ignore seperators until a final quote is seen.
-         * Don't put quote into the argument.
-         */
-        if (*s == '"')
-        {
-            quote_mode = 1;
-            s++;
-        }
-        else
-            quote_mode = 0;
-
-        (*argv)[argc] = s;
-
-        /* Scan for seperator and when overwrite with 0 */
-        while (*s)
-        {
-            /* Treat quote as final seperator; even if there is
-             * more data right after it.
-             * TODO: Process \" and \\ so that user can
-             * have quotes inside quotes.  Tricky to do though.
-             */
-            if (quote_mode && *s == '"')
-                break;
-
-            if (!quote_mode && (*s == ' ' || *s == '\t'))
-                break;
-            s++;
-        }
-        *s = 0;
-        s++;
-        argc += 1;
+    for (t = s; *s; ++s) {       /* End with space or nul. */
+      *t = *s;
+      if (!esc && !quote && isspace(*s))
+        break;
+      if (!esc && *s == '"')     /* Toggle quote mode. */
+        quote = !quote;
+      else if (!(esc = !esc && *s == '\\' && s[1] && (s[1] == '"' || !quote)))
+        ++t;                     /* Only advance if not an active " or \ */
     }
+    if (*s)
+      ++s;                       /* Skip the separator. */
+    *t = '\0';                   /* Overwrite separator with (or append) nul. */
+  }
+  return argv;
+}                                /* strtoargv */
 
-    return argc;
-} /* strtoargv */
-
 static void read_user_effects(char *filename)
 {
     FILE *file = fopen(filename, "rt");
     char s[FILENAME_MAX];
     int argc;
-    char *argv[FILENAME_MAX];
+    char * * argv;
     int len;
 
     /* Free any command line options and then re-initialize to
@@ -860,32 +842,34 @@
       if (s[len-1] == '\n')
         s[len-1] = 0;
 
-      argc = strtoargv(s, &argv);
+      argv = strtoargv(s, &argc);
 
-      /* Make sure first option is an effect name. */
-      if (!sox_find_effect(argv[0]) && !is_pseudo_effect(argv[0]))
-      {
-        printf("Cannot find an effect called `%s'.\n", argv[0]);
-        exit(1);
-      }
+      if (argv) {
+        /* Make sure first option is an effect name. */
+        if (!sox_find_effect(argv[0]) && !is_pseudo_effect(argv[0]))
+        {
+          printf("Cannot find an effect called `%s'.\n", argv[0]);
+          exit(1);
+        }
 
-      /* parse_effects normally parses options from command line.
-       * Reset opt index so it thinks its back at beginning of
-       * main()'s argv[].
-       */
-      optind = 0;
-      parse_effects(argc, argv);
+        /* parse_effects normally parses options from command line.
+         * Reset opt index so it thinks its back at beginning of
+         * main()'s argv[].
+         */
+        optind = 0;
+        parse_effects(argc, argv);
 
-      /* Advance to next effect but only if current chain has been
-       * filled in.  This recovers from side affects of psuedo-effects.
-       */
-      if (nuser_effects[eff_chain_count] > 0)
-      {
-        eff_chain_count++;
-        add_eff_chain();
+        /* Advance to next effect but only if current chain has been
+         * filled in.  This recovers from side affects of psuedo-effects.
+         */
+        if (nuser_effects[eff_chain_count] > 0)
+        {
+          eff_chain_count++;
+          add_eff_chain();
+        }
+        free(argv);
       }
     }
-
     fclose(file);
 
 } /* read_user_effects */
@@ -1238,8 +1222,8 @@
     }
 #endif
     switch (ch) {
-      case 'u': adjust_volume(+7); break;
-      case 'd': adjust_volume(-7); break;
+      case 'V': adjust_volume(+7); break;
+      case 'v': adjust_volume(-7); break;
     }
   }
 
@@ -2380,7 +2364,7 @@
 
 static void parse_options_and_filenames(int argc, char **argv)
 {
-  char * env_opts = lsx_strdup(getenv("SOX_OPTS"));
+  char const * env_opts = getenv(SOX_OPTS);
   file_t opts, opts_none;
   init_file(&opts), init_file(&opts_none);
 
@@ -2388,25 +2372,19 @@
     add_file(&opts, set_default_device(&opts)), init_file(&opts);
 
   if (env_opts) {
-    char * * argv2, * p = env_opts;
-    int argc2 = 0;
-    lsx_valloc(argv2, 1);
-    for (argv2[argc2++] = argv[0]; *p; ++p)
-      if (argc2 == 1 || *p == ' ') {
-        while (*p == ' ')
-          *p++ = '\0';
-        if (*p) {
-          lsx_revalloc(argv2, argc2 + 1);
-          argv2[argc2++] = p;
-        }
-      }
+    char * * argv2, * str = lsx_malloc(strlen(argv[0]) + strlen(env_opts) + 2);
+    int argc2;
+    strcpy(str, argv[0]);
+    strcat(str, " ");
+    strcat(str, env_opts);
+    argv2 = strtoargv(str, &argc2);
     if (parse_gopts_and_fopts(&opts, argc2, argv2)) {
-      lsx_fail("invalid option for SOX_OPTS");
+      lsx_fail("invalid option for "SOX_OPTS);
       exit(1);
     }
     optind = 1, opterr = 0;
+    free(str);
     free(argv2);
-    free(env_opts);
   }
 
   for (; optind < argc && !sox_find_effect(argv[optind]); init_file(&opts)) {
@@ -2629,7 +2607,7 @@
 
 #ifdef HAVE_OPENMP
   if (single_threaded)
-   omp_set_num_threads(1);
+    omp_set_num_threads(1);
 #endif
 
   if (sox_globals.verbosity > 2)