]> sjero.net Git - wget/commitdiff
[svn] Improved command line option processing, introduced boolean options.
authorhniksic <devnull@localhost>
Thu, 6 Nov 2003 20:20:43 +0000 (12:20 -0800)
committerhniksic <devnull@localhost>
Thu, 6 Nov 2003 20:20:43 +0000 (12:20 -0800)
src/ChangeLog
src/init.c
src/main.c

index c79bc8bcf01b41a90f071dbc440858f7960384c7..9942941ee469f2093f975fb71b19c1efc3d16042 100644 (file)
@@ -1,3 +1,9 @@
+2003-11-06  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * main.c (init_switches): New function.  Convert option_data to
+       long_options and short_options, which can be fed to getopt_long.
+       (main): Execute command-line options by consulting option_data.
+
 2003-11-06  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * gen_sslfunc.c (ssl_read): Implement a more correct check for
index a92b5e114d2fba846b0d5d955d4a0990a4fa9645..c0f260ed4c5c7aba282b589336c607b261819128 100644 (file)
@@ -559,6 +559,7 @@ static int
 setval_internal (int comind, const char *com, const char *val)
 {
   assert (0 <= comind && comind < countof (commands));
+  DEBUGP (("Setting %s (%d) to %s\n", com, comind, val));
   return ((*commands[comind].action) (com, val, commands[comind].closure));
 }
 
@@ -575,6 +576,7 @@ setval_internal (int comind, const char *com, const char *val)
 void
 setoptval (const char *com, const char *val)
 {
+  assert (val != NULL);
   if (!setval_internal (command_by_name (com), com, val))
     exit (2);
 }
index 0f93690b76fff701a38167bd8872918ebe11006c..922d605b2f5c28918b3fa5871ece6620f32f37d3 100644 (file)
@@ -49,6 +49,8 @@ so, delete this exception statement from your version.  */
 # include <locale.h>
 #endif /* HAVE_LOCALE_H */
 #endif /* HAVE_NLS */
+#include <assert.h>
+
 #include <errno.h>
 #ifndef errno
 extern int errno;
@@ -116,6 +118,233 @@ i18n_initialize (void)
 #endif /* HAVE_NLS */
 }
 \f
+/* Definition of command-line options. */
+
+#ifdef HAVE_SSL
+# define IF_SSL(x) x
+#else
+# define IF_SSL(x) NULL
+#endif
+
+#ifdef ENABLE_DEBUG
+# define IF_DEBUG(x) x
+#else
+# define IF_DEBUG(x) NULL
+#endif
+
+struct cmdline_option {
+  const char *long_name;
+  char short_name;
+  enum {
+    OPT_VALUE,
+    OPT_BOOLEAN,
+    /* Non-standard options that have to be handled specially in
+       main().  */
+    OPT__APPEND_OUTPUT,
+    OPT__CLOBBER,
+    OPT__EXECUTE,
+    OPT__HELP,
+    OPT__NO,
+    OPT__PARENT,
+    OPT__VERSION
+  } type;
+  const char *handle_cmd;      /* for standard options */
+  int argtype;                 /* for non-standard options */
+};
+
+struct cmdline_option option_data[] =
+  {
+    { "accept", 'A', OPT_VALUE, "accept", -1 },
+    { "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
+    { "background", 'b', OPT_BOOLEAN, "background", -1 },
+    { "backup-converted", 'K', OPT_BOOLEAN, "backupconverted", -1 },
+    { "backups", 0, OPT_BOOLEAN, "backups", -1 },
+    { "base", 'B', OPT_VALUE, "base", -1 },
+    { "bind-address", 0, OPT_VALUE, "bindaddress", -1 },
+    { "cache", 'C', OPT_BOOLEAN, "cache", -1 },
+    { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
+    { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
+    { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
+    { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
+    { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
+    { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
+    { IF_DEBUG ("debug"), 'd', OPT_BOOLEAN, "debug", -1 },
+    { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
+    { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
+    { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
+    { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
+    { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
+    { "domains", 'D', OPT_VALUE, "domains", -1 },
+    { "dot-style", 0, OPT_VALUE, "dotstyle", -1 },
+    { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
+    { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
+    { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
+    { "execute", 'e', OPT__EXECUTE, NULL, required_argument },
+    { "follow-ftp", 0, OPT_BOOLEAN, "followftp", -1 },
+    { "follow-tags", 0, OPT_VALUE, "followtags", -1 },
+    { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
+    { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
+    { "glob", 'g', OPT_BOOLEAN, "glob", -1 },
+    { "header", 0, OPT_VALUE, "header", -1 },
+    { "help", 'h', OPT__HELP, NULL, no_argument },
+    { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
+    { "html-extension", 'E', OPT_BOOLEAN, "htmlextension", -1 },
+    { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
+    { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
+    { "http-passwd", 0, OPT_VALUE, "httppasswd", -1 },
+    { "http-user", 0, OPT_VALUE, "httpuser", -1 },
+    { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
+    { "ignore-tags", 'G', OPT_VALUE, "ignoretags", -1 },
+    { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
+    { "input-file", 'i', OPT_VALUE, "input", -1 },
+    { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
+    { "level", 'l', OPT_VALUE, "reclevel", -1 },
+    { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
+    { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
+    { "mirror", 'm', OPT_BOOLEAN, NULL, -1 },
+    { "no", 'n', OPT__NO, NULL, required_argument },
+    { "no-clobber", 0, OPT_BOOLEAN, "noclobber", -1 },
+    { "no-parent", 0, OPT_BOOLEAN, "noparent", -1 },
+    { "output-document", 'O', OPT_VALUE, "outputdocument", -1 },
+    { "output-file", 'o', OPT_VALUE, "logfile", -1 },
+    { "page-requisites", 'p', OPT_BOOLEAN, "pagerequisites", -1 },
+    { "parent", 0, OPT__PARENT, NULL, optional_argument },
+    { "passive-ftp", 0, OPT_BOOLEAN, "passiveftp", -1 },
+    { "post-data", 0, OPT_VALUE, "postdata", -1 },
+    { "post-file", 0, OPT_VALUE, "postfile", -1 },
+    { "progress", 0, OPT_VALUE, "progress", -1 },
+    { "proxy", 'Y', OPT_BOOLEAN, "useproxy", -1 },
+    { "proxy-passwd", 0, OPT_VALUE, "proxypasswd", -1 },
+    { "proxy-user", 0, OPT_VALUE, "proxyuser", -1 },
+    { "quiet", 'q', OPT_BOOLEAN, "quiet", -1 },
+    { "quota", 'Q', OPT_VALUE, "quota", -1 },
+    { "random-wait", 0, OPT_BOOLEAN, "randomwait", -1 },
+    { "read-timeout", 0, OPT_VALUE, "readtimeout", -1 },
+    { "recursive", 'r', OPT_BOOLEAN, "recursive", -1 },
+    { "referer", 0, OPT_VALUE, "referer", -1 },
+    { "reject", 'R', OPT_VALUE, "reject", -1 },
+    { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
+    { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
+    { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
+    { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
+    { "retry-connrefused", 0, OPT_BOOLEAN, "retryconnrefused", -1 },
+    { "save-cookies", 0, OPT_VALUE, "savecookies", -1 },
+    { "save-headers", 0, OPT_BOOLEAN, "saveheaders", -1 },
+    { "server-response", 'S', OPT_BOOLEAN, "serverresponse", -1 },
+    { "span-hosts", 'H', OPT_BOOLEAN, "spanhosts", -1 },
+    { "spider", 0, OPT_BOOLEAN, "spider", -1 },
+    { IF_SSL ("sslcadir"), 0, OPT_VALUE, "sslcadir", -1 },
+    { IF_SSL ("sslcafile"), 0, OPT_VALUE, "sslcafile", -1 },
+    { IF_SSL ("sslcertfile"), 0, OPT_VALUE, "sslcertfile", -1 },
+    { IF_SSL ("sslcertkey"), 0, OPT_VALUE, "sslcertkey", -1 },
+    { IF_SSL ("sslcerttype"), 0, OPT_VALUE, "sslcerttype", -1 },
+    { IF_SSL ("sslcheckcert"), 0, OPT_VALUE, "sslcheckcert", -1 },
+    { IF_SSL ("sslprotocol"), 0, OPT_VALUE, "sslprotocol", -1 },
+    { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
+    { "timeout", 'T', OPT_VALUE, "timeout", -1 },
+    { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
+    { "tries", 't', OPT_VALUE, "tries", -1 },
+    { "use-proxy", 'Y', OPT_BOOLEAN, "useproxy", -1 },
+    { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
+    { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
+    { "verbose", 0, OPT_BOOLEAN, "verbose", -1 },
+    { "version", 'V', OPT__VERSION, "version", no_argument },
+    { "wait", 'w', OPT_VALUE, "wait", -1 },
+    { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
+  };
+
+#undef IF_DEBUG
+#undef IF_SSL
+
+static char *
+no_prefix (const char *s)
+{
+  static char buffer[1024];
+  static char *p = buffer;
+
+  char *cp = p;
+  int size = 3 + strlen (s) + 1;  /* "no-STRING\0" */
+
+  if (p + size >= buffer + sizeof (buffer))
+    abort ();
+
+  cp[0] = 'n';
+  cp[1] = 'o';
+  cp[2] = '-';
+  strcpy (cp + 3, s);
+  p += size;
+  return cp;
+}
+
+/* The arguments that that main passes to getopt_long. */
+static struct option long_options[2 * countof (option_data) + 1];
+static char short_options[128];
+
+/* Mapping between short option chars and option_data indices. */
+static unsigned char optmap[96];
+
+/* Marker for `--no-FOO' values in long_options.  */
+#define BOOLEAN_NEG_MARKER 1024
+
+static void
+init_switches (void)
+{
+  char *p = short_options;
+  int i, o = 0;
+  for (i = 0; i < countof (option_data); i++)
+    {
+      struct cmdline_option *opt = &option_data[i];
+      struct option *longopt;
+
+      if (!opt->long_name)
+       /* The option is disabled. */
+       continue;
+
+      longopt = &long_options[o++];
+      longopt->name = opt->long_name;
+      longopt->val = i;
+      if (opt->short_name)
+       {
+         *p++ = opt->short_name;
+         optmap[opt->short_name - 32] = longopt - long_options;
+       }
+      switch (opt->type)
+       {
+       case OPT_VALUE:
+         longopt->has_arg = required_argument;
+          if (opt->short_name)
+           *p++ = ':';
+         break;
+       case OPT_BOOLEAN:
+         /* Don't specify optional arguments for boolean short
+            options.  They are evil because they prevent combining of
+            short options.  */
+         longopt->has_arg = optional_argument;
+         /* For Boolean options, add the "--no-FOO" variant, which is
+            identical to "--foo", except it has opposite meaning and
+            it doesn't allow an argument.  */
+         longopt = &long_options[o++];
+         longopt->name = no_prefix (opt->long_name);
+         longopt->has_arg = no_argument;
+         /* Mask the value so we'll be able to recognize that we're
+            dealing with the false value.  */
+         longopt->val = i | BOOLEAN_NEG_MARKER;
+         break;
+       default:
+         assert (opt->argtype != -1);
+         longopt->has_arg = opt->argtype;
+         if (opt->short_name)
+           {
+             if (longopt->has_arg == required_argument)
+               *p++ = ':';
+             /* Don't handle optional_argument */
+           }
+       }
+    }
+  xzero (long_options[o]);
+  *p = '\0';
+}
+
 /* Print the usage message.  */
 static void
 print_usage (void)
@@ -265,119 +494,12 @@ int
 main (int argc, char *const *argv)
 {
   char **url, **t;
-  int i, c, nurl, status, append_to_log;
-
-  static struct option long_options[] =
-  {
-    /* Options without arguments: */
-    { "background", no_argument, NULL, 'b' },
-    { "backup-converted", no_argument, NULL, 'K' },
-    { "continue", no_argument, NULL, 'c' },
-    { "convert-links", no_argument, NULL, 'k' },
-    { "debug", no_argument, NULL, 'd' },
-    { "delete-after", no_argument, NULL, 136 },
-    { "dont-remove-listing", no_argument, NULL, 149 },
-    { "follow-ftp", no_argument, NULL, 142 },
-    { "force-directories", no_argument, NULL, 'x' },
-    { "force-hier", no_argument, NULL, 'x' }, /* obsolete */
-    { "force-html", no_argument, NULL, 'F'},
-    { "help", no_argument, NULL, 'h' },
-    { "html-extension", no_argument, NULL, 'E' },
-    { "ignore-length", no_argument, NULL, 138 },
-    { "keep-session-cookies", no_argument, NULL, 181 },
-    { "mirror", no_argument, NULL, 'm' },
-    { "no-clobber", no_argument, NULL, 141 },
-    { "no-directories", no_argument, NULL, 147 },
-    { "no-host-directories", no_argument, NULL, 148 },
-    { "no-host-lookup", no_argument, NULL, 150 },
-    { "no-http-keep-alive", no_argument, NULL, 156 },
-    { "no-parent", no_argument, NULL, 133 },
-    { "non-verbose", no_argument, NULL, 146 },
-    { "passive-ftp", no_argument, NULL, 139 },
-    { "page-requisites", no_argument, NULL, 'p' },
-    { "quiet", no_argument, NULL, 'q' },
-    { "random-wait", no_argument, NULL, 165 },
-    { "recursive", no_argument, NULL, 'r' },
-    { "relative", no_argument, NULL, 'L' },
-    { "retr-symlinks", no_argument, NULL, 137 },
-    { "retry-connrefused", no_argument, NULL, 174 },
-    { "save-headers", no_argument, NULL, 's' },
-    { "server-response", no_argument, NULL, 'S' },
-    { "span-hosts", no_argument, NULL, 'H' },
-    { "spider", no_argument, NULL, 132 },
-    { "strict-comments", no_argument, NULL, 177 },
-    { "timestamping", no_argument, NULL, 'N' },
-    { "verbose", no_argument, NULL, 'v' },
-    { "version", no_argument, NULL, 'V' },
-
-    /* Options accepting an argument: */
-    { "accept", required_argument, NULL, 'A' },
-    { "append-output", required_argument, NULL, 'a' },
-    { "backups", required_argument, NULL, 151 }, /* undocumented */
-    { "base", required_argument, NULL, 'B' },
-    { "bind-address", required_argument, NULL, 155 },
-    { "cache", required_argument, NULL, 'C' },
-    { "connect-timeout", required_argument, NULL, 180 },
-    { "cookies", required_argument, NULL, 160 },
-    { "cut-dirs", required_argument, NULL, 145 },
-    { "dns-timeout", required_argument, NULL, 178 },
-    { "directory-prefix", required_argument, NULL, 'P' },
-    { "dns-cache", required_argument, NULL, 175 },
-    { "domains", required_argument, NULL, 'D' },
-    { "dot-style", required_argument, NULL, 134 },
-    { "execute", required_argument, NULL, 'e' },
-    { "exclude-directories", required_argument, NULL, 'X' },
-    { "exclude-domains", required_argument, NULL, 140 },
-    { "follow-tags", required_argument, NULL, 153 },
-    { "glob", required_argument, NULL, 'g' },
-    { "header", required_argument, NULL, 131 },
-    { "htmlify", required_argument, NULL, 135 },
-    { "http-passwd", required_argument, NULL, 130 },
-    { "http-user", required_argument, NULL, 129 },
-    { "ignore-tags", required_argument, NULL, 'G' },
-    { "include-directories", required_argument, NULL, 'I' },
-    { "input-file", required_argument, NULL, 'i' },
-    { "level", required_argument, NULL, 'l' },
-    { "limit-rate", required_argument, NULL, 164 },
-    { "load-cookies", required_argument, NULL, 161 },
-    { "no", required_argument, NULL, 'n' },
-    { "output-document", required_argument, NULL, 'O' },
-    { "output-file", required_argument, NULL, 'o' },
-    { "post-data", required_argument, NULL, 167 },
-    { "post-file", required_argument, NULL, 168 },
-    { "progress", required_argument, NULL, 163 },
-    { "proxy", required_argument, NULL, 'Y' },
-    { "proxy-passwd", required_argument, NULL, 144 },
-    { "proxy-user", required_argument, NULL, 143 },
-    { "quota", required_argument, NULL, 'Q' },
-    { "read-timeout", required_argument, NULL, 179 },
-    { "reject", required_argument, NULL, 'R' },
-    { "restrict-file-names", required_argument, NULL, 176 },
-    { "save-cookies", required_argument, NULL, 162 },
-    { "timeout", required_argument, NULL, 'T' },
-    { "tries", required_argument, NULL, 't' },
-    { "user-agent", required_argument, NULL, 'U' },
-    { "referer", required_argument, NULL, 157 },
-    { "use-proxy", required_argument, NULL, 'Y' },
-#ifdef HAVE_SSL
-    { "sslcertfile", required_argument, NULL, 158 },
-    { "sslcertkey", required_argument, NULL, 159 },
-    { "egd-file", required_argument, NULL, 166 },
-    { "sslcadir",         required_argument, NULL, 169},
-    { "sslcafile",        required_argument, NULL, 170},
-    { "sslcerttype",      required_argument, NULL, 171},
-    { "sslcheckcert",     required_argument, NULL, 172},
-    { "sslprotocol",      required_argument, NULL, 173},
-#endif /* HAVE_SSL */
-    { "wait", required_argument, NULL, 'w' },
-    { "waitretry", required_argument, NULL, 152 },
-    { 0, 0, 0, 0 }
-  };
+  int i, ret, longindex;
+  int nurl, status;
+  int append_to_log = 0;
 
   i18n_initialize ();
 
-  append_to_log = 0;
-
   /* Construct the name of the executable, without the directory part.  */
   exec_name = strrchr (argv[0], PATH_SEPARATOR);
   if (!exec_name)
@@ -389,316 +511,87 @@ main (int argc, char *const *argv)
   windows_main_junk (&argc, (char **) argv, (char **) &exec_name);
 #endif
 
-  initialize (); /* sets option defaults; reads the system wgetrc and .wgetrc */
+  /* Set option defaults; read the system wgetrc and ~/.wgetrc.  */
+  initialize ();
 
-  /* [Is the order of the option letters significant?  If not, they should be
-      alphabetized, like the long_options.  The only thing I know for sure is
-      that the options with required arguments must be followed by a ':'.
-      -- Dan Harkless <wget@harkless.org>] */
-  while ((c = getopt_long (argc, argv, "\
-hpVqvdkKsxmNWrHSLcFbEY:G:g:T:U:O:l:n:i:o:a:t:D:A:R:P:B:e:Q:X:I:w:C:",
-                          long_options, (int *)0)) != EOF)
+  init_switches ();
+  longindex = -1;
+  while ((ret = getopt_long (argc, argv,
+                            short_options, long_options, &longindex)) != -1)
     {
-      switch (c)
+      int val;
+      struct cmdline_option *opt;
+      if (ret == '?')
        {
-         /* Options without arguments: */
-       case 132:
-         setoptval ("spider", "on");
-         break;
-       case 133:
-         setoptval ("noparent", "on");
-         break;
-       case 136:
-         setoptval ("deleteafter", "on");
-         break;
-       case 137:
-         setoptval ("retrsymlinks", "on");
-         break;
-       case 138:
-         setoptval ("ignorelength", "on");
-         break;
-       case 139:
-         setoptval ("passiveftp", "on");
-         break;
-       case 141:
-         setoptval ("noclobber", "on");
-         break;
-       case 142:
-         setoptval ("followftp", "on");
-         break;
-       case 145:
-         setoptval ("cutdirs", optarg);
-         break;
-       case 146:
-         setoptval ("verbose", "off");
-         break;
-       case 147:
-         setoptval ("dirstruct", "off");
-         break;
-       case 148:
-         setoptval ("addhostdir", "off");
-         break;
-       case 149:
-         setoptval ("removelisting", "off");
-         break;
-       case 155:
-         setoptval ("bindaddress", optarg);
-         break;
-       case 156:
-         setoptval ("httpkeepalive", "off");
-         break;
-       case 165:
-         setoptval ("randomwait", "on");
-         break;
-       case 'b':
-         setoptval ("background", "on");
-         break;
-       case 'c':
-         setoptval ("continue", "on");
-         break;
-       case 'd':
-#ifdef ENABLE_DEBUG
-         setoptval ("debug", "on");
-#else
-         fprintf (stderr, _("%s: debug support not compiled in.\n"),
-                  exec_name);
-#endif
-         break;
-       case 'E':
-         setoptval ("htmlextension", "on");
-         break;
-       case 'F':
-         setoptval ("forcehtml", "on");
+         print_usage ();
+         printf ("\n");
+         printf (_("Try `%s --help' for more options.\n"), exec_name);
+         exit (2);
+       }
+
+      /* If LONGINDEX is unchanged, it means RET is referring a short
+        option.  Look it up in the mapping table.  */
+      if (longindex == -1)
+       longindex = optmap[ret - 32];
+      val = long_options[longindex].val;
+
+      /* Use the retrieved value to locate the option in the
+        option_data array, and to see if we're dealing with the
+        negated "--no-FOO" variant of the boolean option "--foo".  */
+      opt = &option_data[val & ~BOOLEAN_NEG_MARKER];
+      switch (opt->type)
+       {
+       case OPT_VALUE:
+         setoptval (opt->handle_cmd, optarg);
+         break;
+       case OPT_BOOLEAN:
+         if (optarg)
+           /* The user has specified a value -- use it. */
+           setoptval (opt->handle_cmd, optarg);
+         else
+           {
+             /* NEG is true for `--no-FOO' style boolean options. */
+             int neg = val & BOOLEAN_NEG_MARKER;
+             setoptval (opt->handle_cmd, neg ? "0" : "1");
+           }
          break;
-       case 'H':
-         setoptval ("spanhosts", "on");
+       case OPT__APPEND_OUTPUT:
+         setoptval ("logfile", optarg);
+         append_to_log = 1;
          break;
-       case 'h':
+       case OPT__HELP:
          print_help ();
 #ifdef WINDOWS
          ws_help (exec_name);
 #endif
          exit (0);
          break;
-       case 'K':
-         setoptval ("backupconverted", "on");
-         break;
-       case 'k':
-         setoptval ("convertlinks", "on");
-         break;
-       case 'L':
-         setoptval ("relativeonly", "on");
-         break;
-       case 'm':
-         setoptval ("mirror", "on");
-         break;
-       case 'N':
-         setoptval ("timestamping", "on");
-         break;
-       case 'p':
-         setoptval ("pagerequisites", "on");
-         break;
-       case 'S':
-         setoptval ("serverresponse", "on");
-         break;
-       case 's':
-         setoptval ("saveheaders", "on");
-         break;
-       case 'q':
-         setoptval ("quiet", "on");
-         break;
-       case 'r':
-         setoptval ("recursive", "on");
-         break;
-       case 'V':
-         printf ("GNU Wget %s\n\n", version_string);
-         printf ("%s", _("\
-Copyright (C) 2003 Free Software Foundation, Inc.\n"));
-         printf ("%s", _("\
-This program is distributed in the hope that it will be useful,\n\
-but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
-GNU General Public License for more details.\n"));
-         printf (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"));
-         exit (0);
-         break;
-       case 'v':
-         setoptval ("verbose", "on");
-         break;
-       case 'x':
-         setoptval ("dirstruct", "on");
-         break;
-       case 174:
-         setoptval ("retryconnrefused", "on");
-         break;
-       case 177:
-         setoptval ("strictcomments", "on");
-         break;
-       case 181:
-         setoptval ("keepsessioncookies", "on");
-         break;
-
-         /* Options accepting an argument: */
-       case 129:
-         setoptval ("httpuser", optarg);
-         break;
-       case 130:
-         setoptval ("httppasswd", optarg);
-         break;
-       case 131:
-         setoptval ("header", optarg);
-         break;
-       case 134:
-         setoptval ("dotstyle", optarg);
-         break;
-       case 135:
-         setoptval ("htmlify", optarg);
-         break;
-       case 140:
-         setoptval ("excludedomains", optarg);
-         break;
-       case 143:
-         setoptval ("proxyuser", optarg);
-         break;
-       case 144:
-         setoptval ("proxypasswd", optarg);
-         break;
-       case 151:
-         setoptval ("backups", optarg);
-         break;
-       case 152:
-         setoptval ("waitretry", optarg);
-         break;
-       case 153:
-         setoptval ("followtags", optarg);
-         break;
-       case 160:
-         setoptval ("cookies", optarg);
-         break;
-       case 161:
-         setoptval ("loadcookies", optarg);
-         break;
-       case 162:
-         setoptval ("savecookies", optarg);
-         break;
-       case 163:
-         setoptval ("progress", optarg);
-         break;
-       case 164:
-         setoptval ("limitrate", optarg);
-         break;
-       case 157:
-         setoptval ("referer", optarg);
-         break;
-#ifdef HAVE_SSL
-       case 158:
-         setoptval ("sslcertfile", optarg);
-         break;
-       case 159:
-         setoptval ("sslcertkey", optarg);
-         break;
-       case 166:
-         setoptval ("egdfile", optarg);
-         break;
-       case 169:
-         setoptval ("sslcadir", optarg);
-         break;
-       case 170:
-         setoptval ("sslcafile", optarg);
-         break;
-       case 171:
-         setoptval ("sslcerttype", optarg);
-         break;
-       case 172:
-         setoptval ("sslcheckcert", optarg);
-         break;
-       case 173:
-         setoptval ("sslprotocol", optarg);
-         break;
-#endif /* HAVE_SSL */
-       case 167:
-         setoptval ("postdata", optarg);
-         break;
-       case 168:
-         setoptval ("postfile", optarg);
-         break;
-       case 175:
-         setoptval ("dnscache", optarg);
-         break;
-       case 176:
-         setoptval ("restrictfilenames", optarg);
-         break;
-       case 178:
-         setoptval ("dnstimeout", optarg);
-         break;
-       case 179:
-         setoptval ("readtimeout", optarg);
-         break;
-       case 180:
-         setoptval ("connecttimeout", optarg);
-         break;
-       case 'A':
-         setoptval ("accept", optarg);
-         break;
-       case 'a':
-         setoptval ("logfile", optarg);
-         append_to_log = 1;
-         break;
-       case 'B':
-         setoptval ("base", optarg);
-         break;
-       case 'C':
-         setoptval ("cache", optarg);
-         break;
-       case 'D':
-         setoptval ("domains", optarg);
-         break;
-       case 'e':
+       case OPT__EXECUTE:
          run_command (optarg);
          break;
-       case 'G':
-         setoptval ("ignoretags", optarg);
-         break;
-       case 'g':
-         setoptval ("glob", optarg);
-         break;
-       case 'I':
-         setoptval ("includedirectories", optarg);
-         break;
-       case 'i':
-         setoptval ("input", optarg);
-         break;
-       case 'l':
-         setoptval ("reclevel", optarg);
-         break;
-       case 'n':
+       case OPT__NO:
          {
-           /* #### What we really want here is --no-foo. */
+           /* We support real --no-FOO flags now, but keep these
+              short options for convenience and backward
+              compatibility.  */
            char *p;
-
            for (p = optarg; *p; p++)
              switch (*p)
                {
                case 'v':
-                 setoptval ("verbose", "off");
+                 setoptval ("verbose", "0");
                  break;
                case 'H':
-                 setoptval ("addhostdir", "off");
+                 setoptval ("addhostdir", "0");
                  break;
                case 'd':
-                 setoptval ("dirstruct", "off");
+                 setoptval ("dirstruct", "0");
                  break;
                case 'c':
-                 setoptval ("noclobber", "on");
-                 break;
-               case 'r':
-                 setoptval ("removelisting", "off");
+                 setoptval ("noclobber", "1");
                  break;
                case 'p':
-                 setoptval ("noparent", "on");
-                 break;
-               case 'k':
-                 setoptval ("httpkeepalive", "off");
+                 setoptval ("noparent", "1");
                  break;
                default:
                  printf (_("%s: illegal option -- `-n%c'\n"), exec_name, *p);
@@ -709,47 +602,36 @@ GNU General Public License for more details.\n"));
                }
            break;
          }
-       case 'O':
-         setoptval ("outputdocument", optarg);
-         break;
-       case 'o':
-         setoptval ("logfile", optarg);
-         break;
-       case 'P':
-         setoptval ("dirprefix", optarg);
-         break;
-       case 'Q':
-         setoptval ("quota", optarg);
-         break;
-       case 'R':
-         setoptval ("reject", optarg);
-         break;
-       case 'T':
-         setoptval ("timeout", optarg);
-         break;
-       case 't':
-         setoptval ("tries", optarg);
-         break;
-       case 'U':
-         setoptval ("useragent", optarg);
-         break;
-       case 'w':
-         setoptval ("wait", optarg);
-         break;
-       case 'X':
-         setoptval ("excludedirectories", optarg);
-         break;
-       case 'Y':
-         setoptval ("useproxy", optarg);
-         break;
-
-       case '?':
-         print_usage ();
-         printf ("\n");
-         printf (_("Try `%s --help' for more options.\n"), exec_name);
+       case OPT__PARENT:
+       case OPT__CLOBBER:
+         {
+           /* The wgetrc commands are named noparent and noclobber,
+              so we must revert the meaning of the cmdline options
+              before passing the value to setoptval.  */
+           int flag = 1;
+           if (optarg)
+             flag = (*optarg == '1' || TOLOWER (*optarg) == 'y'
+                     || (TOLOWER (optarg[0]) == 'o'
+                         && TOLOWER (optarg[1]) == 'n'));
+           setoptval (opt->type == OPT__PARENT ? "noparent" : "noclobber",
+                      flag ? "0" : "1");
+           break;
+         }
+       case OPT__VERSION:
+         printf ("GNU Wget %s\n\n", version_string);
+         printf ("%s", _("\
+Copyright (C) 2003 Free Software Foundation, Inc.\n"));
+         printf ("%s", _("\
+This program is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
+GNU General Public License for more details.\n"));
+         printf (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"));
          exit (0);
          break;
        }
+
+      longindex = -1;
     }
 
   /* All user options have now been processed, so it's now safe to do