]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_getparam: add support for `--longopt=value`
authorDaniel Stenberg <daniel@haxx.se>
Mon, 30 Jun 2025 21:53:29 +0000 (23:53 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 27 Jul 2025 16:29:01 +0000 (18:29 +0200)
If the long option name ends with an equals sign (`=`), the argument is
the text following on its right side.

This makes the command line parser accept this common style in addition
to the existing way to accept option arguments more similar to how other
command line tools do.

Example: `curl --user-agent=curl-2000 https://example.com/`

Change a few existing tests to use this syntax: 206, 1333, 1335, 1442

Closes #17789

docs/cmdline-opts/_OPTIONS.md
src/tool_getparam.c
tests/data/test1333
tests/data/test1335
tests/data/test1442
tests/data/test206

index f1067377c8ddcbdd653c80e149fac853c329f855..2b7cb80f4999a144c9015461020b910e4bf6342b 100644 (file)
@@ -24,6 +24,9 @@ When --next is used, it resets the parser state and you start again with a
 clean option state, except for the options that are global. Global options
 retain their values and meaning even after --next.
 
+If the long option name ends with an equals sign (`=`), the argument is the
+text following on its right side. (Added in 8.16.0)
+
 The first argument that is exactly two dashes (`--`), marks the end of
 options; any argument after the end of options is interpreted as a URL
 argument even if it starts with a dash.
index 3a1cc57fdd3a5e9cb9d0344026e5820940110de9..c78494f76d6f226977c60ff0185a54249efd5ddf 100644 (file)
@@ -2803,6 +2803,9 @@ static ParameterError opt_filestring(struct OperationConfig *config,
   return err;
 }
 
+/* the longest command line option, excluding the leading -- */
+#define MAX_OPTION_LEN 26
+
 ParameterError getparameter(const char *flag, /* f or -long-flag */
                             const char *nextarg,    /* NULL if unset */
                             bool *usedarg,    /* set to TRUE if the arg
@@ -2816,6 +2819,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
   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 */
+  bool consumearg = TRUE; /* the argument comes separate */
   const struct LongShort *a = NULL;
   struct GlobalConfig *global = config->global;
   verbose_nopts = 0; /* options processed in `flag`*/
@@ -2827,6 +2831,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
     const char *word = ('-' == flag[0]) ? flag + 2 : flag;
     bool noflagged = FALSE;
     bool expand = FALSE;
+    const char *p;
+    struct Curl_str out;
 
     if(!strncmp(word, "no-", 3)) {
       /* disable this option but ignore the "no-" part when looking for it */
@@ -2840,7 +2846,21 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
       expand = TRUE;
     }
 
-    a = findlongopt(word);
+    p = word;
+    /* is there an '=' ? */
+    if(!curlx_str_until(&p, &out, MAX_OPTION_LEN, '=') &&
+       !curlx_str_single(&p, '=') ) {
+      /* there's an equal sign */
+      char tempword[MAX_OPTION_LEN + 1];
+      memcpy(tempword, curlx_str(&out), curlx_strlen(&out));
+      tempword[curlx_strlen(&out)] = 0;
+      a = findlongopt(tempword);
+      nextarg = p;
+      consumearg = FALSE; /* it is not separate */
+    }
+    else
+      a = findlongopt(word);
+
     if(a) {
       longopt = TRUE;
     }
@@ -2910,7 +2930,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
         break;
       }
       else {
-        *usedarg = TRUE; /* mark it as used */
+        *usedarg = consumearg; /* mark it as used */
       }
       if(a->desc & ARG_DEPR) {
         opt_depr(global, a);
index e6dbb73a62fff9a554a6cf7028580f67915dabbb..5a5dd63a2d9a5c6b4da59223014d01a116f562a8 100644 (file)
@@ -31,7 +31,7 @@ http
 HTTP POST zero length, chunked-encoded
 </name>
 <command>
--d "" --header "Transfer-Encoding: chunked" http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+-d "" --header="Transfer-Encoding: chunked" http://%HOSTIP:%HTTPPORT/%TESTNUMBER
 </command>
 </client>
 
index a0b3aae65ed96317016432b099fac35a88a07d2f..146ff6d91828df93447ef28dbf1ee07a6f778aed 100644 (file)
@@ -30,7 +30,7 @@ http
 HTTP GET with -O without Content-Disposition, -D stdout
 </name>
 <command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D - --output-dir %LOGDIR
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D - --output-dir="%LOGDIR"
 </command>
 </client>
 
index 0825a1e0287d0cc7409509ae7d92bb3f1274257c..2293fdf2f7ad2be0801d2b7e66f1d68735c204cf 100644 (file)
@@ -19,7 +19,7 @@ file
 Check --write-out with trailing \
 </name>
 <command>
-file://localhost/%FILE_PWD/%LOGDIR/non-existent-file.txt --write-out '\'
+file://localhost/%FILE_PWD/%LOGDIR/non-existent-file.txt --write-out='\'
 </command>
 </client>
 
index 99a949302354203b9262cb450d8d9ff5858da327..2ff05075c77b40362f2bec18292994a038f76e56 100644 (file)
@@ -80,7 +80,7 @@ digest
 HTTP proxy CONNECT auth Digest
 </name>
 <command>
-http://test.remote.haxx.se.%TESTNUMBER:8990/path/%TESTNUMBER0002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
+http://test.remote.haxx.se.%TESTNUMBER:8990/path/%TESTNUMBER0002 --proxy=http://%HOSTIP:%HTTPPORT --proxy-user=silly:person --proxy-digest --proxytunnel
 </command>
 </client>