shithub: sox

Download patch

ref: 832bdd1b6f039aac8a14703b45dcf5ce36650f11
parent: f586524ae48ec4b8891fcc2e9c0e233107ece0da
author: robs <robs>
date: Sat Dec 16 07:07:14 EST 2006

Sox option parser clean-ups and checks

--- a/TODO
+++ b/TODO
@@ -102,5 +102,5 @@
     chunks (except LIST which is already handled), especially at the
     end of the file.
 
-  o All option-parsers should fail if extraneous charcters or arguments
-    are present. e.g. -v 1dB, vol 3mW, speed 2 3, should all fail.
+  o Effects option-parsers should fail if extraneous characters or arguments
+    are present. e.g. vol 3mW, speed 2 3, etc. should all fail.
--- a/src/sox.c
+++ b/src/sox.c
@@ -338,199 +338,152 @@
 static struct option long_options[] =
 {
     {"version", 0, NULL, 0},
-    {"help", 0, NULL, 'h'},
-    {"help-effect", 1, NULL, 0},
+    {"help-effect", required_argument, NULL, 0},
     {"comment", required_argument, NULL, 0},
     {"comment-file", required_argument, NULL, 0},
+
+    {"help", 0, NULL, 'h'},
     {NULL, 0, NULL, 0}
 };
 
-static bool doopts(file_options_t *fo, int argc, char **argv)
+static bool doopts(file_options_t * fo, int argc, char **argv)
 {
-    int c, i;
+  while (true) {
+    int i;          /* Needed since scanf %u allows negative numbers :( */
+    char dummy;     /* To check for extraneous chars in optarg. */
     int option_index;
-    char *str;
+    int c = getopt_long(argc, argv, getoptstr, long_options, &option_index);
 
-    while ((c = getopt_long(argc, argv, getoptstr, 
-                            long_options, &option_index)) != -1) {
-        switch(c) {
-            case 0:
-                if (option_index == 3)
-                {
-                  fo->comment = strdup(optarg);
-                  break;
-                }
-                else if (option_index == 4)
-                {
-                  fo->comment = read_comment_file(optarg);
-                  break;
-                }
-                else if (strncmp("help-effect", long_options[option_index].name,
-                            11) == 0)
-                    usage_effect(optarg);
-                else if (strncmp("version", long_options[option_index].name,
-                            7) == 0)
-                {
-                    printf("%s: ", myname);
-                    printf("v%s\n", st_version());
-                    exit(0);
-                }
-                /* no return from above */
-                break;
+    if (c == -1)    /* No more options. */
+      return false; /* Is not null file. */
 
-            case 'e': case 'n':
-                return true; /* is null file */
+    switch (c) {
+      case 0:       /* Long options with no short equivalent. */
+        switch (option_index) {
+          case 0:
+            printf("%s: v%s\n", myname, st_version());
+            exit(0);
+            break;
 
-            case 'o':
-                globalinfo.octave_plot_effect = true;
-                break;
+          case 1:
+            usage_effect(optarg);
+            break;
 
-            case 'h':
-                usage((char *)0);
-                /* no return from above */
-                break;
+          case 2:
+            fo->comment = strdup(optarg);
+            break;
 
-            case 't':
-                fo->filetype = optarg;
-                if (fo->filetype[0] == '.')
-                    fo->filetype++;
-                break;
+          case 3:
+            fo->comment = read_comment_file(optarg);
+            break;
+        }
+        break;
 
-            case 'r':
-                str = optarg;
-                if ((!sscanf(optarg, "%u", &fo->info.rate)) ||
-                    (fo->info.rate <= 0))
-                {
-                    st_fail("-r must be given a positive integer");
-                    cleanup();
-                    exit(1);
-                }
-                break;
-            case 'v':
-                str = optarg;
-                if (!sscanf(str, "%lf", &fo->volume))
-                {
-                    st_fail("Volume value '%s' is not a number",
-                            optarg);
-                    cleanup();
-                    exit(1);
-                }
-                fo->uservolume = 1;
-                if (fo->volume < 0.0)
-                    st_report("Volume adjustment is negative.  This will result in a phase change");
-                break;
+      case 'e': case 'n':
+        return true;            /* Is null file. */
 
-            case 'c':
-                str = optarg;
-                if (!sscanf(str, "%d", &i))
-                {
-                    st_fail("-c must be given a number");
-                    cleanup();
-                    exit(1);
-                }
-                /* Since we use -1 as a special internal value,
-                 * we must do some extra logic so user doesn't
-                 * get confused when we translate -1 to mean
-                 * something valid.
-                 */
-                if (i < 1)
-                {
-                    st_fail("-c must be given a positive number");
-                    cleanup();
-                    exit(1);
-                }
-                fo->info.channels = i;
-                break;
+      case 'o':
+        globalinfo.octave_plot_effect = true;
+        break;
 
-            case 'C':
-                str = optarg;
-                if (!sscanf(str, "%lf", &fo->info.compression))
-                {
-                    st_fail("-C must be given a number");
-                    cleanup();
-                    exit(1);
-                }
-                break;
+      case 'h': case '?':
+        usage((char *) 0);      /* No return */
+        break;
 
-            case '1': case 'b':
-                fo->info.size = ST_SIZE_BYTE;
-                break;
-            case '2': case 'w':
-                fo->info.size = ST_SIZE_WORD;
-                break;
-            case '3':
-                fo->info.size = ST_SIZE_24BIT;
-                break;
-            case '4': case 'l':
-                fo->info.size = ST_SIZE_DWORD;
-                break;
-            case '8': case 'd':
-                fo->info.size = ST_SIZE_DDWORD;
-                break;
-            case 's':
-                fo->info.encoding = ST_ENCODING_SIGN2;
-                break;
-            case 'u':
-                fo->info.encoding = ST_ENCODING_UNSIGNED;
-                break;
-            case 'U':
-                fo->info.encoding = ST_ENCODING_ULAW;
-                if (fo->info.size == -1)
-                    fo->info.size = ST_SIZE_BYTE;
-                break;
-            case 'A':
-                fo->info.encoding = ST_ENCODING_ALAW;
-                if (fo->info.size == -1)
-                    fo->info.size = ST_SIZE_BYTE;
-                break;
-            case 'f':
-                fo->info.encoding = ST_ENCODING_FLOAT;
-                break;
-            case 'a':
-                fo->info.encoding = ST_ENCODING_ADPCM;
-                break;
-            case 'i':
-                fo->info.encoding = ST_ENCODING_IMA_ADPCM;
-                break;
-            case 'g':
-                fo->info.encoding = ST_ENCODING_GSM;
-                break;
+      case 't':
+        fo->filetype = optarg;
+        if (fo->filetype[0] == '.')
+          fo->filetype++;
+        break;
 
-            case 'x':
-                fo->info.swap = 1;
-                break;
+      case 'r':
+        if (sscanf(optarg, "%i %c", &i, &dummy) != 1 || i <= 0) {
+          st_fail("Rate value '%s' is not a positive integer", optarg);
+          cleanup();
+          exit(1);
+        }
+        fo->info.rate = i;
+        break;
 
-            case 'V':
-                str = optarg;
-                if (optarg == NULL)
-                {
-                  ++st_output_verbosity_level;
-                }
-                else if (sscanf(str, "%i", &st_output_verbosity_level) == 0)
-                {
-                  st_fail("argument for -V must be an integer");
-                  cleanup();
-                  exit(1);
-                }
-                break;
+      case 'v':
+        if (sscanf(optarg, "%lf %c", &fo->volume, &dummy) != 1) {
+          st_fail("Volume value '%s' is not a number", optarg);
+          cleanup();
+          exit(1);
+        }
+        fo->uservolume = 1;
+        if (fo->volume < 0.0)
+          st_report("Volume adjustment is negative; "
+                    "this will result in a phase change");
+        break;
 
-            case 'S':
-                status = 1;
-                quiet = 0;
-                break;
+      case 'c':
+        if (sscanf(optarg, "%i %c", &i, &dummy) != 1 || i <= 0) {
+          st_fail("Channels value '%s' is not a positive integer", optarg);
+          cleanup();
+          exit(1);
+        }
+        fo->info.channels = i;
+        break;
 
-            case 'q':
-                status = 0;
-                quiet = 1;
-                break;
+      case 'C':
+        if (sscanf(optarg, "%lf %c", &fo->info.compression, &dummy) != 1) {
+          st_fail("Compression value '%s' is not a number", optarg);
+          cleanup();
+          exit(1);
+        }
+        break;
 
-            case '?':
-                usage((char *)0);
-                /* no return from above */
-                break;
+      case '1': case 'b': fo->info.size = ST_SIZE_BYTE;   break;
+      case '2': case 'w': fo->info.size = ST_SIZE_WORD;   break;
+      case '3':           fo->info.size = ST_SIZE_24BIT;  break;
+      case '4': case 'l': fo->info.size = ST_SIZE_DWORD;  break;
+      case '8': case 'd': fo->info.size = ST_SIZE_DDWORD; break;
+
+      case 's': fo->info.encoding = ST_ENCODING_SIGN2;     break;
+      case 'u': fo->info.encoding = ST_ENCODING_UNSIGNED;  break;
+      case 'f': fo->info.encoding = ST_ENCODING_FLOAT;     break;
+      case 'a': fo->info.encoding = ST_ENCODING_ADPCM;     break;
+      case 'i': fo->info.encoding = ST_ENCODING_IMA_ADPCM; break;
+      case 'g': fo->info.encoding = ST_ENCODING_GSM;       break;
+
+      case 'U': fo->info.encoding = ST_ENCODING_ULAW;
+        if (fo->info.size == -1)
+          fo->info.size = ST_SIZE_BYTE;
+        break;
+
+      case 'A': fo->info.encoding = ST_ENCODING_ALAW;
+        if (fo->info.size == -1)
+          fo->info.size = ST_SIZE_BYTE;
+        break;
+
+      case 'x':
+        fo->info.swap = 1;
+        break;
+
+      case 'V':
+        if (optarg == NULL)
+          ++st_output_verbosity_level;
+        else if (sscanf(optarg, "%i %c", &st_output_verbosity_level, &dummy)
+            != 1 || st_output_verbosity_level < 0) {
+          st_output_verbosity_level = 2;
+          st_fail("Verbosity value '%s' is not an integer >= 0", optarg);
+          cleanup();
+          exit(1);
         }
+        break;
+
+      case 'S':
+        status = 1;
+        quiet = 0;
+        break;
+
+      case 'q':
+        status = 0;
+        quiet = 1;
+        break;
     }
-    return false; /* is not null file */
+  }
 }
 
 static int compare_input(ft_t ft1, ft_t ft2)