]> mj.ucw.cz Git - libucw.git/commitdiff
Opt: Simpified and corrected processing of OPT_SINGLE
authorMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 16:13:46 +0000 (17:13 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 16:13:46 +0000 (17:13 +0100)
OPT_SINGLE is now checked in opt_parse_value(). Previously, short,
long, and positional options had their own checks.

OPT_CL_SWITCH did not allow changing the value of the switch once
it is set, although documentation in opt.h claimed quite the opposite.
Changes are currently allowed unless OPT_SINGLE is set.

Test cases have been updated accordingly.

ucw/opt-test.c
ucw/opt.c
ucw/opt.t

index 0d5337df173f283aa438dab76d848131092db590..cd7acc38f5f27009dd537c3cfcebe1debfdc1987 100644 (file)
@@ -128,10 +128,10 @@ static struct opt_section help = {
     OPT_HELP(""),
     OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"),
     OPT_INT('s', "sugar", sugar, OPT_REQUIRED_VALUE, "<spoons>\tAmount of sugar (in teaspoons)"),
-    OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, 0, "\tStandard teapot"),
-    OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, 0, "\tExclusive teapot"),
-    OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, 0, "\tTransparent glass teapot"),
-    OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, 0, "\tUse user's hands as a teapot (a bit dangerous)"),
+    OPT_SWITCH(0, "standard-set", set, TEAPOT_STANDARD, OPT_SINGLE, "\tStandard teapot"),
+    OPT_SWITCH('x', "exclusive-set", set, TEAPOT_EXCLUSIVE, OPT_SINGLE, "\tExclusive teapot"),
+    OPT_SWITCH('g', "glass-set", set, TEAPOT_GLASS, OPT_SINGLE, "\tTransparent glass teapot"),
+    OPT_SWITCH('h', "hands", set, TEAPOT_HANDS, OPT_SINGLE, "\tUse user's hands as a teapot (a bit dangerous)"),
     OPT_USER('t', "temperature", temperature, teapot_temperature_t, OPT_REQUIRED_VALUE | OPT_REQUIRED,
                  "<value>\tWanted final temperature of the tea to be served (required)\n"
              "\t\tSupported scales:  Celsius [60C], Fahrenheit [140F],\n"
index 4cddc6214c890ca06388030e7b5281d21e39be00..5ba7954d15ed269d3f67b84a5611e5421b33b1a7 100644 (file)
--- a/ucw/opt.c
+++ b/ucw/opt.c
@@ -255,6 +255,9 @@ static struct opt_precomputed * opt_find_item_longopt(struct opt_context * oc, c
 static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * opt, char * value) {
   struct opt_item * item = opt->item;
 
+  if (opt->count++ && (opt->flags & OPT_SINGLE))
+    opt_failure("Option %s must be specified at most once.", THIS_OPT);
+
   for (int i = 0; i < oc->hooks_before_value_count; i++)
     oc->hooks_before_value[i]->u.call(item, value, oc->hooks_before_value[i]->ptr);
 
@@ -315,8 +318,7 @@ static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * op
        break;
       }
     case OPT_CL_SWITCH:
-      // FIXME: Really? And who sets the default to -1?
-      if (*((int *)item->ptr) != -1)
+      if ((opt->flags & OPT_SINGLE) && *((int *)item->ptr) != -1)
        opt_failure("Multiple switches: %s", THIS_OPT);
       else
        *((int *)item->ptr) = item->u.value;
@@ -355,10 +357,6 @@ static int opt_longopt(struct opt_context * oc, char ** argv, int index) {
 
   opt->flags |= OPT_SEEN_AS_LONG;
 
-  // FIXME: Move to opt_parse_value()?
-  if (opt->count++ && (opt->flags & OPT_SINGLE))
-    opt_failure("Option %s must be specified at most once.", THIS_OPT);
-
   if (opt->item->cls == OPT_CL_BOOL && !strncmp(name_in, "no-", 3) && !strncmp(name_in+3, opt->item->name, pos-3)) {
     if (name_in[pos])
       opt_failure("Option --%s must not have any value.", name_in);
@@ -398,10 +396,6 @@ static int opt_shortopt(struct opt_context * oc, char ** argv, int index) {
 
     opt->flags &= ~OPT_SEEN_AS_LONG;
 
-    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);
     else if (opt->flags & OPT_REQUIRED_VALUE) {
@@ -432,11 +426,10 @@ 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 = oc->shortopt[id];
-  if (!opt || (opt->flags & OPT_SINGLE) && opt->count)
+  if (!opt)
     opt_failure("Too many positional arguments.");
   else {
     opt->flags &= OPT_SEEN_AS_LONG;
-    opt->count++;
     opt_parse_value(oc, opt, value);
   }
 }
index d7fac7ecad47d15e326e799c3eeb68d37874adcc..aeafd199ac8baedd3bec86d91be659f1b5805a99 100644 (file)
--- a/ucw/opt.t
+++ b/ucw/opt.t
@@ -19,7 +19,8 @@ Run:  ../obj/ucw/opt-test -t120F -w4 puerh darjeeling earl-grey
 Out:   English style: no|Temperature: 120F|Verbosity: 1|Prayer: no|Water amount: 4|Gas: no|First tea: puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye.
 
 Name:  Opt-5
-Run:   ../obj/ucw/opt-test -ghx 2>&1 1>/dev/null || [ $? -eq "2" ]
+Run:   ../obj/ucw/opt-test -ghx 2>&1 1>/dev/null
+Exit:  2
 Out:   Multiple switches: -h
        Run with argument --help for more information.
 
@@ -32,7 +33,8 @@ Run:  ../obj/ucw/opt-test -t120F -w4 -b15 -b54 -he -- --puerh darjeeling earl-gre
 Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Black magic: 54|Prayer: no|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye.
 
 Name:  Opt-Conf-1
-Run:   ../obj/ucw/opt-test -h --dumpconfig 2>&1 1>/dev/null || [ $? -eq "2" ]
+Run:   ../obj/ucw/opt-test -h --dumpconfig 2>&1 1>/dev/null
+Exit:  2
 Out:   Config options (-C, -S) must stand before other options.
        Run with argument --help for more information.