2004-02-26 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 26 Feb 2004 18:22:02 +0000 (18:22 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 26 Feb 2004 18:22:02 +0000 (18:22 +0000)
* README.gpgconf: Fix description of arguments.
* gpgconf-comp.c (option_check_validity): Rewritten to properly
support optional arguments in lists.

tools/ChangeLog
tools/README.gpgconf
tools/gpgconf-comp.c

index 69af2eb..154ec55 100644 (file)
@@ -1,6 +1,10 @@
 2004-02-26  Marcus Brinkmann  <marcus@g10code.de>
 
-       * README.gpgconf (NAME): Add info about optional arg and arg type 0.
+       * README.gpgconf: Fix description of arguments.
+       * gpgconf-comp.c (option_check_validity): Rewritten to properly
+       support optional arguments in lists.
+       
+       * README.gpgconf: Add info about optional arg and arg type 0.
        * gpgconf-comp.c (gc_component_change_options): Parse list of
        arg type 0 options.
        (option_check_validity): Add new argument NEW_VALUE_NR.  Perform
index 2f6a2e0..0973939 100644 (file)
@@ -80,17 +80,17 @@ Some fields contain an option argument.  The format of an option
 argument depends on the type of the option and on some flags:
 
 The simplest case is that the option does not take an argument at all
-(TYPE is 0).  Then the option argument is either empty if the option
-is not set, or an unsigned number that specifies how often the option
-occurs.  If the LIST flag is not set, then the only valid number is 1.
-Options that don't take an argument never have the "default" flag set.
+(TYPE is 0).  Then the option argument is an unsigned number that
+specifies how often the option occurs.  If the LIST flag is not set,
+then the only valid number is 1.  Options that don't take an argument
+never have the "default" or "optional arg" flag set.
 
 If the option takes a number argument (ALT-TYPE is 2 or 3), and it can
 only occur once (LIST flag is not set), then the option argument is
-either empty if the option is not set, or it is a number.  A number is
-a string that begins with an optional minus character, followed by one
-or more digits.  The number must fit into an integer variable
-(unsigned or signed, depending on ALT-TYPE).
+either empty (only allowed if the argument is optional), or it is a
+number.  A number is a string that begins with an optional minus
+character, followed by one or more digits.  The number must fit into
+an integer variable (unsigned or signed, depending on ALT-TYPE).
 
 If the option takes a number argument and it can occur more than once,
 then the option argument is either empty, or it is a comma-separated
@@ -98,19 +98,16 @@ list of numbers as described above.
 
 If the option takes a string argument (ALT-TYPE is 1), and it can only
 occur once (LIST flag is not set) then the option argument is either
-empty if the option is not set, or it starts with a double quote
-character (") followed by a percent-escaped string that is the
-argument value.  Note that there is only a leading double quote
+empty (only allowed if the argument is optional), or it starts with a
+double quote character (") followed by a percent-escaped string that
+is the argument value.  Note that there is only a leading double quote
 character, no trailing one.  The double quote character is only needed
 to be able to differentiate between no value and the empty string as
 value.
 
-If the option takes a string argument and it can occur more than once,
-then the option argument is either empty or it starts with a double
-quote character (") followed by a comma-separated list of
-percent-escaped strings.  Obviously any commas in the individual
-strings must be percent-escaped.
-
+If the option takes a number argument and it can occur more than once,
+then the option argument is either empty, or it is a comma-separated
+list of string arguments as described above.
 
 FIXME: Document the active language and active character set.  Allow
 to change it via the command line?
index dc8de90..524f217 100644 (file)
@@ -1223,6 +1223,8 @@ static void
 option_check_validity (gc_option_t *option, unsigned long flags,
                       char *new_value, unsigned long *new_value_nr)
 {
+  char *arg;
+
   if (option->new_flags || option->new_value)
     gc_error (1, 0, "option %s already changed", option->name);
 
@@ -1231,101 +1233,89 @@ option_check_validity (gc_option_t *option, unsigned long flags,
       if (*new_value)
        gc_error (1, 0, "argument %s provided for deleted option %s",
                  new_value, option->name);
+
+      return;
     }
-  else
+
+  /* GC_ARG_TYPE_NONE options have special list treatment.  */
+  if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
     {
-      /* This is even correct for GC_ARG_TYPE_NONE options, for which
-        GC_OPT_FLAG_ARG_OPT is never set.  */
-      if (!(option->flags & GC_OPT_FLAG_ARG_OPT) && (*new_value == '\0'))
-       gc_error (1, 0, "no argument for option %s", option->name);
+      char *tail;
 
-      if (*new_value)
+      errno = 0;
+      *new_value_nr = strtoul (new_value, &tail, 0);
+
+      if (errno)
+       gc_error (1, errno, "invalid argument for option %s",
+                 option->name);
+      if (*tail)
+       gc_error (1, 0, "garbage after argument for option %s",
+                     option->name);
+
+      if (!(option->flags & GC_OPT_FLAG_LIST))
        {
-         if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
-           {
-             char *tail;
+         if (*new_value_nr != 1)
+           gc_error (1, 0, "argument for non-list option %s of type 0 "
+                     "(none) must be 1", option->name);
+       }
+      else
+       {
+         if (*new_value_nr == 0)
+           gc_error (1, 0, "argument for option %s of type 0 (none) "
+                     "must be positive", option->name);
+       }
 
-             errno = 0;
-             *new_value_nr = strtoul (new_value, &tail, 0);
+      return;
+    }
 
-             if (errno)
-               gc_error (1, errno, "invalid argument for option %s",
-                         option->name);
-             if (*tail)
-               gc_error (1, 0, "garbage after argument for option %s",
-                         option->name);
+  arg = new_value;
+  do
+    {
+      if (*arg == '\0' || *arg == ',')
+       {
+         if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
+           gc_error (1, 0, "argument required for option %s", option->name);
 
-             if (!(option->flags & GC_OPT_FLAG_LIST))
-               {
-                 if (*new_value_nr != 1)
-                   gc_error (1, 0, "argument for non-list option %s of type 0 "
-                             "(none) must be 1", option->name);
-               }
-             else
-               {
-                 if (*new_value_nr == 0)
-                   gc_error (1, 0, "argument for option %s of type 0 (none) "
-                             "must be positive", option->name);
-               }
-           }
-         else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
-           {
-             if (*new_value != '"')
-               gc_error (1, 0, "string argument for option %s must begin "
-                         "with a quote (\") character", option->name);
-           }
-         else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
-           {
-             char *tail = new_value;
+         if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
+           gc_error (1, 0, "list found for non-list option %s", option->name);
+       }
+      else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
+       {
+         if (*arg != '"')
+           gc_error (1, 0, "string argument for option %s must begin "
+                     "with a quote (\") character", option->name);
+       }
+      else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
+       {
+         errno = 0;
+         (void) strtol (arg, &arg, 0);
 
-             while (*tail)
-               {
-                 errno = 0;
-                 (void) strtol (new_value, &tail, 0);
+         if (errno)
+           gc_error (1, errno, "invalid argument for option %s",
+                     option->name);
 
-                 if (errno)
-                   gc_error (1, errno, "invalid argument for option %s",
-                             option->name);
-                 if (*tail == ',')
-                   {
-                     if (!(option->flags & GC_OPT_FLAG_LIST))
-                       gc_error (1, 0, "list found for non-list option %s",
-                                 option->name);
-                     tail++;
-                   }
-                 else if (*tail)
-                   gc_error (1, 0, "garbage after argument for option %s",
-                             option->name);
-               }
-           }
-         else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32)
-           {
-             char *tail = new_value;
+         if (*arg != '\0' && *arg != ',')
+           gc_error (1, 0, "garbage after argument for option %s",
+                     option->name);
+       }
+      else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
+       {
+         errno = 0;
+         (void) strtoul (arg, &arg, 0);
 
-             while (*tail)
-               {
-                 errno = 0;
-                 (void) strtoul (new_value, &tail, 0);
+         if (errno)
+           gc_error (1, errno, "invalid argument for option %s",
+                     option->name);
 
-                 if (errno)
-                   gc_error (1, errno, "invalid argument for option %s",
-                             option->name);
-                 if (*tail == ',')
-                   {
-                     if (!(option->flags & GC_OPT_FLAG_LIST))
-                       gc_error (1, 0, "list found for non-list option %s",
-                                 option->name);
-                     tail++;
-                   }
-                 else if (*tail)
-                   gc_error (1, 0, "garbage after argument for option %s",
-                             option->name);
-               }
-           }
-         else
-           assert (!"Unexpected argument type");
+         if (*arg != '\0' && *arg != ',')
+           gc_error (1, 0, "garbage after argument for option %s",
+                     option->name);
        }
+      arg = strchr (arg, ',');
+      if (arg)
+       arg++;
     }
+  while (arg && *arg);
 }
 
 
@@ -1377,6 +1367,7 @@ change_options_program (gc_component_t component, gc_backend_t backend,
       xfree (orig_filename);
       orig_filename = NULL;
     }
+
   /* We now initialize the return strings, so the caller can do the
      cleanup for us.  */
   *src_filenamep = src_filename;