From 03a26752c80546ac8cf8fc81807bb5a153786599 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Wed, 23 Feb 2022 20:47:55 -0500 Subject: [PATCH] help_print_optstring: Fix handling of 'flag' options. When getopt_long options use the 'flag' feature, the 'val' member is not meaningful as a short option. So we shouldn't try to format it as if there is a short option, as this leads to printing garbage. --- src/help.c | 9 +++++++-- t/helpopt.c | 38 +++++++++++++++++++++++++++++++++----- tests/functions.at | 10 +++++++--- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/help.c b/src/help.c index ea817e8..43bb266 100644 --- a/src/help.c +++ b/src/help.c @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Nick Bowler + * Copyright © 2021-2022 Nick Bowler * * Helper functions for formatting --help program output. * @@ -51,7 +51,12 @@ */ static int option_type(const struct option *opt) { - return ((opt->val <= CHAR_MAX) << 2) | (opt->has_arg & 3); + int ret = opt->has_arg & 3; + + if (!opt->flag) + ret |= (opt->val <= CHAR_MAX) << 2; + + return ret; } enum { diff --git a/t/helpopt.c b/t/helpopt.c index 303e13a..51b08a7 100644 --- a/t/helpopt.c +++ b/t/helpopt.c @@ -1,7 +1,33 @@ /* - * Read some text from standard input and format it with help_print_desc, - * for testing. Each pair of program arguments is converted to an int and - * passed as the two integer arguments to help_print_desc. + * Copyright © 2021-2022 Nick Bowler + * + * Test helper application to verify help_print_optstring operation. + * + * Command-line arguments are collected to create the options to be formatted. + * There are six basic forms: + * + * --long-option-only + * --long-option-with-argument arg + * --long-option-with-optional-argument [arg] + * --short-option -s arg + * --short-option-with-argument -s arg + * --short-option-with-optional-argument -s [arg] + * + * Adding an argument of '&' to any form will set the "flag" member of + * the option structure to a non-null value. + * + * Based on these arguments, a suitable 'struct option' is constructed and + * passed to help_print_optstring. Then a tab character is printed, followed + * by the return value of help_print_optsring (via printf %d). Then further + * arguments are considered to output more options. + * + * Initially, the "l" value passed to help_print_optstring is 20. This can be + * changed at any point by a numeric command-line argument, which will set a + * new value that applies to all subsequent calls until it is changed again. + * + * License WTFPL2: Do What The Fuck You Want To Public License, version 2. + * This is free software: you are free to do what the fuck you want to. + * There is NO WARRANTY, to the extent permitted by law. */ #include "help.h" #include "tap.h" @@ -14,8 +40,6 @@ #include -static char buf[1000]; - int arg_to_int(const char *s) { char *end; @@ -52,6 +76,7 @@ int main(int argc, char **argv) opt.val = UCHAR_MAX+1; opt.has_arg = 0; opt.name = argv[i]+2; + opt.flag = NULL; } else if (argv[i][0] == '-') { opt.val = argv[i][1]; } else if (argv[i][0] == '[') { @@ -61,6 +86,9 @@ int main(int argc, char **argv) if ((c = strchr(argname, ']'))) *c = 0; opt.has_arg = 2; + } else if (argv[i][0] == '&') { + static int dummy; + opt.flag = &dummy; } else if (argv[i][0] >= '0' && argv[i][0] <= '9') { w = arg_to_int(argv[i]); } else { diff --git a/tests/functions.at b/tests/functions.at index dbbcf6d..cfd5408 100644 --- a/tests/functions.at +++ b/tests/functions.at @@ -1,4 +1,4 @@ -dnl Copyright © 2015, 2021 Nick Bowler +dnl Copyright © 2015, 2021-2022 Nick Bowler dnl dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2. dnl This is free software: you are free to do what the fuck you want to. @@ -66,7 +66,8 @@ AT_CHECK([m4_join([ ], [--quux -q '@<:@ARG@:>@'], [--hello-this-is-a-very-long-option 20], [--hello-this-is-a-very-long-option 50], - [--not-long 12])], [0], + [--not-long 12], + [--flagged -f \&])], [0], [[ --foo 7 -b, --bar 11 --baz=ARG 11 @@ -77,6 +78,7 @@ AT_CHECK([m4_join([ ], 0 --hello-this-is-a-very-long-option 36 --not-long 12 + --flagged 11 ]]) AT_CLEANUP @@ -95,7 +97,8 @@ AT_CHECK([m4_join([ ], [--quux -q '@<:@ARG@:>@'], [--hello-this-is-a-very-long-option 20], [--hello-this-is-a-very-long-option 50], - [--not-long 12])], [0], + [--not-long 12], + [--flagged -f \&])], [0], [[ -foo 6 -bar 6 -baz ARG 10 @@ -106,6 +109,7 @@ AT_CHECK([m4_join([ ], 0 -hello-this-is-a-very-long-option 35 -not-long 11 + -flagged 10 ]]) AT_CLEANUP -- 2.43.2