Commit 263e2e9f 263e2e9f9fcf721c11a61a16dca4cb38d6385fe9 by Sergey Poznyakoff

Fix processing of abbreviated negated boolean options

It was noted that "mhn -nohead" did not suppress the output of
headers as "mhn -noheaders" did.  It turned out that the negation
marker was overwritten while scanning options for possible matching
alternatives.  This patch fixes it.

* libmailutils/opt/opt.c (find_long_option): Don't overwrite
the negation attribute of the last found option.

* libmailutils/tests/parseopt.c: New option --headers, to test
the fix.
* libmailutils/tests/parseopt28.at: New testcase.
* libmailutils/tests/Makefile.am: Add new testcase.
* libmailutils/tests/testsuite.at: Include new testcase.

* libmailutils/tests/parseopt*.at: Trivial changes
1 parent 766dd82f
......@@ -279,7 +279,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
size_t i;
size_t optlen; /* Length of the option in optstr */
int found = 0; /* 1 if the match was found, 2 if option is ambiguous */
enum neg_match neg; /* 1 if a boolean option is negated */
int negated; /* 1 if a boolean option is negated */
struct mu_option *ret_opt = NULL;
struct mu_option *used_opt;
......@@ -290,7 +290,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
size_t j = po->po_longidx[i];
size_t len = strlen (po->po_optv[j]->opt_long);
struct mu_option *opt = option_unalias (po, j);
neg = neg_nomatch;
enum neg_match neg = neg_nomatch;
if ((optlen <= len
&& memcmp (po->po_optv[j]->opt_long, optstr, optlen) == 0)
|| (neg = negmatch (po, j, optstr, optlen)))
......@@ -301,6 +301,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
used_opt = po->po_optv[j];
ret_opt = opt;
found++;
negated = neg != neg_nomatch;
if (optlen == len || neg == neg_match_exact)
i = po->po_longcnt - 1; /* exact match: break the loop */
break;
......@@ -353,12 +354,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
++optlen;
*used_value = (char *)(optstr + optlen);
if (ret_opt->opt_type == mu_c_bool)
{
if (neg)
*value = "0";
else
*value = "1";
}
*value = negated ? "0" : "1";
else
*value = NULL;
return ret_opt;
......
......@@ -141,6 +141,7 @@ TESTSUITE_AT = \
parseopt25.at\
parseopt26.at\
parseopt27.at\
parseopt28.at\
parseopt_help00.at\
parseopt_help01.at\
parseopt_help02.at\
......
......@@ -26,6 +26,7 @@ char *find_value;
int jobs = 0;
int x_option;
int a_option;
int headers_option = 1;
int d_option;
int debug_level_value;
char *debug_info_value;
......@@ -46,6 +47,9 @@ struct mu_option group_a[] = {
"no arguments to this one",
mu_c_bool, &a_option },
{ "debug-all", 0, NULL, MU_OPTION_ALIAS },
{ "headers", 0, NULL, MU_OPTION_DEFAULT,
"show headers",
mu_c_bool, &headers_option },
MU_OPTION_END
};
......@@ -218,6 +222,7 @@ main (int argc, char *argv[])
printf ("opt_value=%s\n", S(opt_value));
printf ("x_option=%d\n", x_option);
printf ("a_option=%d\n", a_option);
printf ("headers_option=%d\n", headers_option);
printf ("find_value=%s\n", S(find_value));
printf ("d_option=%d\n", d_option);
printf ("jobs=%d\n", jobs);
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=initial
x_option=1
a_option=1
headers_option=1
find_value=(null)
d_option=1
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=initial
x_option=1
a_option=1
headers_option=1
find_value=(null)
d_option=1
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=file
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=(null)
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=2
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=10
x_option=1
a_option=1
headers_option=1
find_value=(null)
d_option=2
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=initial
x_option=0
a_option=1
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=file
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=(null)
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=2
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=Word
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=filename
opt_value=(null)
x_option=1
a_option=1
headers_option=1
find_value=word
d_option=0
jobs=10
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=3
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=file
opt_value=(null)
x_option=1
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......@@ -48,6 +49,7 @@ file_name=file
opt_value=(null)
x_option=1
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=foobar
opt_value=initial
x_option=1
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=foobar
opt_value=initial
x_option=1
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=filename
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
......@@ -26,6 +26,7 @@ file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=1
find_value=(null)
d_option=0
jobs=0
......
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2017 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([boolean negation])
AT_KEYWORDS([parseopt parseopt_bool parseopt28])
AT_CHECK([
PARSEOPT_DEFAULT
MU_PARSEOPT_NEGATION=no-
export MU_PARSEOPT_NEGATION
echo "# full option"
parseopt --no-headers
echo "# abbreviated option"
parseopt --no-header
],
[0],
[# full option
rc=0
file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=0
find_value=(null)
d_option=0
jobs=0
debug_level_value=0
debug_info_value=(null)
argv:
# abbreviated option
rc=0
file_name=(null)
opt_value=initial
x_option=0
a_option=0
headers_option=0
find_value=(null)
d_option=0
jobs=0
debug_level_value=0
debug_info_value=(null)
argv:
])
AT_CLEANUP
......@@ -26,6 +26,7 @@ parseopt --help
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -23,7 +23,7 @@ parseopt --usage
[0],
[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
[--debug] [--debug-all] [--debug-info=S] [--debug-level=NUM]
[--file=FILE] [--find=VALUE] [--help] [--jobs=N]
[--file=FILE] [--find=VALUE] [--headers] [--help] [--jobs=N]
[--optional[=FILE]] [--usage] [--verbose]
]])
AT_CLEANUP
......
......@@ -26,6 +26,7 @@ MU_PARSEOPT_PROG_NAME=newname parseopt --help
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -27,6 +27,7 @@ Tests option parsing
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -26,6 +26,7 @@ MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS" parseopt --help
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[[=FILE]] optional argument
-x short-only option
......
......@@ -26,6 +26,7 @@ MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org' parseopt --help
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[[=FILE]] optional argument
-x short-only option
......
......@@ -26,6 +26,7 @@ MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils' MU_PARSEOPT_PACKAGE_URL='http://mailuti
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -33,6 +33,7 @@ Tests option parsing
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -27,6 +27,7 @@ ARGP_HELP_FMT=dup-args,no-dup-args-note,short-opt-col=1,opt-doc-col=32,header-co
Group A
-a, --all, --debug-all no arguments to this one
-f FILE, --file=FILE set file name
--headers show headers
-o[FILE], --optional[=FILE] optional argument
-x short-only option
......
......@@ -24,7 +24,7 @@ ARGP_HELP_FMT=rmargin=62,usage-indent=1\
[0],
[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N]
[-o[FILE]] [--all] [--debug] [--debug-all] [--debug-info=S]
[--debug-level=NUM] [--file=FILE] [--find=VALUE] [--help]
[--jobs=N] [--optional[=FILE]] [--usage] [--verbose]
[--debug-level=NUM] [--file=FILE] [--find=VALUE] [--headers]
[--help] [--jobs=N] [--optional[=FILE]] [--usage] [--verbose]
]])
AT_CLEANUP
......
......@@ -23,7 +23,7 @@ MU_PARSEOPT_VERSION_HOOK=1 parseopt --usage
[0],
[[Usage: parseopt [-advVx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
[--debug] [--debug-all] [--debug-info=S] [--debug-level=NUM]
[--file=FILE] [--find=VALUE] [--help] [--jobs=N]
[--file=FILE] [--find=VALUE] [--headers] [--help] [--jobs=N]
[--optional[=FILE]] [--usage] [--verbose] [--version]
]])
AT_CLEANUP
......
......@@ -26,6 +26,7 @@ MU_PARSEOPT_VERSION_HOOK=1 parseopt --help
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[=FILE] optional argument
-x short-only option
......
......@@ -28,6 +28,7 @@ MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS|ALTERNATIVE ARGS|ANOTHER ARGS" parseopt --
Group A
-a, --all, --debug-all no arguments to this one
-f, --file=FILE set file name
--headers show headers
-o, --optional[[=FILE]] optional argument
-x short-only option
......
......@@ -131,6 +131,7 @@ m4_include([parseopt24.at])
m4_include([parseopt25.at])
m4_include([parseopt26.at])
m4_include([parseopt27.at])
m4_include([parseopt28.at])
AT_BANNER([Command line help output])
m4_include([parseopt_help00.at])
......