]> mj.ucw.cz Git - libucw.git/commitdiff
Opt: Streamlined opt_shortopt()
authorMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 14:51:47 +0000 (15:51 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 14:51:47 +0000 (15:51 +0100)
Also, we reject non-ASCII short options, which enabled us to lower
OPT_POSITIONAL_TAIL to 128 and thus save memory.

ucw/opt.c
ucw/opt.h

index bd1a8bf2832dc5e6f6ec2d075316b0ae8470599d..54f8b2b51c811a01cbf067977367ffa1d21a86b6 100644 (file)
--- a/ucw/opt.c
+++ b/ucw/opt.c
@@ -193,15 +193,6 @@ void opt_help(const struct opt_section * help) {
   }
 }
 
-static struct opt_precomputed * opt_find_item_shortopt(struct opt_context * oc, int chr) {
-  struct opt_precomputed * candidate = oc->shortopt[chr];
-  if (!candidate)
-    opt_failure("Invalid option -%c", chr);
-  if (candidate->count++ && (candidate->flags & OPT_SINGLE))
-    opt_failure("Option -%c appeared the second time.", candidate->item->letter);
-  return candidate;
-}
-
 static struct opt_precomputed * opt_find_item_longopt(struct opt_context * oc, char * str) {
   uns len = strlen(str);
   struct opt_precomputed * candidate = NULL;
@@ -382,52 +373,57 @@ static int opt_longopt(struct opt_context * oc, char ** argv, int index) {
 static int opt_shortopt(struct opt_context * oc, char ** argv, int index) {
   int chr = 0;
   struct opt_precomputed * opt;
-  while (argv[index][++chr] && (opt = opt_find_item_shortopt(oc, argv[index][chr]))) {
-    if (opt->flags & OPT_NO_VALUE) {
+  int o;
+
+  while (o = argv[index][++chr]) {
+    if (o < 0 || o >= 128)
+      opt_failure("Invalid character 0x%02x in option name. Only ASCII is allowed.", o & 0xff);
+    opt = oc->shortopt[o];
+
+    if (!opt)
+      opt_failure("Unknown option -%c.", o);
+
+    if (opt->count && (opt->flags & OPT_SINGLE))
+      opt_failure("Option -%c must be specified at most once.", o);
+    opt->count++;
+
+    if (opt->flags & OPT_NO_VALUE)
       opt_parse_value(oc, opt, NULL, 0);
-    }
     else if (opt->flags & OPT_REQUIRED_VALUE) {
       if (chr == 1 && argv[index][2]) {
         opt_parse_value(oc, opt, argv[index] + 2, 0);
        return 0;
-      }
-      else if (argv[index][chr+1])
-       opt_failure("Option -%c must have a value but found inside a bunch of short opts.", opt->item->letter);
+      } else if (argv[index][chr+1])
+       opt_failure("Option -%c must have a value, but found inside a bunch of short opts.", o);
       else if (!argv[index+1])
-       opt_failure("Option -%c must have a value but nothing supplied.", opt->item->letter);
+       opt_failure("Option -%c must have a value, but nothing supplied.", o);
       else {
        opt_parse_value(oc, opt, argv[index+1], 0);
        return 1;
       }
-    }
-    else if (opt->flags & OPT_MAYBE_VALUE) {
+    } else if (opt->flags & OPT_MAYBE_VALUE) {
       if (chr == 1 && argv[index][2]) {
         opt_parse_value(oc, opt, argv[index] + 2, 0);
        return 0;
-      }
-      else
+      } else
        opt_parse_value(oc, opt, NULL, 0);
-    }
-    else {
+    } else {
       ASSERT(0);
     }
   }
 
-  if (argv[index][chr])
-    opt_failure("Unknown option -%c.", argv[index][chr]);
-
   return 0;
 }
 
 static void opt_positional(struct opt_context * oc, char * value) {
   oc->positional_count++;
   uns id = oc->positional_count > oc->positional_max ? OPT_POSITIONAL_TAIL : OPT_POSITIONAL(oc->positional_count);
-  struct opt_precomputed * opt = opt_find_item_shortopt(oc, id);
-  if (opt)
-    opt_parse_value(oc, opt, value, 2);
-  else {
-    ASSERT(oc->positional_count > oc->positional_max);
+  struct opt_precomputed * opt = oc->shortopt[id];
+  if (!opt || (opt->flags & OPT_SINGLE) && opt->count)
     opt_failure("Too many positional arguments.");
+  else {
+    opt->count++;
+    opt_parse_value(oc, opt, value, 2);
   }
 }
 
index 1bf7f7d2ff818c796066303857c1d8bb0d85bd39..fc8fa0bd3c5462b1ce2033f448dd7b387044e59f 100644 (file)
--- a/ucw/opt.h
+++ b/ucw/opt.h
@@ -148,7 +148,7 @@ void opt_conf_hook_internal(struct opt_item * opt, const char * value, void * da
 // FIXME: Is numbering from 1 natural here?
 // FIXME: Are there any rules for mixing of positional arguments with options?
 #define OPT_POSITIONAL(n)   (OPT_POSITIONAL_TAIL+(n))
-#define OPT_POSITIONAL_TAIL 256
+#define OPT_POSITIONAL_TAIL 128
 
 
 /***