argtable / argtable3

A single-file, ANSI C, command-line parsing library that parses GNU-style command-line options.
http://www.argtable.org
Other
372 stars 65 forks source link

Minus symbol stripped from negative numbers #83

Closed tadejg closed 1 year ago

tadejg commented 1 year ago

I have the following command: set <key> <value>

I want to be able to pass a negative number as the <value> (set some_key -5), however this results in an error (set: invalid option "-?").

Escaping the minus symbol doesn't return an error, but makes the number positive:

> set some_key \-5
Setting value to 5

Wrapping the value in quotes also makes no difference:

> set some_key "\-5"
Setting value to 5

> set some_key "-5"
set: invalid option "-?"

If I make the command set <key> -v|--value <value>, it works fine without the need for escaping.

> set some_key -v -5
Setting value to -5

The only difference I had to make is below:

// Doesn't work
static struct {
    struct arg_str *key = arg_str1(NULL, NULL, "<key>", "Key to update");
    struct arg_str *value = arg_str1(NULL, NULL, "<value>", "Value to set");
    struct arg_end *end = arg_end(2);
} setArgs;

// Works
static struct {
    struct arg_str *key = arg_str1(NULL, NULL, "<key>", "Key to update");
    struct arg_str *value = arg_str1("v", "value", "<value>", "Value to set");  // This line changed
    struct arg_end *end = arg_end(2);
} setArgs;

I can use this as a workaround for the time being, but would prefer to drop the need for -v or --value, if possible, since the command always expects <value> to be present anyways.

For reference: This was initially reported downstream in esp-idf where it was discovered this behavior comes from argtable3 and a reproducible example was put together: https://github.com/espressif/esp-idf/issues/10857

tomghuang commented 1 year ago

Hi @tadejg , I've confirmed the issue and I'll check how to resolve it. Thanks for raising this problem.

tomghuang commented 1 year ago

Hi @tadejg , this behavior is caused by the behavior of getopt. Since Argtable3 is based on getopt, it also has this behavior.

A workaround is using -- to tell getopt that all the command-line options after -- should be treated as untagged options (in Argtable3, an untagged option is an option that does not have both short and long option names). In other words, you have to use:

$ set <key> -- <value>
$ set -- <key> <value>

I've verified that adding -- can resolve this issue. Here is how I setup the table:

struct arg_str* key = arg_str1(NULL, NULL, "<key>", "key to set");
struct arg_int* value = arg_int1(NULL, NULL, "<value>", "value to set");
struct arg_end* end = arg_end(20);
void* argtable[] = {key, value, end};