write: Get rid of gengetopt's string parser.
authorAndre Noll <maan@systemlinux.org>
Sun, 29 Jul 2012 17:49:46 +0000 (19:49 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 27 Aug 2012 11:01:08 +0000 (13:01 +0200)
It causes gengetopt to generate quite some additional code for
the string parsers of all writers. Moreover, this string parser is
inferior to create_argv() and create_shifted_argv() of string.c as
gengetopt's parser does not honor any quoting at all.

This commit changes the signature of the ->parse_config_or_die method
of struct writer to take an (argc, argv) pair instead of a string.  All
writers can thus call the vanilla command line parser of gengetopt. The
single user in write_common.c now calls ->parse_config_or_die()
with an (argc, argv) pair obtained from create_shifted_argv().

alsa_write.c
ao_write.c
audiod.c
file_write.c
m4/gengetopt/makefile
oss_write.c
osx_write.c
write.c
write.h
write_common.c

index 2e096c0..73c9b82 100644 (file)
@@ -328,12 +328,12 @@ err:
        t->error = ret;
 }
 
-__malloc static void *alsa_parse_config_or_die(const char *options)
+__malloc static void *alsa_parse_config_or_die(int argc, char **argv)
 {
        struct alsa_write_args_info *conf = para_calloc(sizeof(*conf));
 
        /* exits on errors */
-       alsa_cmdline_parser_string(options, conf, "alsa_write");
+       alsa_cmdline_parser(argc, argv, conf);
        return conf;
 }
 
index a45d4fb..165caa0 100644 (file)
@@ -337,12 +337,12 @@ out:
        t->error = ret;
 }
 
-__malloc static void *aow_parse_config_or_die(const char *options)
+__malloc static void *aow_parse_config_or_die(int argc, char **argv)
 {
        struct ao_write_args_info *conf = para_calloc(sizeof(*conf));
 
        /* exits on errors */
-       ao_cmdline_parser_string(options, conf, "ao_write");
+       ao_cmdline_parser(argc, argv, conf);
        return conf;
 }
 
index 9f2aa5a..4fc04b5 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -806,17 +806,19 @@ static int parse_writer_args(void)
        }
        /* Use default writer for audio formats which are not yet set up. */
        FOR_EACH_AUDIO_FORMAT(i) {
-               struct writer *w = writers + DEFAULT_WRITER;
+               void *writer_conf;
+               int writer_num;
                a = afi + i;
                if (a->num_writers > 0)
                        continue; /* already set up */
-               PARA_INFO_LOG("%s writer: %s (default)\n", audio_formats[i],
-                       writer_names[DEFAULT_WRITER]);
+               writer_conf = check_writer_arg_or_die(NULL, &writer_num);
                a->writer_nums = para_malloc(sizeof(int));
-               a->writer_nums[0] = DEFAULT_WRITER;
+               a->writer_nums[0] = writer_num;
                a->writer_conf = para_malloc(sizeof(void *));
-               a->writer_conf[0] = w->parse_config_or_die("");
+               a->writer_conf[0] = writer_conf;
                a->num_writers = 1;
+               PARA_INFO_LOG("%s writer: %s (default)\n", audio_formats[i],
+                       writer_names[writer_num]);
        }
        return 1;
 }
index 98d15a4..9817571 100644 (file)
@@ -133,12 +133,12 @@ out:
        t->error = ret;
 }
 
-__malloc static void *file_write_parse_config_or_die(const char *options)
+__malloc static void *file_write_parse_config_or_die(int argc, char **argv)
 {
        struct file_write_args_info *conf = para_calloc(sizeof(*conf));
 
        /* exits on errors */
-       file_cmdline_parser_string(options, conf, "file_write");
+       file_cmdline_parser(argc, argv, conf);
        return conf;
 }
 
index e132411..cc5835c 100644 (file)
@@ -19,7 +19,7 @@ $(cmdline_dir)/%_filter.cmdline.h $(cmdline_dir)/%_filter.cmdline.c: $(ggo_dir)/
                --func-name=$(subst _filter.ggo,,$(<F))_cmdline_parser < $<
 $(cmdline_dir)/%_write.cmdline.h $(cmdline_dir)/%_write.cmdline.c: $(ggo_dir)/%_write.ggo | $(cmdline_dir)
        @[ -z "$(Q)" ] || echo 'GGO $<'
-       $(Q) $(GENGETOPT) -S $(module_ggo_opts) \
+       $(Q) $(GENGETOPT) $(module_ggo_opts) \
                --output-dir=$(cmdline_dir) \
                --set-package=$(subst .ggo,,$(<F)) \
                --arg-struct-name=$(subst .ggo,,$(<F))_args_info \
index 1d9add7..57e2387 100644 (file)
@@ -202,12 +202,12 @@ out:
                btr_remove_node(&wn->btrn);
 }
 
-__malloc static void *oss_parse_config_or_die(const char *options)
+__malloc static void *oss_parse_config_or_die(int argc, char **argv)
 {
        struct oss_write_args_info *conf = para_calloc(sizeof(*conf));
 
        /* exits on errors */
-       oss_cmdline_parser_string(options, conf, "oss_write");
+       oss_cmdline_parser(argc, argv, conf);
        return conf;
 }
 
index 2c6fd0d..69a781c 100644 (file)
@@ -217,12 +217,12 @@ e0:
        return ret;
 }
 
-__malloc static void *osx_write_parse_config_or_die(const char *options)
+__malloc static void *osx_write_parse_config_or_die(int argc, char **argv)
 {
        struct osx_write_args_info *conf = para_calloc(sizeof(*conf));
 
        /* exits on errors */
-       osx_cmdline_parser_string(options, conf, "osx_write");
+       osx_cmdline_parser(argc, argv, conf);
        return conf;
 }
 
diff --git a/write.c b/write.c
index de73000..df37d7e 100644 (file)
--- a/write.c
+++ b/write.c
@@ -187,12 +187,7 @@ __noreturn static void print_help_and_die(void)
 static void setup_writer_node(const char *arg, struct btr_node *parent,
                struct writer_node *wn, struct sched *s)
 {
-       if (arg)
-               wn->conf = check_writer_arg_or_die(arg, &wn->writer_num);
-       else {
-               wn->writer_num = DEFAULT_WRITER;
-               wn->conf = writers[DEFAULT_WRITER].parse_config_or_die("");
-       }
+       wn->conf = check_writer_arg_or_die(arg, &wn->writer_num);
        register_writer_node(wn, parent, s);
 }
 
diff --git a/write.h b/write.h
index ddf43b6..c43e8dc 100644 (file)
--- a/write.h
+++ b/write.h
@@ -39,14 +39,14 @@ struct writer {
        /**
         * The command line parser of the writer.
         *
-        * It should check whether the command line options given by \a options
-        * are valid and return a pointer to the writer-specific configuration
-        * data determined by \a options. This function must either succeed or
-        * call exit(). Note that parse_config_or_die() might be called more
-        * than once with different values of \a options. \sa \ref
-        * free_config().
+        * It should check whether the command line options given by \a argv
+        * and \a argc are valid and return a pointer to the writer-specific
+        * configuration data determined by these options. This function must
+        * either succeed or call exit(). Note that parse_config_or_die() might
+        * be called more than once with different values of \a options. \sa
+        * \ref free_config().
         */
-       void *(*parse_config_or_die)(const char *options);
+       void *(*parse_config_or_die)(int argc, char **argv);
        /**
         * Dellocate all configuration resources.
         *
index e6a5eeb..602f94d 100644 (file)
@@ -50,25 +50,46 @@ void writer_init(void)
  */
 void *check_writer_arg_or_die(const char *wa, int *writer_num)
 {
-       int i;
-
+       int i, ret, argc;
+       const char *cmdline;
+       char **argv;
+       void *conf;
+
+       if (!wa || !*wa) {
+               i = DEFAULT_WRITER;
+               cmdline = NULL;
+               goto check;
+       }
        PARA_INFO_LOG("checking %s\n", wa);
        FOR_EACH_WRITER(i) {
                const char *name = writer_names[i];
                size_t len = strlen(name);
                char c;
+
                if (strlen(wa) < len)
                        continue;
                if (strncmp(name, wa, len))
                        continue;
                c = wa[len];
-               if (c && c != ' ')
-                       continue;
-               *writer_num = i;
-               return writers[i].parse_config_or_die(c? wa + len + 1 : "");
+               if (!c || c == ' ') {
+                       cmdline = c? wa + len + 1 : NULL;
+                       goto check;
+               }
        }
        PARA_EMERG_LOG("invalid writer %s\n", wa);
        exit(EXIT_FAILURE);
+check:
+       ret = create_shifted_argv(cmdline, " \t", &argv);
+       if (ret < 0) {
+               PARA_EMERG_LOG("%s: %s\n", wa, para_strerror(-ret));
+               exit(EXIT_FAILURE);
+       }
+       argc = ret;
+       argv[0] = make_message("%s_write", writer_names[i]);
+       *writer_num = i;
+       conf = writers[i].parse_config_or_die(argc, argv);
+       free_argv(argv);
+       return conf;
 }
 
 /**