conf: add generic argument array
authorDavid Herrmann <dh.herrmann@googlemail.com>
Mon, 16 Jul 2012 17:35:05 +0000 (19:35 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Mon, 16 Jul 2012 17:35:05 +0000 (19:35 +0200)
We want to be able to parse our argument-list from other sources, too, so
put them into a separate array so we are not dependent of getopt() and
others.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
src/conf.c
src/conf.h

index c17999c..c6d5f20 100644 (file)
@@ -77,84 +77,179 @@ static void print_help()
                "kmscon");
 }
 
+static bool parse_help(const char *arg)
+{
+       conf_global.help = 1;
+       return false;
+}
+
+static bool parse_verbose(const char *arg)
+{
+       conf_global.verbose = 1;
+       return false;
+}
+
+static bool parse_debug(const char *arg)
+{
+       conf_global.debug = 1;
+       return false;
+}
+
+static bool parse_silent(const char *arg)
+{
+       conf_global.silent = 1;
+       return false;
+}
+
+static bool parse_fbdev(const char *arg)
+{
+       conf_global.use_fbdev = 1;
+       return false;
+}
+
+static bool parse_switchvt(const char *arg)
+{
+       conf_global.switchvt = 1;
+       return false;
+}
+
+static bool parse_login(const char *arg)
+{
+       conf_global.login = (char*)arg;
+       return true;
+}
+
+static bool parse_term(const char *arg)
+{
+       conf_global.term = arg;
+       return false;
+}
+
+static bool parse_xkb_layout(const char *arg)
+{
+       conf_global.xkb_layout = arg;
+       return false;
+}
+
+static bool parse_xkb_variant(const char *arg)
+{
+       conf_global.xkb_variant = arg;
+       return false;
+}
+
+static bool parse_xkb_options(const char *arg)
+{
+       conf_global.xkb_options = arg;
+       return false;
+}
+
+static bool parse_seat(const char *arg)
+{
+       conf_global.seat = arg;
+       return false;
+}
+
+struct conf_option {
+       char short_name;
+       const char *long_name;
+       int needs_arg; // no_argument, required_argument or optional_argument
+       bool (*parse) (const char *arg);
+} options[] = {
+       { 'h', "help", no_argument, parse_help },
+       { 'v', "verbose", no_argument, parse_verbose },
+       { 0, "debug", no_argument, parse_debug },
+       { 0, "silent", no_argument, parse_silent },
+       { 0, "fbdev", no_argument, parse_fbdev },
+       { 's', "switchvt", no_argument, parse_switchvt },
+       { 'l', "login", required_argument, parse_login },
+       { 't', "term", required_argument, parse_term },
+       { 0, "xkb-layout", required_argument, parse_xkb_layout },
+       { 0, "xkb-variant", required_argument, parse_xkb_variant },
+       { 0, "xkb-options", required_argument, parse_xkb_options },
+       { 0, "seat", required_argument, parse_seat },
+};
+
 int conf_parse_argv(int argc, char **argv)
 {
-       int show_help = 0;
-       char short_options[] = ":hvsl:t:";
-       struct option long_options[] = {
-               { "help", no_argument, NULL, 'h' },
-               { "verbose", no_argument, NULL, 'v' },
-               { "debug", no_argument, &conf_global.debug, 1 },
-               { "silent", no_argument, &conf_global.silent, 1 },
-               { "switchvt", no_argument, NULL, 's' },
-               { "fbdev", no_argument, &conf_global.use_fbdev, 1 },
-               { "xkb-layout", required_argument, NULL, 1001 },
-               { "xkb-variant", required_argument, NULL, 1002 },
-               { "xkb-options", required_argument, NULL, 1003 },
-               { "login", required_argument, NULL, 'l' },
-               { "term", required_argument, NULL, 't' },
-               { "seat", required_argument, NULL, 1004 },
-               { NULL, 0, NULL, 0 },
-       };
-       int idx;
+       char *short_options;
+       struct option *long_options;
+       struct option *opt;
+       size_t len, i, pos;
        int c;
 
        if (!argv || argc < 1)
                return -EINVAL;
 
+       len = sizeof(options) / sizeof(struct conf_option);
+
+       short_options = malloc(sizeof(char) * (len + 1) * 2);
+       if (!short_options) {
+               log_error("cannot allocate enough memory to parse command line arguments (%d): %m");
+               return -ENOMEM;
+       }
+
+       long_options = malloc(sizeof(struct option) * len);
+       if (!long_options) {
+               log_error("cannot allocate enough memory to parse command line arguments (%d): %m");
+               free(short_options);
+               return -ENOMEM;
+       }
+
+       pos = 0;
+       short_options[pos++] = ':';
+       opt = long_options;
+       for (i = 0; i < len; ++i) {
+               if (options[i].short_name) {
+                       short_options[pos++] = options[i].short_name;
+                       if (options[i].needs_arg)
+                               short_options[pos++] = ':';
+               }
+
+               if (options[i].long_name) {
+                       opt->name = options[i].long_name;
+                       opt->has_arg = options[i].needs_arg;
+                       opt->flag = NULL;
+                       opt->val = 1000 + i;
+                       ++opt;
+               }
+       }
+       short_options[pos++] = 0;
+
        opterr = 0;
        while (1) {
                c = getopt_long(argc, argv, short_options,
-                               long_options, &idx);
-               if (c < 0)
-                       break;
-               switch (c) {
-               case 0:
-                       break;
-               case 'h':
-                       show_help = 1;
-                       break;
-               case 'v':
-                       conf_global.verbose = 1;
-                       break;
-               case 's':
-                       conf_global.switchvt = 1;
-                       break;
-               case 1001:
-                       conf_global.xkb_layout = optarg;
-                       break;
-               case 1002:
-                       conf_global.xkb_variant = optarg;
+                               long_options, NULL);
+               if (c <= 0)
                        break;
-               case 1003:
-                       conf_global.xkb_options = optarg;
-                       break;
-               case 1004:
-                       conf_global.seat = optarg;
-                       break;
-               case 'l':
-                       conf_global.login = optarg;
-                       --optind;
-                       goto done;
-               case 't':
-                       conf_global.term = optarg;
-                       break;
-               case ':':
+
+               if (c == ':') {
                        fprintf(stderr, "Missing argument for option -%c\n",
                                optopt);
-                       break;
-               case '?':
+               } else if (c == '?') {
                        if (optopt)
                                fprintf(stderr, "Unknown argument -%c\n",
                                        optopt);
                        else
                                fprintf(stderr, "Unknown argument %s\n",
                                        argv[optind - 1]);
-                       break;
+               } else if (c < 1000) {
+                       for (i = 0; i < len; ++i) {
+                               if (options[i].short_name == c) {
+                                       if (options[i].parse(optarg))
+                                               goto done;
+                                       break;
+                               }
+                       }
+               } else {
+                       if (options[c - 1000].parse(optarg))
+                               goto done;
                }
        }
 
 done:
+       free(long_options);
+       free(short_options);
+
        if (conf_global.login) {
                conf_global.argv = &argv[optind];
        } else {
@@ -181,7 +276,7 @@ done:
        if (!conf_global.seat)
                conf_global.seat = "seat0";
 
-       if (show_help) {
+       if (conf_global.help) {
                print_help();
                conf_global.exit = 1;
        }
index e477937..3f596ca 100644 (file)
@@ -43,6 +43,8 @@
 #include <unistd.h>
 
 struct conf_obj {
+       /* show help/usage information */
+       int help;
        /* exit application after parsing options */
        int exit;
        /* enable debug messages */