]> mj.ucw.cz Git - libucw.git/commitdiff
Opt: Improved parsing of negative boolean options
authorMartin Mares <mj@ucw.cz>
Mon, 17 Feb 2014 17:41:33 +0000 (18:41 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 17 Feb 2014 17:41:33 +0000 (18:41 +0100)
Boolean options with the OPT_NEGATIVE flag, which are named "no-X",
are also recognized as bare "X" with positive meaning.

Include tests for processing of both positive and negative bools.

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

index a030eefea944c6d775ff618eae0e369a9e505d74..ffaf0f9ecf8c41bf1677cb32283daaec46d2f443 100644 (file)
@@ -50,6 +50,7 @@ static int with_gas = 0;
 static int *black_magic;
 static int pray = 0;
 static int water_amount = 0;
+static int clean_pot = 1;
 static char * first_tea = NULL;
 
 #define MAX_TEA_COUNT 30
@@ -144,6 +145,7 @@ static struct opt_section options = {
     OPT_INC('q', "quiet", verbose, OPT_NEGATIVE, "\tQuiet (the more -q, the more quiet)"),
     OPT_INT_MULTIPLE('b', NULL, black_magic, 0, "<strength>\tUse black magic to make the tea extraordinarily delicious.\n\t\tMay be specified more than once to describe the amounts of black magic to be invoked in each step of tea boiling."),
     OPT_BOOL('p', "pray", pray, OPT_SINGLE, "\tPray before boiling"),
+    OPT_BOOL(0, "no-clean", clean_pot, OPT_NEGATIVE, "\tDo not clean the teapot before boiling"),
     OPT_STRING(OPT_POSITIONAL(1), NULL, first_tea, OPT_REQUIRED, ""),
     OPT_CALL(OPT_POSITIONAL_TAIL, NULL, add_tea, &tea_list, 0, ""),
     OPT_HELP(""),
@@ -182,6 +184,7 @@ int main(int argc UNUSED, char ** argv)
   for (uns i=0; i<magick; i++)
     printf("Black magic: %d|", black_magic[i]);
   printf("Prayer: %s|", pray ? "yes" : "no");
+  printf("Clean: %s|", clean_pot ? "yes" : "no");
   printf("Water amount: %d|", water_amount);
   printf("Gas: %s|", with_gas ? "yes" : "no");
   printf("First tea: %s|", first_tea);
index d61433d7342d30c2be8ba91ed4ea650c74b16f7c..229a93b7a3168cd275d1b3e25ae43507445b8e6b 100644 (file)
--- a/ucw/opt.c
+++ b/ucw/opt.c
@@ -94,9 +94,22 @@ static struct opt_precomputed * opt_find_item_longopt(struct opt_context * oc, c
     if (!strncmp(opt->name, str, len)) {
       if (strlen(opt->name) == len)
        return opt;
-    } else if (opt->item->cls == OPT_CL_BOOL && !strncmp("no-", str, 3) && !strncmp(opt->name, str+3, len-3)) {
-      if (strlen(opt->name) == len-3)
-       return opt;
+    } else if (opt->item->cls == OPT_CL_BOOL) {
+      if (opt->flags & OPT_NEGATIVE) {
+       // If the option is called no-X, match X as well
+       if (!strncmp("no-", opt->name, 3) && !strncmp(opt->name+3, str, len)) {
+         if (strlen(opt->name) == len+3)
+           return opt;
+       } else
+         continue;
+      } else {
+       // Match no-X as well
+       if (!strncmp("no-", str, 3) && !strncmp(opt->name, str+3, len-3)) {
+         if (strlen(opt->name) == len-3)
+           return opt;
+       } else
+         continue;
+      }
     } else
       continue;
 
@@ -228,7 +241,10 @@ static int opt_longopt(struct opt_context * oc, char ** argv, int index) {
 
   opt->flags |= OPT_SEEN_AS_LONG;
 
-  if (opt->item->cls == OPT_CL_BOOL && !strncmp(name_in, "no-", 3) && !strncmp(name_in+3, opt->item->name, pos-3)) {
+  if (opt->item->cls == OPT_CL_BOOL &&
+      ((opt->flags & OPT_NEGATIVE)
+         ? (!strncmp(opt->item->name, "no-", 3) && !strncmp(name_in, opt->item->name + 3, pos-3))
+         : (!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);
     value = "n";
index 26c9ab371384a8d9c6bf4ef9065a6bf66544e10d..8ac04438f1d2cf3cf800ef9f8fda0d4735ab5607 100644 (file)
--- a/ucw/opt.t
+++ b/ucw/opt.t
@@ -8,15 +8,15 @@ Out:  Required option -t/--temperature not found.
 
 Name:  Opt-2
 Run:   ../obj/ucw/opt-test -t95C -w640 -gG darjeeling
-Out:   English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
+Out:   English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: yes|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
 
 Name:  Opt-3
 Run:   ../obj/ucw/opt-test -vvqvqvhpe -t120F -w4 darjeeling
-Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 3|Prayer: yes|Water amount: 4|Gas: no|First tea: darjeeling|Everything OK. Bye.
+Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 3|Prayer: yes|Clean: yes|Water amount: 4|Gas: no|First tea: darjeeling|Everything OK. Bye.
 
 Name:  Opt-4
 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.
+Out:   English style: no|Temperature: 120F|Verbosity: 1|Prayer: no|Clean: yes|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
@@ -26,11 +26,27 @@ Out:        Multiple switches: -h
 
 Name:  Opt-6
 Run:   ../obj/ucw/opt-test -t120F -w4 -b15 -he -- --puerh darjeeling earl-grey
-Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Prayer: no|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye.
+Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Prayer: no|Clean: yes|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye.
 
 Name:  Opt-7
 Run:   ../obj/ucw/opt-test -t120F -w4 -b15 -b54 -he -- --puerh darjeeling earl-grey
-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.
+Out:   English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Black magic: 54|Prayer: no|Clean: yes|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye.
+
+Name:  Opt-bool-1
+Run:   ../obj/ucw/opt-test -t95C -w640 -gG darjeeling --english-style
+Out:   English style: yes|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: yes|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
+
+Name:  Opt-bool-2
+Run:   ../obj/ucw/opt-test -t95C -w640 -gG darjeeling --english-style --no-english-style
+Out:   English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: yes|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
+
+Name:  Opt-bool-negative-1
+Run:   ../obj/ucw/opt-test -t95C -w640 -gG darjeeling --clean
+Out:   English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: yes|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
+
+Name:  Opt-bool-negative-2
+Run:   ../obj/ucw/opt-test -t95C -w640 -gG darjeeling --no-clean
+Out:   English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: no|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
 
 Name:  Opt-Conf-1
 Run:   ../obj/ucw/opt-test -h -SX.Y=Z 2>&1 1>/dev/null
@@ -40,4 +56,4 @@ Out:  Config options must stand before other options.
 
 Name:  Opt-Hook-1
 Run:   ../obj/ucw/opt-test -Ht 95C -w640 -gG darjeeling
-Out:   [HOOK-postval:H/show-hooks=(null)] [HOOK-preval:t/temperature=95C] [HOOK-postval:t/temperature=95C] [HOOK-prearg] [HOOK-preval:w/water=640] [HOOK-postval:w/water=640] [HOOK-prearg] [HOOK-preval:g/glass-set=(null)] [HOOK-postval:g/glass-set=(null)] [HOOK-preval:G/with-gas=(null)] [HOOK-postval:G/with-gas=(null)] [HOOK-prearg] [HOOK-preval:\81/(null)=darjeeling] [HOOK-postval:\81/(null)=darjeeling] English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.
+Out:   [HOOK-postval:H/show-hooks=(null)] [HOOK-preval:t/temperature=95C] [HOOK-postval:t/temperature=95C] [HOOK-prearg] [HOOK-preval:w/water=640] [HOOK-postval:w/water=640] [HOOK-prearg] [HOOK-preval:g/glass-set=(null)] [HOOK-postval:g/glass-set=(null)] [HOOK-preval:G/with-gas=(null)] [HOOK-postval:G/with-gas=(null)] [HOOK-prearg] [HOOK-preval:\81/(null)=darjeeling] [HOOK-postval:\81/(null)=darjeeling] English style: no|Chosen teapot: glass|Temperature: 95C|Verbosity: 1|Prayer: no|Clean: yes|Water amount: 640|Gas: yes|First tea: darjeeling|Everything OK. Bye.