]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_getparam: refactored, simplified
authorDaniel Stenberg <daniel@haxx.se>
Sun, 25 May 2025 10:24:49 +0000 (12:24 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 28 May 2025 12:25:32 +0000 (14:25 +0200)
- add dedicated option functions for bools/none/strings
- simplify clearing (some) arguments, use '*' instead of ' '
- scripts/top-complexity: remove getparameter from whitelist
- handle --help separately
- getstr and getstrn do not allow a NULL input
- improve the ;auto check, it needs to be trailing
- add toggle bit helper function
- unify an error message for bad --no- use
- introduce generic handling of deprecated options: ARG_DEPR
- handle --no- prefix on more booleans:

    --cert-status
    --doh-cert-status
    --false-start
    --mptcp
    --ssl-no-revoke
    --ssl-revoke-best-effort
    --tcp-fastopen

Closes #17448

scripts/top-complexity
src/tool_cfgable.h
src/tool_getparam.c
src/tool_getparam.h
src/tool_helpers.c
src/tool_parsecfg.c

index 675d83b1854d3820f87d19345796f5d50421e7cf..9bd771048f21568da03dbd8e68ebb4fcaebd9910 100755 (executable)
@@ -75,7 +75,7 @@ my @output=`$cmd`;
 
 # these functions can have these scores, but not higher
 my %whitelist = (
-    'getparameter' => 142
+
     );
 
 # functions with complexity above this level causes the function to return error
index 804e2c4a1a757bc2138e8326cef148df3f4ffb41..c4f1d6b23448169e3b7557b0982a35bece831626 100644 (file)
@@ -218,7 +218,7 @@ struct OperationConfig {
   long retry_delay;         /* delay between retries (in seconds) */
   long retry_maxtime;       /* maximum time to keep retrying */
 
-  long mime_options;        /* Mime option flags. */
+  unsigned long mime_options; /* Mime option flags. */
   long tftp_blksize;        /* TFTP BLKSIZE option */
   long alivetime;           /* keepalive-time */
   long alivecnt;            /* keepalive-cnt */
index 7354c059be6be08431b95a6ec9e82a292cbc5908..08b1167f1930d9fa23d84dea92a1157026010e82 100644 (file)
@@ -51,14 +51,14 @@ static ParameterError getstr(char **str, const char *val, bool allowblank)
     free(*str);
     *str = NULL;
   }
-  if(val) {
-    if(!allowblank && !val[0])
-      return PARAM_BLANK_STRING;
+  DEBUGASSERT(val);
+  if(!allowblank && !val[0])
+    return PARAM_BLANK_STRING;
+
+  *str = strdup(val);
+  if(!*str)
+    return PARAM_NO_MEM;
 
-    *str = strdup(val);
-    if(!*str)
-      return PARAM_NO_MEM;
-  }
   return PARAM_OK;
 }
 
@@ -69,17 +69,17 @@ static ParameterError getstrn(char **str, const char *val,
     free(*str);
     *str = NULL;
   }
-  if(val) {
-    if(!allowblank && !val[0])
-      return PARAM_BLANK_STRING;
+  DEBUGASSERT(val);
+  if(!allowblank && !val[0])
+    return PARAM_BLANK_STRING;
 
-    *str = malloc(len + 1);
-    if(!*str)
-      return PARAM_NO_MEM;
+  *str = malloc(len + 1);
+  if(!*str)
+    return PARAM_NO_MEM;
+
+  memcpy(*str, val, len);
+  (*str)[len] = 0; /* null terminate */
 
-    memcpy(*str, val, len);
-    (*str)[len] = 0; /* null terminate */
-  }
   return PARAM_OK;
 }
 
@@ -96,7 +96,7 @@ static const struct LongShort aliases[]= {
   {"ca-native",                  ARG_BOOL|ARG_TLS, ' ', C_CA_NATIVE},
   {"cacert",                     ARG_FILE|ARG_TLS, ' ', C_CACERT},
   {"capath",                     ARG_FILE|ARG_TLS, ' ', C_CAPATH},
-  {"cert",                       ARG_FILE|ARG_TLS, 'E', C_CERT},
+  {"cert",                       ARG_FILE|ARG_TLS|ARG_CLEAR, 'E', C_CERT},
   {"cert-status",                ARG_BOOL|ARG_TLS, ' ', C_CERT_STATUS},
   {"cert-type",                  ARG_STRG|ARG_TLS, ' ', C_CERT_TYPE},
   {"ciphers",                    ARG_STRG|ARG_TLS, ' ', C_CIPHERS},
@@ -131,11 +131,11 @@ static const struct LongShort aliases[]= {
   {"dns-servers",                ARG_STRG, ' ', C_DNS_SERVERS},
   {"doh-cert-status",            ARG_BOOL|ARG_TLS, ' ', C_DOH_CERT_STATUS},
   {"doh-insecure",               ARG_BOOL|ARG_TLS, ' ', C_DOH_INSECURE},
-  {"doh-url"        ,            ARG_STRG|ARG_TLS, ' ', C_DOH_URL},
+  {"doh-url"        ,            ARG_STRG, ' ', C_DOH_URL},
   {"dump-ca-embed",              ARG_NONE|ARG_TLS, ' ', C_DUMP_CA_EMBED},
   {"dump-header",                ARG_FILE, 'D', C_DUMP_HEADER},
   {"ech",                        ARG_STRG|ARG_TLS, ' ', C_ECH},
-  {"egd-file",                   ARG_STRG, ' ', C_EGD_FILE},
+  {"egd-file",                   ARG_STRG|ARG_DEPR, ' ', C_EGD_FILE},
   {"engine",                     ARG_STRG|ARG_TLS, ' ', C_ENGINE},
   {"eprt",                       ARG_BOOL, ' ', C_EPRT},
   {"epsv",                       ARG_BOOL, ' ', C_EPSV},
@@ -169,7 +169,7 @@ static const struct LongShort aliases[]= {
   {"haproxy-protocol",           ARG_BOOL, ' ', C_HAPROXY_PROTOCOL},
   {"head",                       ARG_BOOL, 'I', C_HEAD},
   {"header",                     ARG_STRG, 'H', C_HEADER},
-  {"help",                       ARG_BOOL, 'h', C_HELP},
+  {"help",                       ARG_STRG, 'h', C_HELP},
   {"hostpubmd5",                 ARG_STRG, ' ', C_HOSTPUBMD5},
   {"hostpubsha256",              ARG_STRG, ' ', C_HOSTPUBSHA256},
   {"hsts",                       ARG_STRG|ARG_TLS, ' ', C_HSTS},
@@ -195,7 +195,7 @@ static const struct LongShort aliases[]= {
   {"keepalive",                  ARG_BOOL|ARG_NO, ' ', C_KEEPALIVE},
   {"keepalive-cnt",              ARG_STRG, ' ', C_KEEPALIVE_CNT},
   {"keepalive-time",             ARG_STRG, ' ', C_KEEPALIVE_TIME},
-  {"key",                        ARG_FILE|ARG_TLS, ' ', C_KEY},
+  {"key",                        ARG_FILE, ' ', C_KEY},
   {"key-type",                   ARG_STRG|ARG_TLS, ' ', C_KEY_TYPE},
   {"krb",                        ARG_STRG, ' ', C_KRB},
   {"krb4",                       ARG_STRG, ' ', C_KRB4},
@@ -214,7 +214,7 @@ static const struct LongShort aliases[]= {
   {"max-filesize",               ARG_STRG, ' ', C_MAX_FILESIZE},
   {"max-redirs",                 ARG_STRG, ' ', C_MAX_REDIRS},
   {"max-time",                   ARG_STRG, 'm', C_MAX_TIME},
-  {"metalink",                   ARG_BOOL, ' ', C_METALINK},
+  {"metalink",                   ARG_BOOL|ARG_DEPR, ' ', C_METALINK},
   {"mptcp",                      ARG_BOOL, ' ', C_MPTCP},
   {"negotiate",                  ARG_BOOL, ' ', C_NEGOTIATE},
   {"netrc",                      ARG_BOOL, 'n', C_NETRC},
@@ -222,16 +222,16 @@ static const struct LongShort aliases[]= {
   {"netrc-optional",             ARG_BOOL, ' ', C_NETRC_OPTIONAL},
   {"next",                       ARG_NONE, ':', C_NEXT},
   {"noproxy",                    ARG_STRG, ' ', C_NOPROXY},
-  {"npn",                        ARG_BOOL|ARG_NO, ' ', C_NPN},
+  {"npn",                        ARG_BOOL|ARG_DEPR, ' ', C_NPN},
   {"ntlm",                       ARG_BOOL, ' ', C_NTLM},
-  {"ntlm-wb",                    ARG_BOOL, ' ', C_NTLM_WB},
-  {"oauth2-bearer",              ARG_STRG, ' ', C_OAUTH2_BEARER},
+  {"ntlm-wb",                    ARG_BOOL|ARG_DEPR, ' ', C_NTLM_WB},
+  {"oauth2-bearer",              ARG_STRG|ARG_CLEAR, ' ', C_OAUTH2_BEARER},
   {"output",                     ARG_FILE, 'o', C_OUTPUT},
   {"output-dir",                 ARG_STRG, ' ', C_OUTPUT_DIR},
   {"parallel",                   ARG_BOOL, 'Z', C_PARALLEL},
   {"parallel-immediate",         ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},
   {"parallel-max",               ARG_STRG, ' ', C_PARALLEL_MAX},
-  {"pass",                       ARG_STRG, ' ', C_PASS},
+  {"pass",                       ARG_STRG|ARG_CLEAR, ' ', C_PASS},
   {"path-as-is",                 ARG_BOOL, ' ', C_PATH_AS_IS},
   {"pinnedpubkey",               ARG_STRG|ARG_TLS, ' ', C_PINNEDPUBKEY},
   {"post301",                    ARG_BOOL, ' ', C_POST301},
@@ -249,7 +249,7 @@ static const struct LongShort aliases[]= {
   {"proxy-ca-native",            ARG_BOOL|ARG_TLS, ' ', C_PROXY_CA_NATIVE},
   {"proxy-cacert",               ARG_FILE|ARG_TLS, ' ', C_PROXY_CACERT},
   {"proxy-capath",               ARG_FILE|ARG_TLS, ' ', C_PROXY_CAPATH},
-  {"proxy-cert",                 ARG_FILE|ARG_TLS, ' ', C_PROXY_CERT},
+  {"proxy-cert",                ARG_FILE|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_CERT},
   {"proxy-cert-type",            ARG_STRG|ARG_TLS, ' ', C_PROXY_CERT_TYPE},
   {"proxy-ciphers",              ARG_STRG|ARG_TLS, ' ', C_PROXY_CIPHERS},
   {"proxy-crlfile",              ARG_FILE|ARG_TLS, ' ', C_PROXY_CRLFILE},
@@ -261,7 +261,7 @@ static const struct LongShort aliases[]= {
   {"proxy-key-type",             ARG_STRG|ARG_TLS, ' ', C_PROXY_KEY_TYPE},
   {"proxy-negotiate",            ARG_BOOL, ' ', C_PROXY_NEGOTIATE},
   {"proxy-ntlm",                 ARG_BOOL, ' ', C_PROXY_NTLM},
-  {"proxy-pass",                 ARG_STRG, ' ', C_PROXY_PASS},
+  {"proxy-pass",                 ARG_STRG|ARG_CLEAR, ' ', C_PROXY_PASS},
   {"proxy-pinnedpubkey",         ARG_STRG|ARG_TLS, ' ', C_PROXY_PINNEDPUBKEY},
   {"proxy-service-name",         ARG_STRG, ' ', C_PROXY_SERVICE_NAME},
   {"proxy-ssl-allow-beast",      ARG_BOOL|ARG_TLS, ' ',
@@ -270,15 +270,15 @@ static const struct LongShort aliases[]= {
    C_PROXY_SSL_AUTO_CLIENT_CERT},
   {"proxy-tls13-ciphers",        ARG_STRG|ARG_TLS, ' ', C_PROXY_TLS13_CIPHERS},
   {"proxy-tlsauthtype",          ARG_STRG|ARG_TLS, ' ', C_PROXY_TLSAUTHTYPE},
-  {"proxy-tlspassword",          ARG_STRG|ARG_TLS, ' ', C_PROXY_TLSPASSWORD},
-  {"proxy-tlsuser",              ARG_STRG|ARG_TLS, ' ', C_PROXY_TLSUSER},
+  {"proxy-tlspassword",  ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_TLSPASSWORD},
+  {"proxy-tlsuser",          ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_PROXY_TLSUSER},
   {"proxy-tlsv1",                ARG_NONE|ARG_TLS, ' ', C_PROXY_TLSV1},
-  {"proxy-user",                 ARG_STRG, 'U', C_PROXY_USER},
+  {"proxy-user",                 ARG_STRG|ARG_CLEAR, 'U', C_PROXY_USER},
   {"proxy1.0",                   ARG_STRG, ' ', C_PROXY1_0},
   {"proxytunnel",                ARG_BOOL, 'p', C_PROXYTUNNEL},
   {"pubkey",                     ARG_STRG, ' ', C_PUBKEY},
   {"quote",                      ARG_STRG, 'Q', C_QUOTE},
-  {"random-file",                ARG_FILE, ' ', C_RANDOM_FILE},
+  {"random-file",                ARG_FILE|ARG_DEPR, ' ', C_RANDOM_FILE},
   {"range",                      ARG_STRG, 'r', C_RANGE},
   {"rate",                       ARG_STRG, ' ', C_RATE},
   {"raw",                        ARG_BOOL, ' ', C_RAW},
@@ -325,8 +325,8 @@ static const struct LongShort aliases[]= {
   {"ssl-revoke-best-effort",     ARG_BOOL|ARG_TLS, ' ',
    C_SSL_REVOKE_BEST_EFFORT},
   {"ssl-sessions",               ARG_FILE|ARG_TLS, ' ', C_SSL_SESSIONS},
-  {"sslv2",                      ARG_NONE|ARG_TLS, '2', C_SSLV2},
-  {"sslv3",                      ARG_NONE|ARG_TLS, '3', C_SSLV3},
+  {"sslv2",                      ARG_NONE|ARG_DEPR, '2', C_SSLV2},
+  {"sslv3",                      ARG_NONE|ARG_DEPR, '3', C_SSLV3},
   {"stderr",                     ARG_FILE, ' ', C_STDERR},
   {"styled-output",              ARG_BOOL, ' ', C_STYLED_OUTPUT},
   {"suppress-connect-headers",   ARG_BOOL, ' ', C_SUPPRESS_CONNECT_HEADERS},
@@ -344,8 +344,8 @@ static const struct LongShort aliases[]= {
   {"tls-max",                    ARG_STRG|ARG_TLS, ' ', C_TLS_MAX},
   {"tls13-ciphers",              ARG_STRG|ARG_TLS, ' ', C_TLS13_CIPHERS},
   {"tlsauthtype",                ARG_STRG|ARG_TLS, ' ', C_TLSAUTHTYPE},
-  {"tlspassword",                ARG_STRG|ARG_TLS, ' ', C_TLSPASSWORD},
-  {"tlsuser",                    ARG_STRG|ARG_TLS, ' ', C_TLSUSER},
+  {"tlspassword",              ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_TLSPASSWORD},
+  {"tlsuser",                    ARG_STRG|ARG_TLS|ARG_CLEAR, ' ', C_TLSUSER},
   {"tlsv1",                      ARG_NONE|ARG_TLS, '1', C_TLSV1},
   {"tlsv1.0",                    ARG_NONE|ARG_TLS, ' ', C_TLSV1_0},
   {"tlsv1.1",                    ARG_NONE|ARG_TLS, ' ', C_TLSV1_1},
@@ -363,7 +363,7 @@ static const struct LongShort aliases[]= {
   {"url",                        ARG_STRG, ' ', C_URL},
   {"url-query",                  ARG_STRG, ' ', C_URL_QUERY},
   {"use-ascii",                  ARG_BOOL, 'B', C_USE_ASCII},
-  {"user",                       ARG_STRG, 'u', C_USER},
+  {"user",                       ARG_STRG|ARG_CLEAR, 'u', C_USER},
   {"user-agent",                 ARG_STRG, 'A', C_USER_AGENT},
   {"variable",                   ARG_STRG, ' ', C_VARIABLE},
   {"verbose",                    ARG_BOOL, 'v', C_VERBOSE},
@@ -573,18 +573,18 @@ static ParameterError GetSizeParameter(struct GlobalConfig *global,
 }
 
 #ifdef HAVE_WRITABLE_ARGV
-static void cleanarg(argv_item_t str)
+static void cleanarg(char *str)
 {
   /* now that getstr has copied the contents of nextarg, wipe the next
    * argument out so that the username:password is not displayed in the
    * system process list */
   if(str) {
     size_t len = strlen(str);
-    memset(str, ' ', len);
+    memset(str, '*', len);
   }
 }
 #else
-#define cleanarg(x)
+#define cleanarg(x) tool_nop_stmt
 #endif
 
 /* the maximum size we allow the dynbuf generated string */
@@ -1469,9 +1469,10 @@ static ParameterError parse_upload_file(struct OperationConfig *config,
   return err;
 }
 
+static size_t verbose_nopts;
+
 static ParameterError parse_verbose(struct GlobalConfig *global,
-                                    bool toggle,
-                                    size_t nopts)
+                                    bool toggle)
 {
   ParameterError err = PARAM_OK;
 
@@ -1484,7 +1485,7 @@ static ParameterError parse_verbose(struct GlobalConfig *global,
     global->tracetype = TRACE_NONE;
     return err;
   }
-  else if(!nopts) {
+  else if(!verbose_nopts) {
     /* fist `-v` in an argument resets to base verbosity */
     global->verbosity = 0;
     if(set_trace_config(global, "-all"))
@@ -1673,23 +1674,501 @@ static ParameterError parse_upload_flags(struct OperationConfig *config,
   return err;
 }
 
-ParameterError getparameter(const char *flag, /* f or -long-flag */
-                            const char *nextarg,    /* NULL if unset */
-                            argv_item_t cleararg1,
-                            argv_item_t cleararg2,
-                            bool *usedarg,    /* set to TRUE if the arg
-                                                 has been used */
-                            struct GlobalConfig *global,
-                            struct OperationConfig *config)
+/* if 'toggle' is TRUE, set the 'bits' in 'modify'.
+   if 'toggle' is FALSE, clear the 'bits' in 'modify'
+*/
+static void togglebit(bool toggle, unsigned long *modify, unsigned long bits)
+{
+  if(toggle)
+    *modify |= bits;
+  else
+    *modify &= ~bits;
+}
+
+/* opt_depr is the function that handles ARG_DEPR options */
+static void opt_depr(struct GlobalConfig *global,
+                     const struct LongShort *a)
+{
+  warnf(global, "--%s is deprecated and has no function anymore", a->lname);
+}
+
+/* opt_none is the function that handles ARG_NONE options */
+static ParameterError opt_none(struct GlobalConfig *global,
+                               struct OperationConfig *config,
+                               const struct LongShort *a)
+{
+  switch(a->cmd) {
+  case C_DUMP_CA_EMBED: /* --dump-ca-embed */
+    return PARAM_CA_EMBED_REQUESTED;
+
+  case C_HTTP1_0: /* --http1.0 */
+    /* HTTP version 1.0 */
+    sethttpver(global, config, CURL_HTTP_VERSION_1_0);
+    break;
+  case C_HTTP1_1: /* --http1.1 */
+    /* HTTP version 1.1 */
+    sethttpver(global, config, CURL_HTTP_VERSION_1_1);
+    break;
+  case C_HTTP2: /* --http2 */
+    /* HTTP version 2.0 */
+    if(!feature_http2)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    sethttpver(global, config, CURL_HTTP_VERSION_2_0);
+    break;
+  case C_HTTP2_PRIOR_KNOWLEDGE: /* --http2-prior-knowledge */
+    /* HTTP version 2.0 over clean TCP */
+    if(!feature_http2)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
+    break;
+  case C_HTTP3: /* --http3: */
+    /* Try HTTP/3, allow fallback */
+    if(!feature_http3)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      sethttpver(global, config, CURL_HTTP_VERSION_3);
+    break;
+  case C_HTTP3_ONLY: /* --http3-only */
+    /* Try HTTP/3 without fallback */
+    if(!feature_http3)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
+    break;
+  case C_TLSV1: /* --tlsv1 */
+    config->ssl_version = CURL_SSLVERSION_TLSv1;
+    break;
+  case C_TLSV1_0: /* --tlsv1.0 */
+    config->ssl_version = CURL_SSLVERSION_TLSv1_0;
+    break;
+  case C_TLSV1_1: /* --tlsv1.1 */
+    config->ssl_version = CURL_SSLVERSION_TLSv1_1;
+    break;
+  case C_TLSV1_2: /* --tlsv1.2 */
+    config->ssl_version = CURL_SSLVERSION_TLSv1_2;
+    break;
+  case C_TLSV1_3: /* --tlsv1.3 */
+    config->ssl_version = CURL_SSLVERSION_TLSv1_3;
+    break;
+  case C_IPV4: /* --ipv4 */
+    config->ip_version = CURL_IPRESOLVE_V4;
+    break;
+  case C_IPV6: /* --ipv6 */
+    config->ip_version = CURL_IPRESOLVE_V6;
+    break;
+  case C_NEXT: /* --next */
+    return PARAM_NEXT_OPERATION;
+  case C_PROXY_TLSV1: /* --proxy-tlsv1 */
+    /* TLS version 1 for proxy */
+    config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
+    break;
+  }
+  return PARAM_OK;
+}
+
+/* opt_bool is the function that handles boolean options */
+static ParameterError opt_bool(struct GlobalConfig *global,
+                               struct OperationConfig *config,
+                               const struct LongShort *a,
+                               bool toggle)
+{
+  switch(a->cmd) {
+  case C_ALPN: /* --alpn */
+    config->noalpn = !toggle;
+    break;
+  case C_DISABLE_EPSV: /* --disable-epsv */
+    config->disable_epsv = toggle;
+    break;
+  case C_DISALLOW_USERNAME_IN_URL: /* --disallow-username-in-url */
+    config->disallow_username_in_url = toggle;
+    break;
+  case C_EPSV: /* --epsv */
+    config->disable_epsv = !toggle;
+    break;
+  case C_COMPRESSED: /* --compressed */
+    if(toggle && !(feature_libz || feature_brotli || feature_zstd))
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      config->encoding = toggle;
+    break;
+  case C_TR_ENCODING: /* --tr-encoding */
+    config->tr_encoding = toggle;
+    break;
+  case C_DIGEST: /* --digest */
+    togglebit(toggle, &config->authtype, CURLAUTH_DIGEST);
+    break;
+  case C_FTP_CREATE_DIRS: /* --ftp-create-dirs */
+    config->ftp_create_dirs = toggle;
+    break;
+  case C_CREATE_DIRS: /* --create-dirs */
+    config->create_dirs = toggle;
+    break;
+  case C_PROXY_NTLM: /* --proxy-ntlm */
+    if(!feature_ntlm)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      config->proxyntlm = toggle;
+    break;
+  case C_CRLF: /* --crlf */
+    config->crlf = toggle;
+    break;
+  case C_HAPROXY_PROTOCOL: /* --haproxy-protocol */
+    config->haproxy_protocol = toggle;
+    break;
+  case C_NEGOTIATE: /* --negotiate */
+    if(!feature_spnego && toggle)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    togglebit(toggle, &config->authtype, CURLAUTH_NEGOTIATE);
+    break;
+  case C_NTLM: /* --ntlm */
+    if(!feature_ntlm && toggle)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    togglebit(toggle, &config->authtype, CURLAUTH_NTLM);
+    break;
+  case C_BASIC: /* --basic */
+    togglebit(toggle, &config->authtype, CURLAUTH_BASIC);
+    break;
+  case C_ANYAUTH: /* --anyauth */
+    if(toggle)
+      config->authtype = CURLAUTH_ANY;
+    /* --no-anyauth simply does not touch it */
+    break;
+#ifdef USE_WATT32
+  case C_WDEBUG: /* --wdebug */
+    dbug_init();
+    break;
+#endif
+  case C_DISABLE_EPRT: /* --disable-eprt */
+    config->disable_eprt = toggle;
+    break;
+  case C_EPRT: /* --eprt */
+    config->disable_eprt = !toggle;
+    break;
+  case C_XATTR: /* --xattr */
+    config->xattr = toggle;
+    break;
+  case C_FTP_SSL: /* --ftp-ssl */
+  case C_SSL: /* --ssl */
+    config->ftp_ssl = toggle;
+    if(config->ftp_ssl)
+      warnf(global, "--%s is an insecure option, consider --ssl-reqd instead",
+            a->lname);
+    break;
+  case C_FTP_SSL_CCC: /* --ftp-ssl-ccc */
+    config->ftp_ssl_ccc = toggle;
+    if(!config->ftp_ssl_ccc_mode)
+      config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+    break;
+  case C_TCP_NODELAY: /* --tcp-nodelay */
+    config->tcp_nodelay = toggle;
+    break;
+  case C_PROXY_DIGEST: /* --proxy-digest */
+    config->proxydigest = toggle;
+    break;
+  case C_PROXY_BASIC: /* --proxy-basic */
+    config->proxybasic = toggle;
+    break;
+  case C_RETRY_CONNREFUSED: /* --retry-connrefused */
+    config->retry_connrefused = toggle;
+    break;
+  case C_RETRY_ALL_ERRORS: /* --retry-all-errors */
+    config->retry_all_errors = toggle;
+    break;
+  case C_PROXY_NEGOTIATE: /* --proxy-negotiate */
+    if(!feature_spnego)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      config->proxynegotiate = toggle;
+    break;
+  case C_FORM_ESCAPE: /* --form-escape */
+    togglebit(toggle, &config->mime_options, CURLMIMEOPT_FORMESCAPE);
+    break;
+  case C_PROXY_ANYAUTH: /* --proxy-anyauth */
+    config->proxyanyauth = toggle;
+    break;
+  case C_TRACE_TIME: /* --trace-time */
+    global->tracetime = toggle;
+    break;
+  case C_IGNORE_CONTENT_LENGTH: /* --ignore-content-length */
+    config->ignorecl = toggle;
+    break;
+  case C_FTP_SKIP_PASV_IP: /* --ftp-skip-pasv-ip */
+    config->ftp_skip_ip = toggle;
+    break;
+  case C_FTP_SSL_REQD: /* --ftp-ssl-reqd */
+  case C_SSL_REQD: /* --ssl-reqd */
+    config->ftp_ssl_reqd = toggle;
+    break;
+  case C_SESSIONID: /* --sessionid */
+    config->disable_sessionid = !toggle;
+    break;
+  case C_FTP_SSL_CONTROL: /* --ftp-ssl-control */
+    config->ftp_ssl_control = toggle;
+    break;
+  case C_RAW: /* --raw */
+    config->raw = toggle;
+    break;
+  case C_KEEPALIVE: /* --keepalive */
+    config->nokeepalive = !toggle;
+    break;
+  case C_POST301: /* --post301 */
+    config->post301 = toggle;
+    break;
+  case C_POST302: /* --post302 */
+    config->post302 = toggle;
+    break;
+  case C_POST303: /* --post303 */
+    config->post303 = toggle;
+    break;
+  case C_SOCKS5_GSSAPI_NEC: /* --socks5-gssapi-nec */
+    config->socks5_gssapi_nec = toggle;
+    break;
+  case C_FTP_PRET: /* --ftp-pret */
+    config->ftp_pret = toggle;
+    break;
+  case C_SASL_IR: /* --sasl-ir */
+    config->sasl_ir = toggle;
+    break;
+#ifdef DEBUGBUILD
+  case C_TEST_DUPHANDLE: /* --test-duphandle */
+    global->test_duphandle = toggle;
+    break;
+  case C_TEST_EVENT: /* --test-event */
+    global->test_event_based = toggle;
+    break;
+#endif
+  case C_PATH_AS_IS: /* --path-as-is */
+    config->path_as_is = toggle;
+    break;
+  case C_TFTP_NO_OPTIONS: /* --tftp-no-options */
+    config->tftp_no_options = toggle;
+    break;
+  case C_TLS_EARLYDATA: /* --tls-earlydata */
+    config->ssl_allow_earlydata = toggle;
+    break;
+  case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
+    config->suppress_connect_headers = toggle;
+    break;
+  case C_COMPRESSED_SSH: /* --compressed-ssh */
+    config->ssh_compression = toggle;
+    break;
+  case C_TRACE_IDS: /* --trace-ids */
+    global->traceids = toggle;
+    break;
+  case C_PROGRESS_METER: /* --progress-meter */
+    global->noprogress = !toggle;
+    break;
+  case C_PROGRESS_BAR: /* --progress-bar */
+    global->progressmode = toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
+    break;
+  case C_HTTP0_9: /* --http0.9 */
+    config->http09_allowed = toggle;
+    break;
+  case C_PROXY_HTTP2: /* --proxy-http2 */
+    if(!feature_httpsproxy || !feature_http2)
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+
+    config->proxyver = toggle ? CURLPROXY_HTTPS2 : CURLPROXY_HTTPS;
+    break;
+  case C_APPEND: /* --append */
+    config->ftp_append = toggle;
+    break;
+  case C_USE_ASCII: /* --use-ascii */
+    config->use_ascii = toggle;
+    break;
+  case C_CA_NATIVE: /* --ca-native */
+    config->native_ca_store = toggle;
+    break;
+  case C_PROXY_CA_NATIVE: /* --proxy-ca-native */
+    config->proxy_native_ca_store = toggle;
+    break;
+  case C_SSL_ALLOW_BEAST: /* --ssl-allow-beast */
+    config->ssl_allow_beast = toggle;
+    break;
+  case C_SSL_AUTO_CLIENT_CERT: /* --ssl-auto-client-cert */
+    config->ssl_auto_client_cert = toggle;
+    break;
+  case C_PROXY_SSL_AUTO_CLIENT_CERT: /* --proxy-ssl-auto-client-cert */
+    config->proxy_ssl_auto_client_cert = toggle;
+    break;
+  case C_CERT_STATUS: /* --cert-status */
+    config->verifystatus = toggle;
+    break;
+  case C_DOH_CERT_STATUS: /* --doh-cert-status */
+    config->doh_verifystatus = toggle;
+    break;
+  case C_FALSE_START: /* --false-start */
+    config->falsestart = toggle;
+    break;
+  case C_SSL_NO_REVOKE: /* --ssl-no-revoke */
+    config->ssl_no_revoke = toggle;
+    break;
+  case C_SSL_REVOKE_BEST_EFFORT: /* --ssl-revoke-best-effort */
+    config->ssl_revoke_best_effort = toggle;
+    break;
+  case C_TCP_FASTOPEN: /* --tcp-fastopen */
+    config->tcp_fastopen = toggle;
+    break;
+  case C_PROXY_SSL_ALLOW_BEAST: /* --proxy-ssl-allow-beast */
+    config->proxy_ssl_allow_beast = toggle;
+    break;
+  case C_PROXY_INSECURE: /* --proxy-insecure */
+    config->proxy_insecure_ok = toggle;
+    break;
+  case C_SOCKS5_BASIC: /* --socks5-basic */
+    togglebit(toggle, &config->socks5_auth, CURLAUTH_BASIC);
+    break;
+  case C_SOCKS5_GSSAPI: /* --socks5-gssapi */
+    togglebit(toggle, &config->socks5_auth, CURLAUTH_GSSAPI);
+    break;
+  case C_FAIL_EARLY: /* --fail-early */
+    global->fail_early = toggle;
+    break;
+  case C_STYLED_OUTPUT: /* --styled-output */
+    global->styled_output = toggle;
+    break;
+  case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
+    config->mail_rcpt_allowfails = toggle;
+    break;
+  case C_FAIL_WITH_BODY: /* --fail-with-body */
+    config->failwithbody = toggle;
+    if(config->failonerror && config->failwithbody) {
+      errorf(config->global, "You must select either --fail or "
+             "--fail-with-body, not both.");
+      return PARAM_BAD_USE;
+    }
+    break;
+  case C_REMOVE_ON_ERROR: /* --remove-on-error */
+    if(config->use_resume && toggle) {
+      errorf(config->global,
+             "--continue-at is mutually exclusive with --remove-on-error");
+      return PARAM_BAD_USE;
+    }
+    config->rm_partial = toggle;
+    break;
+  case C_FAIL: /* --fail */
+    config->failonerror = toggle;
+    if(config->failonerror && config->failwithbody) {
+      errorf(config->global, "You must select either --fail or "
+             "--fail-with-body, not both.");
+      return PARAM_BAD_USE;
+    }
+    break;
+  case C_GLOBOFF: /* --globoff */
+    config->globoff = toggle;
+    break;
+  case C_GET: /* --get */
+    config->use_httpget = toggle;
+    break;
+  case C_INCLUDE: /* --include */
+  case C_SHOW_HEADERS: /* --show-headers */
+    config->show_headers = toggle;
+    break;
+  case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
+    config->cookiesession = toggle;
+    break;
+  case C_HEAD: /* --head */
+    config->no_body = toggle;
+    config->show_headers = toggle;
+    if(SetHTTPrequest(config, (config->no_body) ? TOOL_HTTPREQ_HEAD :
+                      TOOL_HTTPREQ_GET, &config->httpreq))
+      return PARAM_BAD_USE;
+    break;
+  case C_REMOTE_HEADER_NAME: /* --remote-header-name */
+    config->content_disposition = toggle;
+    break;
+  case C_INSECURE: /* --insecure */
+    config->insecure_ok = toggle;
+    break;
+  case C_DOH_INSECURE: /* --doh-insecure */
+    config->doh_insecure_ok = toggle;
+    break;
+  case C_LIST_ONLY: /* --list-only */
+    config->dirlistonly = toggle; /* only list the names of the FTP dir */
+    break;
+  case C_LOCATION_TRUSTED: /* --location-trusted */
+    config->unrestricted_auth = toggle;
+    FALLTHROUGH();
+  case C_LOCATION: /* --location */
+    config->followlocation = toggle; /* Follow Location: HTTP headers */
+    break;
+  case C_MANUAL: /* --manual */
+    if(toggle)   /* --no-manual shows no manual... */
+      return PARAM_MANUAL_REQUESTED;
+    break;
+  case C_NETRC_OPTIONAL: /* --netrc-optional */
+    config->netrc_opt = toggle;
+    break;
+  case C_NETRC: /* --netrc */
+    config->netrc = toggle;
+    break;
+  case C_BUFFER: /* --buffer */
+    config->nobuffer = !toggle;
+    break;
+  case C_REMOTE_NAME_ALL: /* --remote-name-all */
+    config->remote_name_all = toggle;
+    break;
+  case C_CLOBBER: /* --clobber */
+    if(config->use_resume && !toggle) {
+      errorf(config->global,
+             "--continue-at is mutually exclusive with --no-clobber");
+      return PARAM_BAD_USE;
+    }
+    config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
+    break;
+  case C_REMOTE_NAME: /* --remote-name */
+    return parse_remote_name(config, toggle);
+    break;
+  case C_PROXYTUNNEL: /* --proxytunnel */
+    config->proxytunnel = toggle;
+    break;
+  case C_DISABLE: /* --disable */
+    /* if used first, already taken care of, we do it like this so we do not
+       cause an error! */
+    break;
+  case C_REMOTE_TIME: /* --remote-time */
+    config->remote_time = toggle;
+    break;
+  case C_SILENT: /* --silent */
+    global->silent = toggle;
+    break;
+  case C_SKIP_EXISTING: /* --skip-existing */
+    config->skip_existing = toggle;
+    break;
+  case C_SHOW_ERROR: /* --show-error */
+    global->showerror = toggle;
+    break;
+  case C_VERBOSE: /* --verbose */
+    return parse_verbose(global, toggle);
+    break;
+  case C_VERSION: /* --version */
+    if(toggle)    /* --no-version yields no output! */
+      return PARAM_VERSION_INFO_REQUESTED;
+    break;
+  case C_PARALLEL: /* --parallel */
+    global->parallel = toggle;
+    break;
+  case C_PARALLEL_IMMEDIATE:   /* --parallel-immediate */
+    global->parallel_connect = toggle;
+    break;
+  case C_MPTCP: /* --mptcp */
+    config->mptcp = toggle;
+    break;
+  default:
+    return PARAM_OPTION_UNKNOWN;
+  }
+  return PARAM_OK;
+}
+
+
+/* opt_filestring handles string and file options */
+static ParameterError opt_filestring(struct GlobalConfig *global,
+                                     struct OperationConfig *config,
+                                     const struct LongShort *a,
+                                     const char *nextarg)
 {
-  const char *parse = NULL;
-  bool longopt = FALSE;
-  bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
-  size_t nopts = 0; /* options processed in `flag`*/
   ParameterError err = PARAM_OK;
-  bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
-                         by using --OPTION or --no-OPTION */
-  bool nextalloc = FALSE; /* if nextarg is allocated */
+  curl_off_t value;
   static const char *redir_protos[] = {
     "http",
     "https",
@@ -1697,1270 +2176,772 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
     "ftps",
     NULL
   };
-  const struct LongShort *a = NULL;
-  curl_off_t value;
-#ifdef HAVE_WRITABLE_ARGV
-  argv_item_t clearthis = NULL;
-#else
-  (void)cleararg1;
-  (void)cleararg2;
-#endif
-
-  *usedarg = FALSE; /* default is that we do not use the arg */
-
-  if(('-' != flag[0]) || ('-' == flag[1])) {
-    /* this should be a long name */
-    const char *word = ('-' == flag[0]) ? flag + 2 : flag;
-    bool noflagged = FALSE;
-    bool expand = FALSE;
+  if(!nextarg)
+    nextarg = "";
+
+  switch(a->cmd) {
+  case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */
+    if(!curlinfo->ares_num) /* c-ares is needed for this */
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    /* addr in dot notation */
+    return getstr(&config->dns_ipv4_addr, nextarg, DENY_BLANK);
+
+  case C_DNS_IPV6_ADDR: /* --dns-ipv6-addr */
+    if(!curlinfo->ares_num) /* c-ares is needed for this */
+      return PARAM_LIBCURL_DOESNT_SUPPORT;
+    /* addr in dot notation */
+    return getstr(&config->dns_ipv6_addr, nextarg, DENY_BLANK);
+
+  case C_OAUTH2_BEARER: /* --oauth2-bearer */
+    config->authtype |= CURLAUTH_BEARER;
+    return getstr(&config->oauth_bearer, nextarg, DENY_BLANK);
+
+  case C_CONNECT_TIMEOUT: /* --connect-timeout */
+    return secs2ms(&config->connecttimeout_ms, nextarg);
+
+  case C_DOH_URL: /* --doh-url */
+    err = getstr(&config->doh_url, nextarg, ALLOW_BLANK);
+    if(!err && config->doh_url && !config->doh_url[0])
+      /* if given a blank string, make it NULL again */
+      tool_safefree(config->doh_url);
+    break;
 
-    if(!strncmp(word, "no-", 3)) {
-      /* disable this option but ignore the "no-" part when looking for it */
-      word += 3;
-      toggle = FALSE;
-      noflagged = TRUE;
-    }
-    else if(!strncmp(word, "expand-", 7)) {
-      /* variable expansions is to be done on the argument */
-      word += 7;
-      expand = TRUE;
-    }
+  case C_CIPHERS: /* -- ciphers */
+    err = getstr(&config->cipher_list, nextarg, DENY_BLANK);
+    break;
 
-    a = findlongopt(word);
-    if(a) {
-      longopt = TRUE;
-    }
-    else {
-      err = PARAM_OPTION_UNKNOWN;
-      goto error;
+  case C_DNS_INTERFACE: /* --dns-interface */
+    if(!curlinfo->ares_num) /* c-ares is needed for this */
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      /* interface name */
+      err = getstr(&config->dns_interface, nextarg, DENY_BLANK);
+    break;
+  case C_DNS_SERVERS: /* --dns-servers */
+    if(!curlinfo->ares_num) /* c-ares is needed for this */
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      /* IP addrs of DNS servers */
+      err = getstr(&config->dns_servers, nextarg, DENY_BLANK);
+    break;
+  case C_TRACE: /* --trace */
+    err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
+    if(!err) {
+      if(global->tracetype && (global->tracetype != TRACE_BIN))
+        warnf(global, "--trace overrides an earlier trace/verbose option");
+      global->tracetype = TRACE_BIN;
     }
-    if(noflagged && (ARGTYPE(a->desc) != ARG_BOOL)) {
-      /* --no- prefixed an option that is not boolean! */
-      err = PARAM_NO_NOT_BOOLEAN;
-      goto error;
+    break;
+  case C_TRACE_ASCII: /* --trace-ascii */
+    err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
+    if(!err) {
+      if(global->tracetype && (global->tracetype != TRACE_ASCII))
+        warnf(global,
+              "--trace-ascii overrides an earlier trace/verbose option");
+      global->tracetype = TRACE_ASCII;
     }
-    else if(expand && nextarg) {
-      struct dynbuf nbuf;
-      bool replaced;
-
-      if((ARGTYPE(a->desc) != ARG_STRG) &&
-         (ARGTYPE(a->desc) != ARG_FILE)) {
-        /* --expand on an option that is not a string or a filename */
-        err = PARAM_EXPAND_ERROR;
-        goto error;
-      }
-      err = varexpand(global, nextarg, &nbuf, &replaced);
-      if(err) {
-        curlx_dyn_free(&nbuf);
-        goto error;
-      }
-      if(replaced) {
-        nextarg = curlx_dyn_ptr(&nbuf);
-        nextalloc = TRUE;
-      }
+    break;
+  case C_LIMIT_RATE: /* --limit-rate */
+    err = GetSizeParameter(global, nextarg, "rate", &value);
+    if(!err) {
+      config->recvpersecond = value;
+      config->sendpersecond = value;
     }
-  }
-  else {
-    flag++; /* prefixed with one dash, pass it */
-    parse = flag;
-  }
-
-  do {
-    /* we can loop here if we have multiple single-letters */
-    cmdline_t cmd;
-
-    if(!longopt && !a) {
-      a = findshortopt(*parse);
-      if(!a) {
-        err = PARAM_OPTION_UNKNOWN;
-        break;
-      }
-    }
-    cmd = (cmdline_t)a->cmd;
-    if(ARGTYPE(a->desc) >= ARG_STRG) {
-      /* this option requires an extra parameter */
-      if(!longopt && parse[1]) {
-        nextarg = &parse[1]; /* this is the actual extra parameter */
-        singleopt = TRUE;   /* do not loop anymore after this */
-#ifdef HAVE_WRITABLE_ARGV
-        if(cleararg1)
-          clearthis = &cleararg1[parse + 2 - flag];
-#endif
-      }
-      else if(!nextarg) {
-        err = PARAM_REQUIRES_PARAMETER;
-        break;
-      }
-      else {
-#ifdef HAVE_WRITABLE_ARGV
-        if(cleararg2)
-          clearthis = cleararg2;
-#endif
-        *usedarg = TRUE; /* mark it as used */
-      }
-
-      if((ARGTYPE(a->desc) == ARG_FILE) &&
-         (nextarg[0] == '-') && nextarg[1]) {
-        /* if the filename looks like a command line option */
-        warnf(global, "The filename argument '%s' looks like a flag.",
-              nextarg);
-      }
-      else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) {
-        warnf(global, "The argument '%s' starts with a Unicode quote where "
-              "maybe an ASCII \" was intended?",
-              nextarg);
-      }
-    }
-    else if((ARGTYPE(a->desc) == ARG_NONE) && !toggle) {
-      err = PARAM_NO_PREFIX;
-      break;
-    }
-    else if((a->desc & ARG_TLS) && !feature_ssl) {
-      err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      break;
-    }
-
-    if(!nextarg)
-      /* this is a precaution mostly to please scan-build, as all arguments
-         that use nextarg should be marked as such and they will check that
-         nextarg is set before continuing, but code analyzers are not always
-         that aware of that state */
-      nextarg = "";
-
-    switch(cmd) {
-    case C_RANDOM_FILE: /* --random-file */
-    case C_EGD_FILE: /* --egd-file */
-    case C_NTLM_WB: /* --ntlm-wb */
-    case C_NPN: /* --npn */
-    case C_SSLV2: /* --sslv2 */
-    case C_SSLV3: /* --sslv3 */
-      warnf(global, "--%s is deprecated and has no function anymore",
-            a->lname);
-      break;
-    case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */
-      if(!curlinfo->ares_num) /* c-ares is needed for this */
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        /* addr in dot notation */
-        err = getstr(&config->dns_ipv4_addr, nextarg, DENY_BLANK);
-      break;
-    case C_DNS_IPV6_ADDR: /* --dns-ipv6-addr */
-      if(!curlinfo->ares_num) /* c-ares is needed for this */
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        /* addr in dot notation */
-        err = getstr(&config->dns_ipv6_addr, nextarg, DENY_BLANK);
-      break;
-    case C_OAUTH2_BEARER: /* --oauth2-bearer */
-      err = getstr(&config->oauth_bearer, nextarg, DENY_BLANK);
-      if(!err) {
-        cleanarg(clearthis);
-        config->authtype |= CURLAUTH_BEARER;
-      }
-      break;
-    case C_CONNECT_TIMEOUT: /* --connect-timeout */
-      err = secs2ms(&config->connecttimeout_ms, nextarg);
-      break;
-    case C_DOH_URL: /* --doh-url */
-      err = getstr(&config->doh_url, nextarg, ALLOW_BLANK);
-      if(!err && config->doh_url && !config->doh_url[0])
-        /* if given a blank string, make it NULL again */
-        tool_safefree(config->doh_url);
-      break;
-    case C_CIPHERS: /* -- ciphers */
-      err = getstr(&config->cipher_list, nextarg, DENY_BLANK);
-      break;
-    case C_DNS_INTERFACE: /* --dns-interface */
-      if(!curlinfo->ares_num) /* c-ares is needed for this */
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        /* interface name */
-        err = getstr(&config->dns_interface, nextarg, DENY_BLANK);
-      break;
-    case C_DISABLE_EPSV: /* --disable-epsv */
-      config->disable_epsv = toggle;
-      break;
-    case C_DISALLOW_USERNAME_IN_URL: /* --disallow-username-in-url */
-      config->disallow_username_in_url = toggle;
-      break;
-    case C_EPSV: /* --epsv */
-      config->disable_epsv = !toggle;
-      break;
-    case C_DNS_SERVERS: /* --dns-servers */
-      if(!curlinfo->ares_num) /* c-ares is needed for this */
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        /* IP addrs of DNS servers */
-        err = getstr(&config->dns_servers, nextarg, DENY_BLANK);
-      break;
-    case C_TRACE: /* --trace */
-      err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
-      if(!err) {
-        if(global->tracetype && (global->tracetype != TRACE_BIN))
-          warnf(global, "--trace overrides an earlier trace/verbose option");
-        global->tracetype = TRACE_BIN;
-      }
-      break;
-    case C_TRACE_ASCII: /* --trace-ascii */
-      err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
-      if(!err) {
-        if(global->tracetype && (global->tracetype != TRACE_ASCII))
-          warnf(global,
-                "--trace-ascii overrides an earlier trace/verbose option");
-        global->tracetype = TRACE_ASCII;
-      }
-      break;
-    case C_ALPN: /* --alpn */
-      config->noalpn = !toggle;
-      break;
-    case C_LIMIT_RATE: /* --limit-rate */
-      err = GetSizeParameter(global, nextarg, "rate", &value);
-      if(!err) {
-        config->recvpersecond = value;
-        config->sendpersecond = value;
-      }
-      break;
-    case C_RATE:
-      err = set_rate(global, nextarg);
-      break;
-    case C_COMPRESSED: /* --compressed */
-      if(toggle && !(feature_libz || feature_brotli || feature_zstd))
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        config->encoding = toggle;
-      break;
-    case C_TR_ENCODING: /* --tr-encoding */
-      config->tr_encoding = toggle;
-      break;
-    case C_DIGEST: /* --digest */
-      if(toggle)
-        config->authtype |= CURLAUTH_DIGEST;
-      else
-        config->authtype &= ~CURLAUTH_DIGEST;
-      break;
-    case C_NEGOTIATE: /* --negotiate */
-      if(!toggle)
-        config->authtype &= ~CURLAUTH_NEGOTIATE;
-      else if(feature_spnego)
-        config->authtype |= CURLAUTH_NEGOTIATE;
-      else
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      break;
-    case C_NTLM: /* --ntlm */
-      if(!toggle)
-        config->authtype &= ~CURLAUTH_NTLM;
-      else if(feature_ntlm)
-        config->authtype |= CURLAUTH_NTLM;
-      else
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      break;
-    case C_BASIC: /* --basic */
-      if(toggle)
-        config->authtype |= CURLAUTH_BASIC;
-      else
-        config->authtype &= ~CURLAUTH_BASIC;
-      break;
-    case C_ANYAUTH: /* --anyauth */
-      if(toggle)
-        config->authtype = CURLAUTH_ANY;
-      /* --no-anyauth simply does not touch it */
-      break;
-#ifdef USE_WATT32
-    case C_WDEBUG: /* --wdebug */
-      dbug_init();
-      break;
-#endif
-    case C_FTP_CREATE_DIRS: /* --ftp-create-dirs */
-      config->ftp_create_dirs = toggle;
-      break;
-    case C_CREATE_DIRS: /* --create-dirs */
-      config->create_dirs = toggle;
-      break;
-    case C_CREATE_FILE_MODE: /* --create-file-mode */
-      err = oct2nummax(&config->create_file_mode, nextarg, 0777);
-      break;
-    case C_MAX_REDIRS: /* --max-redirs */
-      /* specified max no of redirects (http(s)), this accepts -1 as a
-         special condition */
-      err = str2num(&config->maxredirs, nextarg);
-      if(!err && (config->maxredirs < -1))
-        err = PARAM_BAD_NUMERIC;
-      break;
+    break;
+  case C_RATE:
+    err = set_rate(global, nextarg);
+    break;
+  case C_CREATE_FILE_MODE: /* --create-file-mode */
+    err = oct2nummax(&config->create_file_mode, nextarg, 0777);
+    break;
+  case C_MAX_REDIRS: /* --max-redirs */
+    /* specified max no of redirects (http(s)), this accepts -1 as a
+       special condition */
+    err = str2num(&config->maxredirs, nextarg);
+    if(!err && (config->maxredirs < -1))
+      err = PARAM_BAD_NUMERIC;
+    break;
 #ifndef CURL_DISABLE_IPFS
-    case C_IPFS_GATEWAY: /* --ipfs-gateway */
-      err = getstr(&config->ipfs_gateway, nextarg, DENY_BLANK);
-      break;
+  case C_IPFS_GATEWAY: /* --ipfs-gateway */
+    err = getstr(&config->ipfs_gateway, nextarg, DENY_BLANK);
+    break;
 #endif /* !CURL_DISABLE_IPFS */
-    case C_PROXY_NTLM: /* --proxy-ntlm */
-      if(!feature_ntlm)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        config->proxyntlm = toggle;
-      break;
-    case C_CRLF: /* --crlf */
-      /* LF -> CRLF conversion? */
-      config->crlf = toggle;
-      break;
-    case C_AWS_SIGV4: /* --aws-sigv4 */
-      config->authtype |= CURLAUTH_AWS_SIGV4;
-      err = getstr(&config->aws_sigv4, nextarg, ALLOW_BLANK);
-      break;
-    case C_STDERR: /* --stderr */
-      tool_set_stderr_file(global, nextarg);
-      break;
-    case C_INTERFACE: /* --interface */
-      /* interface */
-      err = getstr(&config->iface, nextarg, DENY_BLANK);
-      break;
-    case C_KRB: /* --krb */
-      /* kerberos level string */
-      if(!feature_spnego)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->krblevel, nextarg, DENY_BLANK);
-      break;
-    case C_HAPROXY_PROTOCOL: /* --haproxy-protocol */
-      config->haproxy_protocol = toggle;
-      break;
-    case C_HAPROXY_CLIENTIP: /* --haproxy-clientip */
-      err = getstr(&config->haproxy_clientip, nextarg, DENY_BLANK);
-      break;
-    case C_MAX_FILESIZE: /* --max-filesize */
-      err = GetSizeParameter(global, nextarg, "max-filesize", &value);
-      if(!err)
-        config->max_filesize = value;
-      break;
-    case C_DISABLE_EPRT: /* --disable-eprt */
-      config->disable_eprt = toggle;
-      break;
-    case C_EPRT: /* --eprt */
-      config->disable_eprt = !toggle;
-      break;
-    case C_XATTR: /* --xattr */
-      config->xattr = toggle;
-      break;
-    case C_URL: /* --url */
-      err = parse_url(global, config, nextarg);
-      break;
-    case C_FTP_SSL: /* --ftp-ssl */
-    case C_SSL: /* --ssl */
-      config->ftp_ssl = toggle;
-      if(config->ftp_ssl)
-        warnf(global,
-              "--%s is an insecure option, consider --ssl-reqd instead",
-              a->lname);
-      break;
-    case C_FTP_PASV: /* --ftp-pasv */
-      tool_safefree(config->ftpport);
-      break;
-    case C_SOCKS5: /* --socks5 */
-      /*  socks5 proxy to use, and resolves the name locally and passes on the
-          resolved address */
-      err = getstr(&config->proxy, nextarg, DENY_BLANK);
-      config->proxyver = CURLPROXY_SOCKS5;
-      break;
-    case C_SOCKS4: /* --socks4 */
-      err = getstr(&config->proxy, nextarg, DENY_BLANK);
-      config->proxyver = CURLPROXY_SOCKS4;
-      break;
-    case C_SOCKS4A: /* --socks4a */
-      err = getstr(&config->proxy, nextarg, DENY_BLANK);
-      config->proxyver = CURLPROXY_SOCKS4A;
-      break;
-    case C_SOCKS5_HOSTNAME: /* --socks5-hostname */
-      err = getstr(&config->proxy, nextarg, DENY_BLANK);
-      config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
-      break;
-    case C_TCP_NODELAY: /* --tcp-nodelay */
-      config->tcp_nodelay = toggle;
-      break;
-    case C_IP_TOS: { /* --ip-tos */
-      struct TOSEntry find;
-      const struct TOSEntry *entry;
-      find.name = nextarg;
-      entry = bsearch(&find, tos_entries,
-                      CURL_ARRAYSIZE(tos_entries),
-                      sizeof(*tos_entries), find_tos);
-      if(entry)
-        config->ip_tos = entry->value;
-      else /* numeric tos value */
-        err = str2unummax(&config->ip_tos, nextarg, 0xFF);
-      break;
-    }
-    case C_VLAN_PRIORITY: /* --vlan-priority */
-      err = str2unummax(&config->vlan_priority, nextarg, 7);
-      break;
-    case C_PROXY_DIGEST: /* --proxy-digest */
-      config->proxydigest = toggle;
-      break;
-    case C_PROXY_BASIC: /* --proxy-basic */
-      config->proxybasic = toggle;
-      break;
-    case C_RETRY: /* --retry */
-      err = str2unum(&config->req_retry, nextarg);
-      break;
-    case C_RETRY_CONNREFUSED: /* --retry-connrefused */
-      config->retry_connrefused = toggle;
-      break;
-    case C_RETRY_DELAY: /* --retry-delay */
-      err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
-      break;
-    case C_RETRY_MAX_TIME: /* --retry-max-time */
-      err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
-      break;
-    case C_RETRY_ALL_ERRORS: /* --retry-all-errors */
-      config->retry_all_errors = toggle;
-      break;
-    case C_PROXY_NEGOTIATE: /* --proxy-negotiate */
-      if(!feature_spnego)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        config->proxynegotiate = toggle;
-      break;
-    case C_FORM_ESCAPE: /* --form-escape */
-      config->mime_options &= ~CURLMIMEOPT_FORMESCAPE;
-      if(toggle)
-        config->mime_options |= CURLMIMEOPT_FORMESCAPE;
-      break;
-    case C_FTP_ACCOUNT: /* --ftp-account */
-      err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_ANYAUTH: /* --proxy-anyauth */
-      config->proxyanyauth = toggle;
-      break;
-    case C_TRACE_TIME: /* --trace-time */
-      global->tracetime = toggle;
-      break;
-    case C_IGNORE_CONTENT_LENGTH: /* --ignore-content-length */
-      config->ignorecl = toggle;
-      break;
-    case C_FTP_SKIP_PASV_IP: /* --ftp-skip-pasv-ip */
-      config->ftp_skip_ip = toggle;
-      break;
-    case C_FTP_METHOD: /* --ftp-method */
-      config->ftp_filemethod = ftpfilemethod(config, nextarg);
-      break;
-    case C_LOCAL_PORT: /* --local-port */
-      err = parse_localport(config, nextarg);
-      break;
-    case C_FTP_ALTERNATIVE_TO_USER: /* --ftp-alternative-to-user */
-      err = getstr(&config->ftp_alternative_to_user, nextarg, DENY_BLANK);
-      break;
-    case C_FTP_SSL_REQD: /* --ftp-ssl-reqd */
-    case C_SSL_REQD: /* --ssl-reqd */
-      config->ftp_ssl_reqd = toggle;
-      break;
-    case C_SESSIONID: /* --sessionid */
-      config->disable_sessionid = !toggle;
-      break;
-    case C_FTP_SSL_CONTROL: /* --ftp-ssl-control */
-      config->ftp_ssl_control = toggle;
-      break;
-    case C_FTP_SSL_CCC: /* --ftp-ssl-ccc */
-      config->ftp_ssl_ccc = toggle;
-      if(!config->ftp_ssl_ccc_mode)
-        config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
-      break;
-    case C_FTP_SSL_CCC_MODE: /* --ftp-ssl-ccc-mode */
-      config->ftp_ssl_ccc = TRUE;
-      config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
-      break;
-    case C_LIBCURL: /* --libcurl */
+  case C_AWS_SIGV4: /* --aws-sigv4 */
+    config->authtype |= CURLAUTH_AWS_SIGV4;
+    err = getstr(&config->aws_sigv4, nextarg, ALLOW_BLANK);
+    break;
+  case C_STDERR: /* --stderr */
+    tool_set_stderr_file(global, nextarg);
+    break;
+  case C_INTERFACE: /* --interface */
+    /* interface */
+    err = getstr(&config->iface, nextarg, DENY_BLANK);
+    break;
+  case C_KRB: /* --krb */
+    /* kerberos level string */
+    if(!feature_spnego)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->krblevel, nextarg, DENY_BLANK);
+    break;
+  case C_HAPROXY_CLIENTIP: /* --haproxy-clientip */
+    err = getstr(&config->haproxy_clientip, nextarg, DENY_BLANK);
+    break;
+  case C_MAX_FILESIZE: /* --max-filesize */
+    err = GetSizeParameter(global, nextarg, "max-filesize", &value);
+    if(!err)
+      config->max_filesize = value;
+    break;
+  case C_URL: /* --url */
+    err = parse_url(global, config, nextarg);
+    break;
+  case C_FTP_PASV: /* --ftp-pasv */
+    tool_safefree(config->ftpport);
+    break;
+  case C_SOCKS5: /* --socks5 */
+    /*  socks5 proxy to use, and resolves the name locally and passes on the
+        resolved address */
+    err = getstr(&config->proxy, nextarg, DENY_BLANK);
+    config->proxyver = CURLPROXY_SOCKS5;
+    break;
+  case C_SOCKS4: /* --socks4 */
+    err = getstr(&config->proxy, nextarg, DENY_BLANK);
+    config->proxyver = CURLPROXY_SOCKS4;
+    break;
+  case C_SOCKS4A: /* --socks4a */
+    err = getstr(&config->proxy, nextarg, DENY_BLANK);
+    config->proxyver = CURLPROXY_SOCKS4A;
+    break;
+  case C_SOCKS5_HOSTNAME: /* --socks5-hostname */
+    err = getstr(&config->proxy, nextarg, DENY_BLANK);
+    config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
+    break;
+  case C_IP_TOS: { /* --ip-tos */
+    struct TOSEntry find;
+    const struct TOSEntry *entry;
+    find.name = nextarg;
+    entry = bsearch(&find, tos_entries,
+                    CURL_ARRAYSIZE(tos_entries),
+                    sizeof(*tos_entries), find_tos);
+    if(entry)
+      config->ip_tos = entry->value;
+    else /* numeric tos value */
+      err = str2unummax(&config->ip_tos, nextarg, 0xFF);
+    break;
+  }
+  case C_VLAN_PRIORITY: /* --vlan-priority */
+    err = str2unummax(&config->vlan_priority, nextarg, 7);
+    break;
+  case C_RETRY: /* --retry */
+    err = str2unum(&config->req_retry, nextarg);
+    break;
+  case C_RETRY_DELAY: /* --retry-delay */
+    err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
+    break;
+  case C_RETRY_MAX_TIME: /* --retry-max-time */
+    err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
+    break;
+  case C_FTP_ACCOUNT: /* --ftp-account */
+    err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
+    break;
+  case C_FTP_METHOD: /* --ftp-method */
+    config->ftp_filemethod = ftpfilemethod(config, nextarg);
+    break;
+  case C_LOCAL_PORT: /* --local-port */
+    err = parse_localport(config, nextarg);
+    break;
+  case C_FTP_ALTERNATIVE_TO_USER: /* --ftp-alternative-to-user */
+    err = getstr(&config->ftp_alternative_to_user, nextarg, DENY_BLANK);
+    break;
+  case C_LIBCURL: /* --libcurl */
 #ifdef CURL_DISABLE_LIBCURL_OPTION
-      warnf(global,
-            "--libcurl option was disabled at build-time");
-      err = PARAM_OPTION_UNKNOWN;
+    warnf(global,
+          "--libcurl option was disabled at build-time");
+    err = PARAM_OPTION_UNKNOWN;
 #else
-      err = getstr(&global->libcurl, nextarg, DENY_BLANK);
+    err = getstr(&global->libcurl, nextarg, DENY_BLANK);
 #endif
-      break;
-    case C_RAW: /* --raw */
-      config->raw = toggle;
-      break;
-    case C_KEEPALIVE: /* --keepalive */
-      config->nokeepalive = !toggle;
-      break;
-    case C_KEEPALIVE_TIME: /* --keepalive-time */
-      err = str2unum(&config->alivetime, nextarg);
-      break;
-    case C_KEEPALIVE_CNT: /* --keepalive-cnt */
-      err = str2unum(&config->alivecnt, nextarg);
-      break;
-    case C_POST301: /* --post301 */
-      config->post301 = toggle;
-      break;
-    case C_POST302: /* --post302 */
-      config->post302 = toggle;
-      break;
-    case C_POST303: /* --post303 */
-      config->post303 = toggle;
-      break;
-    case C_NOPROXY: /* --noproxy */
-      /* This specifies the noproxy list */
-      err = getstr(&config->noproxy, nextarg, ALLOW_BLANK);
-      break;
-    case C_SOCKS5_GSSAPI_NEC: /* --socks5-gssapi-nec */
-      config->socks5_gssapi_nec = toggle;
-      break;
-    case C_PROXY1_0: /* --proxy1.0 */
-      /* http 1.0 proxy */
-      err = getstr(&config->proxy, nextarg, DENY_BLANK);
-      config->proxyver = CURLPROXY_HTTP_1_0;
-      break;
-    case C_TFTP_BLKSIZE: /* --tftp-blksize */
-      err = str2unum(&config->tftp_blksize, nextarg);
-      break;
-    case C_MAIL_FROM: /* --mail-from */
-      err = getstr(&config->mail_from, nextarg, DENY_BLANK);
-      break;
-    case C_MAIL_RCPT: /* --mail-rcpt */
-      /* append receiver to a list */
-      err = add2list(&config->mail_rcpt, nextarg);
-      break;
-    case C_FTP_PRET: /* --ftp-pret */
-      config->ftp_pret = toggle;
-      break;
-    case C_PROTO: /* --proto */
-      config->proto_present = TRUE;
-      err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
-      break;
-    case C_PROTO_REDIR: /* --proto-redir */
-      config->proto_redir_present = TRUE;
-      if(proto2num(config, redir_protos, &config->proto_redir_str,
-                   nextarg))
-        err = PARAM_BAD_USE;
-      break;
-    case C_RESOLVE: /* --resolve */
-      err = add2list(&config->resolve, nextarg);
-      break;
-    case C_DELEGATION: /* --delegation */
-      config->gssapi_delegation = delegation(config, nextarg);
-      break;
-    case C_MAIL_AUTH: /* --mail-auth */
-      err = getstr(&config->mail_auth, nextarg, DENY_BLANK);
-      break;
-    case C_METALINK: /* --metalink */
-      errorf(global, "--metalink is disabled");
+    break;
+  case C_KEEPALIVE_TIME: /* --keepalive-time */
+    err = str2unum(&config->alivetime, nextarg);
+    break;
+  case C_KEEPALIVE_CNT: /* --keepalive-cnt */
+    err = str2unum(&config->alivecnt, nextarg);
+    break;
+  case C_NOPROXY: /* --noproxy */
+    /* This specifies the noproxy list */
+    err = getstr(&config->noproxy, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY1_0: /* --proxy1.0 */
+    /* http 1.0 proxy */
+    err = getstr(&config->proxy, nextarg, DENY_BLANK);
+    config->proxyver = CURLPROXY_HTTP_1_0;
+    break;
+  case C_TFTP_BLKSIZE: /* --tftp-blksize */
+    err = str2unum(&config->tftp_blksize, nextarg);
+    break;
+  case C_MAIL_FROM: /* --mail-from */
+    err = getstr(&config->mail_from, nextarg, DENY_BLANK);
+    break;
+  case C_MAIL_RCPT: /* --mail-rcpt */
+    /* append receiver to a list */
+    err = add2list(&config->mail_rcpt, nextarg);
+    break;
+  case C_PROTO: /* --proto */
+    config->proto_present = TRUE;
+    err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
+    break;
+  case C_PROTO_REDIR: /* --proto-redir */
+    config->proto_redir_present = TRUE;
+    if(proto2num(config, redir_protos, &config->proto_redir_str,
+                 nextarg))
       err = PARAM_BAD_USE;
+    break;
+  case C_RESOLVE: /* --resolve */
+    err = add2list(&config->resolve, nextarg);
+    break;
+  case C_DELEGATION: /* --delegation */
+    config->gssapi_delegation = delegation(config, nextarg);
+    break;
+  case C_MAIL_AUTH: /* --mail-auth */
+    err = getstr(&config->mail_auth, nextarg, DENY_BLANK);
+    break;
+  case C_SASL_AUTHZID: /* --sasl-authzid */
+    err = getstr(&config->sasl_authzid, nextarg, DENY_BLANK);
+    break;
+  case C_UNIX_SOCKET: /* --unix-socket */
+    config->abstract_unix_socket = FALSE;
+    err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_SERVICE_NAME: /* --proxy-service-name */
+    err = getstr(&config->proxy_service_name, nextarg, DENY_BLANK);
+    break;
+  case C_SERVICE_NAME: /* --service-name */
+    err = getstr(&config->service_name, nextarg, DENY_BLANK);
+    break;
+  case C_PROTO_DEFAULT: /* --proto-default */
+    err = getstr(&config->proto_default, nextarg, DENY_BLANK);
+    if(!err)
+      err = check_protocol(config->proto_default);
+    break;
+  case C_EXPECT100_TIMEOUT: /* --expect100-timeout */
+    err = secs2ms(&config->expect100timeout_ms, nextarg);
+    break;
+  case C_CONNECT_TO: /* --connect-to */
+    err = add2list(&config->connect_to, nextarg);
+    break;
+  case C_ABSTRACT_UNIX_SOCKET: /* --abstract-unix-socket */
+    config->abstract_unix_socket = TRUE;
+    err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
+    break;
+  case C_TLS_MAX: /* --tls-max */
+    err = str2tls_max(&config->ssl_version_max, nextarg);
+    break;
+  case C_HAPPY_EYEBALLS_TIMEOUT_MS: /* --happy-eyeballs-timeout-ms */
+    err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
+    /* 0 is a valid value for this timeout */
+    break;
+  case C_TRACE_CONFIG: /* --trace-config */
+    if(set_trace_config(global, nextarg))
+      err = PARAM_NO_MEM;
+    break;
+  case C_VARIABLE: /* --variable */
+    err = setvariable(global, nextarg);
+    break;
+  case C_TLS13_CIPHERS: /* --tls13-ciphers */
+    err = getstr(&config->cipher13_list, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_TLS13_CIPHERS: /* --proxy-tls13-ciphers */
+    err = getstr(&config->proxy_cipher13_list, nextarg, DENY_BLANK);
+    break;
+  case C_USER_AGENT: /* --user-agent */
+    err = getstr(&config->useragent, nextarg, ALLOW_BLANK);
+    break;
+  case C_ALT_SVC: /* --alt-svc */
+    if(!feature_altsvc)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->altsvc, nextarg, ALLOW_BLANK);
+    break;
+  case C_HSTS: /* --hsts */
+    if(!feature_hsts)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
+    break;
+  case C_COOKIE: /* --cookie */
+    if(strchr(nextarg, '=')) {
+      /* A cookie string must have a =-letter */
+      err = add2list(&config->cookies, nextarg);
       break;
-    case C_SASL_AUTHZID: /* --sasl-authzid */
-      err = getstr(&config->sasl_authzid, nextarg, DENY_BLANK);
-      break;
-    case C_SASL_IR: /* --sasl-ir */
-      config->sasl_ir = toggle;
-      break;
-#ifdef DEBUGBUILD
-    case C_TEST_DUPHANDLE: /* --test-duphandle */
-      global->test_duphandle = toggle;
-      break;
-    case C_TEST_EVENT: /* --test-event */
-      global->test_event_based = toggle;
-      break;
-#endif
-    case C_UNIX_SOCKET: /* --unix-socket */
-      config->abstract_unix_socket = FALSE;
-      err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
-      break;
-    case C_PATH_AS_IS: /* --path-as-is */
-      config->path_as_is = toggle;
-      break;
-    case C_PROXY_SERVICE_NAME: /* --proxy-service-name */
-      err = getstr(&config->proxy_service_name, nextarg, DENY_BLANK);
-      break;
-    case C_SERVICE_NAME: /* --service-name */
-      err = getstr(&config->service_name, nextarg, DENY_BLANK);
-      break;
-    case C_PROTO_DEFAULT: /* --proto-default */
-      err = getstr(&config->proto_default, nextarg, DENY_BLANK);
-      if(!err)
-        err = check_protocol(config->proto_default);
-      break;
-    case C_EXPECT100_TIMEOUT: /* --expect100-timeout */
-      err = secs2ms(&config->expect100timeout_ms, nextarg);
-      break;
-    case C_TFTP_NO_OPTIONS: /* --tftp-no-options */
-      config->tftp_no_options = toggle;
-      break;
-    case C_CONNECT_TO: /* --connect-to */
-      err = add2list(&config->connect_to, nextarg);
-      break;
-    case C_ABSTRACT_UNIX_SOCKET: /* --abstract-unix-socket */
-      config->abstract_unix_socket = TRUE;
-      err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
-      break;
-    case C_TLS_EARLYDATA: /* --tls-earlydata */
-      config->ssl_allow_earlydata = toggle;
-      break;
-    case C_TLS_MAX: /* --tls-max */
-      err = str2tls_max(&config->ssl_version_max, nextarg);
-      break;
-    case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
-      config->suppress_connect_headers = toggle;
-      break;
-    case C_COMPRESSED_SSH: /* --compressed-ssh */
-      config->ssh_compression = toggle;
-      break;
-    case C_HAPPY_EYEBALLS_TIMEOUT_MS: /* --happy-eyeballs-timeout-ms */
-      err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
-      /* 0 is a valid value for this timeout */
-      break;
-    case C_TRACE_IDS: /* --trace-ids */
-      global->traceids = toggle;
-      break;
-    case C_TRACE_CONFIG: /* --trace-config */
-      if(set_trace_config(global, nextarg))
-        err = PARAM_NO_MEM;
-      break;
-    case C_PROGRESS_METER: /* --progress-meter */
-      global->noprogress = !toggle;
-      break;
-    case C_PROGRESS_BAR: /* --progress-bar */
-      global->progressmode = toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
-      break;
-    case C_VARIABLE: /* --variable */
-      err = setvariable(global, nextarg);
-      break;
-    case C_NEXT: /* --next */
-      err = PARAM_NEXT_OPERATION;
-      break;
-    case C_HTTP1_0: /* --http1.0 */
-      /* HTTP version 1.0 */
-      sethttpver(global, config, CURL_HTTP_VERSION_1_0);
-      break;
-    case C_HTTP1_1: /* --http1.1 */
-      /* HTTP version 1.1 */
-      sethttpver(global, config, CURL_HTTP_VERSION_1_1);
-      break;
-    case C_HTTP2: /* --http2 */
-      /* HTTP version 2.0 */
-      if(!feature_http2)
-        return PARAM_LIBCURL_DOESNT_SUPPORT;
-      sethttpver(global, config, CURL_HTTP_VERSION_2_0);
-      break;
-    case C_HTTP2_PRIOR_KNOWLEDGE: /* --http2-prior-knowledge */
-      /* HTTP version 2.0 over clean TCP */
-      if(!feature_http2)
-        return PARAM_LIBCURL_DOESNT_SUPPORT;
-      sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
-      break;
-    case C_HTTP3: /* --http3: */
-      /* Try HTTP/3, allow fallback */
-      if(!feature_http3)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        sethttpver(global, config, CURL_HTTP_VERSION_3);
-      break;
-    case C_HTTP3_ONLY: /* --http3-only */
-      /* Try HTTP/3 without fallback */
-      if(!feature_http3)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
-      break;
-    case C_HTTP0_9: /* --http0.9 */
-      /* Allow HTTP/0.9 responses! */
-      config->http09_allowed = toggle;
-      break;
-    case C_PROXY_HTTP2: /* --proxy-http2 */
-      if(!feature_httpsproxy || !feature_http2)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        config->proxyver = CURLPROXY_HTTPS2;
-      break;
-    case C_TLSV1: /* --tlsv1 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1;
-      break;
-    case C_TLSV1_0: /* --tlsv1.0 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1_0;
-      break;
-    case C_TLSV1_1: /* --tlsv1.1 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1_1;
-      break;
-    case C_TLSV1_2: /* --tlsv1.2 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1_2;
-      break;
-    case C_TLSV1_3: /* --tlsv1.3 */
-      config->ssl_version = CURL_SSLVERSION_TLSv1_3;
-      break;
-    case C_TLS13_CIPHERS: /* --tls13-ciphers */
-      err = getstr(&config->cipher13_list, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_TLS13_CIPHERS: /* --proxy-tls13-ciphers */
-      err = getstr(&config->proxy_cipher13_list, nextarg, DENY_BLANK);
-      break;
-    case C_IPV4: /* --ipv4 */
-      config->ip_version = CURL_IPRESOLVE_V4;
-      break;
-    case C_IPV6: /* --ipv6 */
-      config->ip_version = CURL_IPRESOLVE_V6;
-      break;
-    case C_APPEND: /* --append */
-      /* This makes the FTP sessions use APPE instead of STOR */
-      config->ftp_append = toggle;
-      break;
-    case C_USER_AGENT: /* --user-agent */
-      err = getstr(&config->useragent, nextarg, ALLOW_BLANK);
-      break;
-    case C_ALT_SVC: /* --alt-svc */
-      if(!feature_altsvc)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->altsvc, nextarg, ALLOW_BLANK);
-      break;
-    case C_HSTS: /* --hsts */
-      if(!feature_hsts)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
-      break;
-    case C_COOKIE: /* --cookie */
-      if(strchr(nextarg, '=')) {
-        /* A cookie string must have a =-letter */
-        err = add2list(&config->cookies, nextarg);
-        break;
-      }
-      else {
-        /* We have a cookie file to read from! */
-        err = add2list(&config->cookiefiles, nextarg);
-      }
-      break;
-    case C_USE_ASCII: /* --use-ascii */
-      config->use_ascii = toggle;
-      break;
-    case C_COOKIE_JAR: /* --cookie-jar */
-      err = getstr(&config->cookiejar, nextarg, DENY_BLANK);
-      break;
-    case C_CONTINUE_AT: /* --continue-at */
-      err = parse_continue_at(global, config, nextarg);
-      break;
-    case C_DATA: /* --data */
-    case C_DATA_ASCII:  /* --data-ascii */
-    case C_DATA_BINARY:  /* --data-binary */
-    case C_DATA_URLENCODE:  /* --data-urlencode */
-    case C_JSON:  /* --json */
-    case C_DATA_RAW:  /* --data-raw */
-      err = set_data(cmd, nextarg, global, config);
-      break;
-    case C_URL_QUERY:  /* --url-query */
-      err = url_query(nextarg, global, config);
-      break;
-    case C_DUMP_CA_EMBED: /* --dump-ca-embed */
-      err = PARAM_CA_EMBED_REQUESTED;
-      break;
-    case C_DUMP_HEADER: /* --dump-header */
-      err = getstr(&config->headerfile, nextarg, DENY_BLANK);
-      break;
-    case C_REFERER: { /* --referer */
-      const char *ptr = strstr(nextarg, ";auto");
-      size_t len;
-      if(ptr) {
-        /* Automatic referer requested, this may be combined with a
-           set initial one */
-        config->autoreferer = TRUE;
-        len = ptr - nextarg;
-      }
-      else {
-        config->autoreferer = FALSE;
-        len = strlen(nextarg);
-      }
-      ptr = len ? nextarg : NULL;
-      err = getstrn(&config->referer, ptr, len, ALLOW_BLANK);
     }
+    else {
+      /* We have a cookie file to read from! */
+      err = add2list(&config->cookiefiles, nextarg);
+    }
+    break;
+  case C_COOKIE_JAR: /* --cookie-jar */
+    err = getstr(&config->cookiejar, nextarg, DENY_BLANK);
+    break;
+  case C_CONTINUE_AT: /* --continue-at */
+    err = parse_continue_at(global, config, nextarg);
+    break;
+  case C_DATA: /* --data */
+  case C_DATA_ASCII:  /* --data-ascii */
+  case C_DATA_BINARY:  /* --data-binary */
+  case C_DATA_URLENCODE:  /* --data-urlencode */
+  case C_JSON:  /* --json */
+  case C_DATA_RAW:  /* --data-raw */
+    err = set_data((cmdline_t)a->cmd, nextarg, global, config);
+    break;
+  case C_URL_QUERY:  /* --url-query */
+    err = url_query(nextarg, global, config);
+    break;
+  case C_DUMP_HEADER: /* --dump-header */
+    err = getstr(&config->headerfile, nextarg, DENY_BLANK);
+    break;
+  case C_REFERER: { /* --referer */
+    size_t len = strlen(nextarg);
+    /* does it end with ;auto ? */
+    if(len >= 5 && !strcmp(";auto", &nextarg[len - 5])) {
+      /* Automatic referer requested, this may be combined with a set initial
+         one */
+      config->autoreferer = TRUE;
+      len -= 5;
+    }
+    else
+      config->autoreferer = FALSE;
+
+    if(len)
+      err = getstrn(&config->referer, nextarg, len, ALLOW_BLANK);
+    else
+      tool_safefree(config->referer);
+  }
+    break;
+  case C_CERT: /* --cert */
+    GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
+    break;
+  case C_CACERT: /* --cacert */
+    err = getstr(&config->cacert, nextarg, DENY_BLANK);
+    break;
+  case C_CERT_TYPE: /* --cert-type */
+    err = getstr(&config->cert_type, nextarg, DENY_BLANK);
+    break;
+  case C_KEY: /* --key */
+    err = getstr(&config->key, nextarg, DENY_BLANK);
+    break;
+  case C_KEY_TYPE: /* --key-type */
+    err = getstr(&config->key_type, nextarg, DENY_BLANK);
+    break;
+  case C_PASS: /* --pass */
+    err = getstr(&config->key_passwd, nextarg, DENY_BLANK);
+    break;
+  case C_ENGINE: /* --engine */
+    err = getstr(&config->engine, nextarg, DENY_BLANK);
+    if(!err &&
+       config->engine && !strcmp(config->engine, "list")) {
+      err = PARAM_ENGINES_REQUESTED;
+    }
+    break;
+  case C_ECH: /* --ech */
+    err = parse_ech(global, config, nextarg);
+    break;
+  case C_CAPATH: /* --capath */
+    err = getstr(&config->capath, nextarg, DENY_BLANK);
+    break;
+  case C_PUBKEY: /* --pubkey */
+    err = getstr(&config->pubkey, nextarg, DENY_BLANK);
+    break;
+  case C_HOSTPUBMD5: /* --hostpubmd5 */
+    err = getstr(&config->hostpubmd5, nextarg, DENY_BLANK);
+    if(!err) {
+      if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
+        err = PARAM_BAD_USE;
+    }
+    break;
+  case C_HOSTPUBSHA256: /* --hostpubsha256 */
+    if(!feature_libssh2)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->hostpubsha256, nextarg, DENY_BLANK);
+    break;
+  case C_CRLFILE: /* --crlfile */
+    err = getstr(&config->crlfile, nextarg, DENY_BLANK);
+    break;
+  case C_TLSUSER: /* --tlsuser */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->tls_username, nextarg, DENY_BLANK);
+    break;
+  case C_TLSPASSWORD: /* --tlspassword */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->tls_password, nextarg, ALLOW_BLANK);
+    break;
+  case C_TLSAUTHTYPE: /* --tlsauthtype */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else {
+      err = getstr(&config->tls_authtype, nextarg, DENY_BLANK);
+      if(!err && config->tls_authtype && strcmp(config->tls_authtype, "SRP"))
+        err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+    }
+    break;
+  case C_PINNEDPUBKEY: /* --pinnedpubkey */
+    err = getstr(&config->pinnedpubkey, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_PINNEDPUBKEY: /* --proxy-pinnedpubkey */
+    err = getstr(&config->proxy_pinnedpubkey, nextarg, DENY_BLANK);
+    break;
+  case C_SSL_SESSIONS: /* --ssl-sessions */
+    if(feature_ssls_export)
+      err = getstr(&global->ssl_sessions, nextarg, DENY_BLANK);
+    else
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    break;
+  case C_PROXY_TLSUSER: /* --proxy-tlsuser */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->proxy_tls_username, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY_TLSPASSWORD: /* --proxy-tlspassword */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else
+      err = getstr(&config->proxy_tls_password, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_TLSAUTHTYPE: /* --proxy-tlsauthtype */
+    if(!feature_tls_srp)
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
+    else {
+      err = getstr(&config->proxy_tls_authtype, nextarg, DENY_BLANK);
+      if(!err && config->proxy_tls_authtype &&
+         strcmp(config->proxy_tls_authtype, "SRP"))
+        err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+    }
+    break;
+  case C_PROXY_CERT: /* --proxy-cert */
+    GetFileAndPassword(nextarg, &config->proxy_cert,
+                       &config->proxy_key_passwd);
+    break;
+  case C_PROXY_CERT_TYPE: /* --proxy-cert-type */
+    err = getstr(&config->proxy_cert_type, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_KEY: /* --proxy-key */
+    err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY_KEY_TYPE: /* --proxy-key-type */
+    err = getstr(&config->proxy_key_type, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_PASS: /* --proxy-pass */
+    err = getstr(&config->proxy_key_passwd, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY_CIPHERS: /* --proxy-ciphers */
+    err = getstr(&config->proxy_cipher_list, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_CRLFILE: /* --proxy-crlfile */
+    err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
+    break;
+  case C_LOGIN_OPTIONS: /* --login-options */
+    err = getstr(&config->login_options, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY_CACERT: /* --proxy-cacert */
+    err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY_CAPATH: /* --proxy-capath */
+    err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
+    break;
+  case C_ETAG_SAVE: /* --etag-save */
+    if(config->num_urls > 1) {
+      errorf(global, "The etag options only work on a single URL");
+      err = PARAM_BAD_USE;
+    }
+    else
+      err = getstr(&config->etag_save_file, nextarg, DENY_BLANK);
+    break;
+  case C_ETAG_COMPARE: /* --etag-compare */
+    if(config->num_urls > 1) {
+      errorf(global, "The etag options only work on a single URL");
+      err = PARAM_BAD_USE;
+    }
+    else
+      err = getstr(&config->etag_compare_file, nextarg, DENY_BLANK);
+    break;
+  case C_CURVES: /* --curves */
+    err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
+    break;
+  case C_SIGNATURE_ALGORITHMS: /* --sigalgs */
+    err = getstr(&config->ssl_signature_algorithms, nextarg, DENY_BLANK);
+    break;
+  case C_FORM: /* --form */
+  case C_FORM_STRING: /* --form-string */
+    /* "form data" simulation, this is a little advanced so lets do our best
+       to sort this out slowly and carefully */
+    if(formparse(config,
+                 nextarg,
+                 &config->mimeroot,
+                 &config->mimecurrent,
+                 (a->cmd == C_FORM_STRING))) /* literal string */
+      err = PARAM_BAD_USE;
+    else if(SetHTTPrequest(config, TOOL_HTTPREQ_MIMEPOST, &config->httpreq))
+      err = PARAM_BAD_USE;
+    break;
+  case C_REQUEST_TARGET: /* --request-target */
+    err = getstr(&config->request_target, nextarg, DENY_BLANK);
+    break;
+  case C_HEADER: /* --header */
+  case C_PROXY_HEADER: /* --proxy-header */
+    err = parse_header(global, config, (cmdline_t)a->cmd, nextarg);
+    break;
+  case C_CONFIG: /* --config */
+    if(parseconfig(nextarg, global)) {
+      errorf(global, "cannot read config from '%s'", nextarg);
+      err = PARAM_READ_ERROR;
+    }
+    break;
+  case C_MAX_TIME: /* --max-time */
+    /* specified max time */
+    err = secs2ms(&config->timeout_ms, nextarg);
+    break;
+  case C_NETRC_FILE: /* --netrc-file */
+    err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
+    break;
+  case C_OUTPUT_DIR: /* --output-dir */
+    err = getstr(&config->output_dir, nextarg, DENY_BLANK);
+    break;
+  case C_OUTPUT: /* --output */
+    err = parse_output(config, nextarg);
+    break;
+  case C_FTP_PORT: /* --ftp-port */
+    /* This makes the FTP sessions use PORT instead of PASV */
+    /* use <eth0> or <192.168.10.10> style addresses. Anything except
+       this will make us try to get the "default" address.
+       NOTE: this is a changed behavior since the released 4.1!
+    */
+    err = getstr(&config->ftpport, nextarg, DENY_BLANK);
+    break;
+  case C_FTP_SSL_CCC_MODE: /* --ftp-ssl-ccc-mode */
+    config->ftp_ssl_ccc = TRUE;
+    config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
+    break;
+  case C_QUOTE: /* --quote */
+    err = parse_quote(config, nextarg);
+    break;
+  case C_RANGE: /* --range */
+    err = parse_range(global, config, nextarg);
+    break;
+  case C_TELNET_OPTION: /* --telnet-option */
+    /* Telnet options */
+    err = add2list(&config->telnet_options, nextarg);
+    break;
+  case C_UPLOAD_FILE: /* --upload-file */
+    err = parse_upload_file(config, nextarg);
+    break;
+  case C_USER: /* --user */
+    /* user:password  */
+    err = getstr(&config->userpwd, nextarg, ALLOW_BLANK);
+    break;
+  case C_PROXY_USER: /* --proxy-user */
+    /* Proxy user:password  */
+    err = getstr(&config->proxyuserpwd, nextarg, ALLOW_BLANK);
+    break;
+  case C_WRITE_OUT: /* --write-out */
+    err = parse_writeout(global, config, nextarg);
+    break;
+  case C_PREPROXY: /* --preproxy */
+    err = getstr(&config->preproxy, nextarg, DENY_BLANK);
+    break;
+  case C_PROXY: /* --proxy */
+    /* --proxy */
+    err = getstr(&config->proxy, nextarg, ALLOW_BLANK);
+    if(config->proxyver != CURLPROXY_HTTPS2)
+      config->proxyver = CURLPROXY_HTTP;
+    break;
+  case C_REQUEST: /* --request */
+    /* set custom request */
+    err = getstr(&config->customrequest, nextarg, DENY_BLANK);
+    break;
+  case C_SPEED_TIME: /* --speed-time */
+    /* low speed time */
+    err = str2unum(&config->low_speed_time, nextarg);
+    if(!err && !config->low_speed_limit)
+      config->low_speed_limit = 1;
+    break;
+  case C_SPEED_LIMIT: /* --speed-limit */
+    /* low speed limit */
+    err = str2unum(&config->low_speed_limit, nextarg);
+    if(!err && !config->low_speed_time)
+      config->low_speed_time = 30;
+    break;
+  case C_PARALLEL_MAX: {  /* --parallel-max */
+    long val;
+    err = str2unum(&val, nextarg);
+    if(err)
       break;
-    case C_CERT: /* --cert */
-      GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
-      cleanarg(clearthis);
-      break;
-    case C_CACERT: /* --cacert */
-      err = getstr(&config->cacert, nextarg, DENY_BLANK);
-      break;
-    case C_CA_NATIVE: /* --ca-native */
-      config->native_ca_store = toggle;
-      break;
-    case C_PROXY_CA_NATIVE: /* --proxy-ca-native */
-      config->proxy_native_ca_store = toggle;
-      break;
-    case C_CERT_TYPE: /* --cert-type */
-      err = getstr(&config->cert_type, nextarg, DENY_BLANK);
-      break;
-    case C_KEY: /* --key */
-      err = getstr(&config->key, nextarg, DENY_BLANK);
-      break;
-    case C_KEY_TYPE: /* --key-type */
-      err = getstr(&config->key_type, nextarg, DENY_BLANK);
-      break;
-    case C_PASS: /* --pass */
-      err = getstr(&config->key_passwd, nextarg, DENY_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_ENGINE: /* --engine */
-      err = getstr(&config->engine, nextarg, DENY_BLANK);
-      if(!err &&
-         config->engine && !strcmp(config->engine, "list")) {
-        err = PARAM_ENGINES_REQUESTED;
-      }
-      break;
-    case C_ECH: /* --ech */
-      err = parse_ech(global, config, nextarg);
-      break;
-    case C_CAPATH: /* --capath */
-      err = getstr(&config->capath, nextarg, DENY_BLANK);
-      break;
-    case C_PUBKEY: /* --pubkey */
-      err = getstr(&config->pubkey, nextarg, DENY_BLANK);
-      break;
-    case C_HOSTPUBMD5: /* --hostpubmd5 */
-      err = getstr(&config->hostpubmd5, nextarg, DENY_BLANK);
-      if(!err) {
-        if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
-          err = PARAM_BAD_USE;
-      }
-      break;
-    case C_HOSTPUBSHA256: /* --hostpubsha256 */
-      if(!feature_libssh2)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->hostpubsha256, nextarg, DENY_BLANK);
-      break;
-    case C_CRLFILE: /* --crlfile */
-      err = getstr(&config->crlfile, nextarg, DENY_BLANK);
-      break;
-    case C_TLSUSER: /* --tlsuser */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->tls_username, nextarg, DENY_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_TLSPASSWORD: /* --tlspassword */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->tls_password, nextarg, ALLOW_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_TLSAUTHTYPE: /* --tlsauthtype */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else {
-        err = getstr(&config->tls_authtype, nextarg, DENY_BLANK);
-        if(!err && strcmp(config->tls_authtype, "SRP"))
-          err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
-      }
-      break;
-    case C_SSL_ALLOW_BEAST: /* --ssl-allow-beast */
-      config->ssl_allow_beast = toggle;
-      break;
-    case C_SSL_AUTO_CLIENT_CERT: /* --ssl-auto-client-cert */
-      config->ssl_auto_client_cert = toggle;
-      break;
-    case C_PROXY_SSL_AUTO_CLIENT_CERT: /* --proxy-ssl-auto-client-cert */
-      config->proxy_ssl_auto_client_cert = toggle;
-      break;
-    case C_PINNEDPUBKEY: /* --pinnedpubkey */
-      err = getstr(&config->pinnedpubkey, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_PINNEDPUBKEY: /* --proxy-pinnedpubkey */
-      err = getstr(&config->proxy_pinnedpubkey, nextarg, DENY_BLANK);
-      break;
-    case C_CERT_STATUS: /* --cert-status */
-      config->verifystatus = TRUE;
-      break;
-    case C_DOH_CERT_STATUS: /* --doh-cert-status */
-      config->doh_verifystatus = TRUE;
-      break;
-    case C_FALSE_START: /* --false-start */
-      config->falsestart = TRUE;
-      break;
-    case C_SSL_NO_REVOKE: /* --ssl-no-revoke */
-      config->ssl_no_revoke = TRUE;
-      break;
-    case C_SSL_REVOKE_BEST_EFFORT: /* --ssl-revoke-best-effort */
-      config->ssl_revoke_best_effort = TRUE;
-      break;
-    case C_SSL_SESSIONS: /* --ssl-sessions */
-      if(feature_ssls_export)
-        err = getstr(&global->ssl_sessions, nextarg, DENY_BLANK);
-      else
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      break;
-    case C_TCP_FASTOPEN: /* --tcp-fastopen */
-      config->tcp_fastopen = TRUE;
-      break;
-    case C_PROXY_TLSUSER: /* --proxy-tlsuser */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->proxy_tls_username, nextarg, ALLOW_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_PROXY_TLSPASSWORD: /* --proxy-tlspassword */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else
-        err = getstr(&config->proxy_tls_password, nextarg, DENY_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_PROXY_TLSAUTHTYPE: /* --proxy-tlsauthtype */
-      if(!feature_tls_srp)
-        err = PARAM_LIBCURL_DOESNT_SUPPORT;
-      else {
-        err = getstr(&config->proxy_tls_authtype, nextarg, DENY_BLANK);
-        if(!err && strcmp(config->proxy_tls_authtype, "SRP"))
-          err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
-      }
-      break;
-    case C_PROXY_CERT: /* --proxy-cert */
-      GetFileAndPassword(nextarg, &config->proxy_cert,
-                         &config->proxy_key_passwd);
-      cleanarg(clearthis);
-      break;
-    case C_PROXY_CERT_TYPE: /* --proxy-cert-type */
-      err = getstr(&config->proxy_cert_type, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_KEY: /* --proxy-key */
-      err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
-      break;
-    case C_PROXY_KEY_TYPE: /* --proxy-key-type */
-      err = getstr(&config->proxy_key_type, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_PASS: /* --proxy-pass */
-      err = getstr(&config->proxy_key_passwd, nextarg, ALLOW_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_PROXY_CIPHERS: /* --proxy-ciphers */
-      err = getstr(&config->proxy_cipher_list, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_CRLFILE: /* --proxy-crlfile */
-      err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_SSL_ALLOW_BEAST: /* --proxy-ssl-allow-beast */
-      config->proxy_ssl_allow_beast = toggle;
-      break;
-    case C_LOGIN_OPTIONS: /* --login-options */
-      err = getstr(&config->login_options, nextarg, ALLOW_BLANK);
-      break;
-    case C_PROXY_CACERT: /* --proxy-cacert */
-      err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_CAPATH: /* --proxy-capath */
-      err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY_INSECURE: /* --proxy-insecure */
-      config->proxy_insecure_ok = toggle;
-      break;
-    case C_PROXY_TLSV1: /* --proxy-tlsv1 */
-      /* TLS version 1 for proxy */
-      config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
-      break;
-    case C_SOCKS5_BASIC: /* --socks5-basic */
-      if(toggle)
-        config->socks5_auth |= CURLAUTH_BASIC;
-      else
-        config->socks5_auth &= ~CURLAUTH_BASIC;
-      break;
-    case C_SOCKS5_GSSAPI: /* --socks5-gssapi */
-      if(toggle)
-        config->socks5_auth |= CURLAUTH_GSSAPI;
-      else
-        config->socks5_auth &= ~CURLAUTH_GSSAPI;
-      break;
-    case C_ETAG_SAVE: /* --etag-save */
-      if(config->num_urls > 1) {
-        errorf(global, "The etag options only work on a single URL");
-        err = PARAM_BAD_USE;
+    if(val > MAX_PARALLEL)
+      global->parallel_max = MAX_PARALLEL;
+    else if(val < 1)
+      global->parallel_max = PARALLEL_DEFAULT;
+    else
+      global->parallel_max = (unsigned short)val;
+    break;
+  }
+  case C_TIME_COND: /* --time-cond */
+    err = parse_time_cond(global, config, nextarg);
+    break;
+  case C_UPLOAD_FLAGS: /* --upload-flags */
+    err = parse_upload_flags(config, nextarg);
+    break;
+  }
+  return err;
+}
+
+ParameterError getparameter(const char *flag, /* f or -long-flag */
+                            const char *nextarg,    /* NULL if unset */
+                            bool *usedarg,    /* set to TRUE if the arg
+                                                 has been used */
+                            struct GlobalConfig *global,
+                            struct OperationConfig *config)
+{
+  const char *parse = NULL;
+  bool longopt = FALSE;
+  bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
+  ParameterError err = PARAM_OK;
+  bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
+                         by using --OPTION or --no-OPTION */
+  bool nextalloc = FALSE; /* if nextarg is allocated */
+  const struct LongShort *a = NULL;
+  verbose_nopts = 0; /* options processed in `flag`*/
+
+  *usedarg = FALSE; /* default is that we do not use the arg */
+
+  if(('-' != flag[0]) || ('-' == flag[1])) {
+    /* this should be a long name */
+    const char *word = ('-' == flag[0]) ? flag + 2 : flag;
+    bool noflagged = FALSE;
+    bool expand = FALSE;
+
+    if(!strncmp(word, "no-", 3)) {
+      /* disable this option but ignore the "no-" part when looking for it */
+      word += 3;
+      toggle = FALSE;
+      noflagged = TRUE;
+    }
+    else if(!strncmp(word, "expand-", 7)) {
+      /* variable expansions is to be done on the argument */
+      word += 7;
+      expand = TRUE;
+    }
+
+    a = findlongopt(word);
+    if(a) {
+      longopt = TRUE;
+    }
+    else {
+      err = PARAM_OPTION_UNKNOWN;
+      goto error;
+    }
+    if(noflagged && (ARGTYPE(a->desc) != ARG_BOOL)) {
+      /* --no- prefixed an option that is not boolean! */
+      err = PARAM_NO_PREFIX;
+      goto error;
+    }
+    else if(expand && nextarg) {
+      struct dynbuf nbuf;
+      bool replaced;
+
+      if((ARGTYPE(a->desc) != ARG_STRG) &&
+         (ARGTYPE(a->desc) != ARG_FILE)) {
+        /* --expand on an option that is not a string or a filename */
+        err = PARAM_EXPAND_ERROR;
+        goto error;
       }
-      else
-        err = getstr(&config->etag_save_file, nextarg, DENY_BLANK);
-      break;
-    case C_ETAG_COMPARE: /* --etag-compare */
-      if(config->num_urls > 1) {
-        errorf(global, "The etag options only work on a single URL");
-        err = PARAM_BAD_USE;
+      err = varexpand(global, nextarg, &nbuf, &replaced);
+      if(err) {
+        curlx_dyn_free(&nbuf);
+        goto error;
       }
-      else
-        err = getstr(&config->etag_compare_file, nextarg, DENY_BLANK);
-      break;
-    case C_CURVES: /* --curves */
-      err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
-      break;
-    case C_SIGNATURE_ALGORITHMS: /* --sigalgs */
-      err = getstr(&config->ssl_signature_algorithms, nextarg, DENY_BLANK);
-      break;
-    case C_FAIL_EARLY: /* --fail-early */
-      global->fail_early = toggle;
-      break;
-    case C_STYLED_OUTPUT: /* --styled-output */
-      global->styled_output = toggle;
-      break;
-    case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
-      config->mail_rcpt_allowfails = toggle;
-      break;
-    case C_FAIL_WITH_BODY: /* --fail-with-body */
-      config->failwithbody = toggle;
-      if(config->failonerror && config->failwithbody) {
-        errorf(config->global, "You must select either --fail or "
-               "--fail-with-body, not both.");
-        err = PARAM_BAD_USE;
+      if(replaced) {
+        nextarg = curlx_dyn_ptr(&nbuf);
+        nextalloc = TRUE;
       }
-      break;
-    case C_REMOVE_ON_ERROR: /* --remove-on-error */
-      if(config->use_resume && toggle) {
-        errorf(config->global,
-               "--continue-at is mutually exclusive with --remove-on-error");
-        return PARAM_BAD_USE;
+    }
+  }
+  else {
+    flag++; /* prefixed with one dash, pass it */
+    parse = flag;
+  }
+
+  do {
+    /* we can loop here if we have multiple single-letters */
+    if(!longopt) {
+      a = findshortopt(*parse);
+      if(!a) {
+        err = PARAM_OPTION_UNKNOWN;
+        break;
       }
-      config->rm_partial = toggle;
+    }
+    if((a->desc & ARG_TLS) && !feature_ssl) {
+      err = PARAM_LIBCURL_DOESNT_SUPPORT;
       break;
-    case C_FAIL: /* --fail */
-      config->failonerror = toggle;
-      if(config->failonerror && config->failwithbody) {
-        errorf(config->global, "You must select either --fail or "
-               "--fail-with-body, not both.");
-        err = PARAM_BAD_USE;
+    }
+    else if(ARGTYPE(a->desc) >= ARG_STRG) {
+      /* this option requires an extra parameter */
+      if(!longopt && parse[1]) {
+        nextarg = &parse[1]; /* this is the actual extra parameter */
+        singleopt = TRUE;   /* do not loop anymore after this */
       }
-      break;
-    case C_FORM: /* --form */
-    case C_FORM_STRING: /* --form-string */
-      /* "form data" simulation, this is a little advanced so lets do our best
-         to sort this out slowly and carefully */
-      if(formparse(config,
-                   nextarg,
-                   &config->mimeroot,
-                   &config->mimecurrent,
-                   (cmd == C_FORM_STRING))) /* literal string */
-        err = PARAM_BAD_USE;
-      else if(SetHTTPrequest(config, TOOL_HTTPREQ_MIMEPOST, &config->httpreq))
-        err = PARAM_BAD_USE;
-      break;
-    case C_GLOBOFF: /* --globoff */
-      config->globoff = toggle;
-      break;
-    case C_GET: /* --get */
-      config->use_httpget = toggle;
-      break;
-    case C_REQUEST_TARGET: /* --request-target */
-      err = getstr(&config->request_target, nextarg, DENY_BLANK);
-      break;
-    case C_HELP: /* --help */
-      if(toggle) {
+      else if(a->cmd == C_HELP) {
+        /* --help is special */
         tool_help((nextarg && *nextarg) ? nextarg : NULL);
         err = PARAM_HELP_REQUESTED;
+        break;
       }
-      /* we now actually support --no-help too! */
-      break;
-    case C_HEADER: /* --header */
-    case C_PROXY_HEADER: /* --proxy-header */
-      err = parse_header(global, config, cmd, nextarg);
-      break;
-    case C_INCLUDE: /* --include */
-    case C_SHOW_HEADERS: /* --show-headers */
-      config->show_headers = toggle; /* show the headers as well in the
-                                        general output stream */
-      break;
-    case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
-      config->cookiesession = toggle;
-      break;
-    case C_HEAD: /* --head */
-      config->no_body = toggle;
-      config->show_headers = toggle;
-      if(SetHTTPrequest(config, (config->no_body) ? TOOL_HTTPREQ_HEAD :
-                        TOOL_HTTPREQ_GET, &config->httpreq))
-        err = PARAM_BAD_USE;
-      break;
-    case C_REMOTE_HEADER_NAME: /* --remote-header-name */
-      config->content_disposition = toggle;
-      break;
-    case C_INSECURE: /* --insecure */
-      config->insecure_ok = toggle;
-      break;
-    case C_DOH_INSECURE: /* --doh-insecure */
-      config->doh_insecure_ok = toggle;
-      break;
-    case C_CONFIG: /* --config */
-      if(parseconfig(nextarg, global)) {
-        errorf(global, "cannot read config from '%s'", nextarg);
-        err = PARAM_READ_ERROR;
+      else if(!nextarg) {
+        err = PARAM_REQUIRES_PARAMETER;
+        break;
       }
-      break;
-    case C_LIST_ONLY: /* --list-only */
-      config->dirlistonly = toggle; /* only list the names of the FTP dir */
-      break;
-    case C_LOCATION_TRUSTED: /* --location-trusted */
-      /* Continue to send authentication (user+password) when following
-       * locations, even when hostname changed */
-      config->unrestricted_auth = toggle;
-      FALLTHROUGH();
-    case C_LOCATION: /* --location */
-      config->followlocation = toggle; /* Follow Location: HTTP headers */
-      break;
-    case C_MAX_TIME: /* --max-time */
-      /* specified max time */
-      err = secs2ms(&config->timeout_ms, nextarg);
-      break;
-    case C_MANUAL: /* --manual */
-      if(toggle) { /* --no-manual shows no manual... */
-        err = PARAM_MANUAL_REQUESTED;
+      else {
+        *usedarg = TRUE; /* mark it as used */
       }
-      break;
-    case C_NETRC_OPTIONAL: /* --netrc-optional */
-      config->netrc_opt = toggle;
-      break;
-    case C_NETRC_FILE: /* --netrc-file */
-      err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
-      break;
-    case C_NETRC: /* --netrc */
-      /* pick info from .netrc, if this is used for http, curl will
-         automatically enforce user+password with the request */
-      config->netrc = toggle;
-      break;
-    case C_BUFFER: /* --buffer */
-      /* disable the output I/O buffering. note that the option is called
-         --buffer but is mostly used in the negative form: --no-buffer */
-      config->nobuffer = (bool)(longopt ? !toggle : TRUE);
-      break;
-    case C_REMOTE_NAME_ALL: /* --remote-name-all */
-      config->remote_name_all = toggle;
-      break;
-    case C_OUTPUT_DIR: /* --output-dir */
-      err = getstr(&config->output_dir, nextarg, DENY_BLANK);
-      break;
-    case C_CLOBBER: /* --clobber */
-      if(config->use_resume && !toggle) {
-        errorf(config->global,
-               "--continue-at is mutually exclusive with --no-clobber");
-        return PARAM_BAD_USE;
+      if(a->desc & ARG_DEPR) {
+        opt_depr(global, a);
+        break;
       }
-      config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
-      break;
-    case C_OUTPUT: /* --output */
-      err = parse_output(config, nextarg);
-      break;
-    case C_REMOTE_NAME: /* --remote-name */
-      err = parse_remote_name(config, toggle);
-      break;
-    case C_FTP_PORT: /* --ftp-port */
-      /* This makes the FTP sessions use PORT instead of PASV */
-      /* use <eth0> or <192.168.10.10> style addresses. Anything except
-         this will make us try to get the "default" address.
-         NOTE: this is a changed behavior since the released 4.1!
-      */
-      err = getstr(&config->ftpport, nextarg, DENY_BLANK);
-      break;
-    case C_PROXYTUNNEL: /* --proxytunnel */
-      /* proxy tunnel for non-http protocols */
-      config->proxytunnel = toggle;
-      break;
 
-    case C_DISABLE: /* --disable */
-      /* if used first, already taken care of, we do it like this so we do not
-         cause an error! */
-      break;
-    case C_QUOTE: /* --quote */
-      err = parse_quote(config, nextarg);
-      break;
-    case C_RANGE: /* --range */
-      err = parse_range(global, config, nextarg);
-      break;
-    case C_REMOTE_TIME: /* --remote-time */
-      /* use remote file's time */
-      config->remote_time = toggle;
-      break;
-    case C_SILENT: /* --silent */
-      global->silent = toggle;
-      break;
-    case C_SKIP_EXISTING: /* --skip-existing */
-      config->skip_existing = toggle;
-      break;
-    case C_SHOW_ERROR: /* --show-error */
-      global->showerror = toggle;
-      break;
-    case C_TELNET_OPTION: /* --telnet-option */
-      /* Telnet options */
-      err = add2list(&config->telnet_options, nextarg);
-      break;
-    case C_UPLOAD_FILE: /* --upload-file */
-      err = parse_upload_file(config, nextarg);
-      break;
-    case C_USER: /* --user */
-      /* user:password  */
-      err = getstr(&config->userpwd, nextarg, ALLOW_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_PROXY_USER: /* --proxy-user */
-      /* Proxy user:password  */
-      err = getstr(&config->proxyuserpwd, nextarg, ALLOW_BLANK);
-      cleanarg(clearthis);
-      break;
-    case C_VERBOSE: /* --verbose */
-      err = parse_verbose(global, toggle, nopts);
-      break;
-    case C_VERSION: /* --version */
-      if(toggle)    /* --no-version yields no output! */
-        err = PARAM_VERSION_INFO_REQUESTED;
-      break;
-    case C_WRITE_OUT: /* --write-out */
-      err = parse_writeout(global, config, nextarg);
-      break;
-    case C_PREPROXY: /* --preproxy */
-      err = getstr(&config->preproxy, nextarg, DENY_BLANK);
-      break;
-    case C_PROXY: /* --proxy */
-      /* --proxy */
-      err = getstr(&config->proxy, nextarg, ALLOW_BLANK);
-      if(config->proxyver != CURLPROXY_HTTPS2)
-        config->proxyver = CURLPROXY_HTTP;
-      break;
-    case C_REQUEST: /* --request */
-      /* set custom request */
-      err = getstr(&config->customrequest, nextarg, DENY_BLANK);
-      break;
-    case C_SPEED_TIME: /* --speed-time */
-      /* low speed time */
-      err = str2unum(&config->low_speed_time, nextarg);
-      if(!err && !config->low_speed_limit)
-        config->low_speed_limit = 1;
-      break;
-    case C_SPEED_LIMIT: /* --speed-limit */
-      /* low speed limit */
-      err = str2unum(&config->low_speed_limit, nextarg);
-      if(!err && !config->low_speed_time)
-        config->low_speed_time = 30;
-      break;
-    case C_PARALLEL: /* --parallel */
-      global->parallel = toggle;
-      break;
-    case C_PARALLEL_MAX: {  /* --parallel-max */
-      long val;
-      err = str2unum(&val, nextarg);
-      if(err)
+      if((ARGTYPE(a->desc) == ARG_FILE) &&
+         (nextarg[0] == '-') && nextarg[1]) {
+        /* if the filename looks like a command line option */
+        warnf(global, "The filename argument '%s' looks like a flag.",
+              nextarg);
+      }
+      else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) {
+        warnf(global, "The argument '%s' starts with a Unicode quote where "
+              "maybe an ASCII \" was intended?",
+              nextarg);
+      }
+      /* ARG_FILE | ARG_STRG */
+      err = opt_filestring(global, config, a, nextarg);
+      if(a->desc & ARG_CLEAR)
+        cleanarg(CURL_UNCONST(nextarg));
+    }
+    else {
+      if(a->desc & ARG_DEPR) {
+        opt_depr(global, a);
         break;
-      if(val > MAX_PARALLEL)
-        global->parallel_max = MAX_PARALLEL;
-      else if(val < 1)
-        global->parallel_max = PARALLEL_DEFAULT;
+      }
+      /* ARG_NONE | ARG_BOOL */
+      if(ARGTYPE(a->desc) == ARG_BOOL)
+        err = opt_bool(global, config, a, toggle);
       else
-        global->parallel_max = (unsigned short)val;
-      break;
+        err = opt_none(global, config, a);
     }
-    case C_PARALLEL_IMMEDIATE:   /* --parallel-immediate */
-      global->parallel_connect = toggle;
-      break;
-    case C_TIME_COND: /* --time-cond */
-      err = parse_time_cond(global, config, nextarg);
-      break;
-    case C_MPTCP: /* --mptcp */
-      config->mptcp = TRUE;
-      break;
-    case C_UPLOAD_FLAGS: /* --upload-flags */
-      err = parse_upload_flags(config, nextarg);
-      break;
-    default: /* unknown flag */
-      err = PARAM_OPTION_UNKNOWN;
-      break;
-    }
-    a = NULL;
-    ++nopts; /* processed one option from `flag` input, loop for more */
+
+    ++verbose_nopts; /* processed one option from `flag` input, loop for
+                        more */
   } while(!longopt && !singleopt && *++parse && !*usedarg && !err);
 
 error:
@@ -3000,8 +2981,7 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
           }
         }
 
-        result = getparameter(orig_opt, nextarg, argv[i], argv[i + 1],
-                              &passarg, global, config);
+        result = getparameter(orig_opt, nextarg, &passarg, global, config);
 
         unicodefree(nextarg);
         config = global->last;
@@ -3043,8 +3023,7 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
       bool used;
 
       /* Just add the URL please */
-      result = getparameter("--url", orig_opt, NULL, NULL,
-                            &used, global, config);
+      result = getparameter("--url", orig_opt, &used, global, config);
     }
 
     if(!result) {
index b0f924816cff15d8be56a0beaa1b340980f8f26f..d84e85222571a3a40889bd89604e0aab61190145 100644 (file)
@@ -317,6 +317,8 @@ typedef enum {
 #define ARG_TYPEMASK 0x03
 #define ARGTYPE(x) ((x) & ARG_TYPEMASK)
 
+#define ARG_DEPR 0x10 /* deprecated option */
+#define ARG_CLEAR 0x20 /* clear cmdline argument */
 #define ARG_TLS 0x40 /* requires TLS support */
 #define ARG_NO 0x80 /* set if the option is documented as --no-* */
 
@@ -347,7 +349,6 @@ typedef enum {
   PARAM_NEXT_OPERATION,
   PARAM_NO_PREFIX,
   PARAM_NUMBER_TOO_LARGE,
-  PARAM_NO_NOT_BOOLEAN,
   PARAM_CONTDISP_RESUME_FROM, /* --continue-at and --remote-header-name */
   PARAM_READ_ERROR,
   PARAM_EXPAND_ERROR, /* --expand problem */
@@ -363,8 +364,6 @@ const struct LongShort *findlongopt(const char *opt);
 const struct LongShort *findshortopt(char letter);
 
 ParameterError getparameter(const char *flag, const char *nextarg,
-                            argv_item_t cleararg1,
-                            argv_item_t cleararg2,
                             bool *usedarg,
                             struct GlobalConfig *global,
                             struct OperationConfig *operation);
index b3bb09e68e4296ad44816c4d1e662d710e257821..5026fcf1c6701fbe27c18182549002d5755d31d3 100644 (file)
@@ -62,8 +62,6 @@ const char *param2text(ParameterError error)
     return "the given option cannot be reversed with a --no- prefix";
   case PARAM_NUMBER_TOO_LARGE:
     return "too large number";
-  case PARAM_NO_NOT_BOOLEAN:
-    return "used '--no-' for option that is not a boolean";
   case PARAM_CONTDISP_RESUME_FROM:
     return "--continue-at and --remote-header-name cannot be combined";
   case PARAM_READ_ERROR:
index 9ce734be6e75e6e0d7b3aa69424e8da43bf09978..0c59bdef785a81812132871f7ebd96b9135dff95 100644 (file)
@@ -172,8 +172,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
 #ifdef DEBUG_CONFIG
       fprintf(tool_stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
 #endif
-      res = getparameter(option, param, NULL, NULL,
-                         &usedarg, global, operation);
+      res = getparameter(option, param, &usedarg, global, operation);
       operation = global->last;
 
       if(!res && param && *param && !usedarg)