You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/05/24 00:40:27 UTC
svn commit: r409017 - in /incubator/stdcxx/trunk/tests: self/0.cmdopts.cpp
src/cmdopt.cpp
Author: sebor
Date: Tue May 23 15:40:27 2006
New Revision: 409017
URL: http://svn.apache.org/viewvc?rev=409017&view=rev
Log:
2006-05-23 Martin Sebor <se...@roguewave.com>
* cmdopt.cpp (cmdopts_t): Added the toggle_ member.
(rw_vsetopts): Added the tilde ('~') special character
denoting a toggle (i.e., and off/on option).
(_rw_match_toggle): New.
(rw_runopts): Called _rw_match_toggle.
* 0.cmdopts.cpp (test_toggles): Added tests for the above.
(main): Called test_toggles.
Modified:
incubator/stdcxx/trunk/tests/self/0.cmdopts.cpp
incubator/stdcxx/trunk/tests/src/cmdopt.cpp
Modified: incubator/stdcxx/trunk/tests/self/0.cmdopts.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/self/0.cmdopts.cpp?rev=409017&r1=409016&r2=409017&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.cmdopts.cpp (original)
+++ incubator/stdcxx/trunk/tests/self/0.cmdopts.cpp Tue May 23 15:40:27 2006
@@ -7,16 +7,22 @@
*
************************************************************************
*
- * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
- * Software division. Licensed under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
- * applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License
- * for the specific language governing permissions and limitations under
- * the License.
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2005-2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
**************************************************************************/
@@ -276,8 +282,6 @@
/**************************************************************************/
-
-
// convenience macros for brevity
#define A mkargv
@@ -389,6 +393,36 @@
/**************************************************************************/
static void
+test_toggles ()
+{
+ // +-- expected result string
+ // | +-- expected return value from rw_getopts()
+ // | | +-- command line arguments
+ // | | | +-- number of directives
+ // | | | | +-- cmdopt specification
+ // | | | | | +-- counter
+ // | | | | | |
+ // V V V V V V
+ T ("#1", 0, A ("--enable-foo"), 1, "|-foo~", C0);
+ T ("#1", 0, A ("--use-foo"), 1, "|-foo~", C0);
+ T ("#1", 0, A ("--with-foo"), 1, "|-foo~", C0);
+
+ T ("#-1", 0, A ("--disable-foo"), 1, "|-foo~", C0);
+ T ("#-1", 0, A ("--no-foo"), 1, "|-foo~", C0);
+ T ("#-1", 0, A ("--without-foo"), 1, "|-foo~", C0);
+
+ // the same toggle can be repeated any number of times
+ T ("#1", 0, A ("--enable-foo", "--use-foo"), 1, "|-foo~", C0);
+ T ("#-1", 0, A ("--no-foo", "--without-foo"), 1, "|-foo~", C0);
+
+ // the last toggle wins
+ T ("#-1", 0, A ("--use-foo", "--no-foo"), 1, "|-foo~", C0);
+ T ("#1", 0, A ("--no-foo", "--use-foo"), 1, "|-foo~", C0);
+}
+
+/**************************************************************************/
+
+static void
test_optional_argument ()
{
// exercise an option with an optional argument
@@ -546,6 +580,9 @@
// exercise the handling of options with an optional argument
test_optional_argument ();
+
+ // exercise the handling of toggling options
+ test_toggles ();
// exercise the handling of options with a required argument
test_required_argument ();
Modified: incubator/stdcxx/trunk/tests/src/cmdopt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/cmdopt.cpp?rev=409017&r1=409016&r2=409017&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/cmdopt.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/cmdopt.cpp Tue May 23 15:40:27 2006
@@ -4,16 +4,22 @@
*
************************************************************************
*
- * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
- * Software division. Licensed under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
- * applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License
- * for the specific language governing permissions and limitations under
- * the License.
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2005-2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
**************************************************************************/
@@ -22,7 +28,6 @@
#include <cmdopt.h>
-#include <assert.h> // for assert
#include <ctype.h> // isdigit(), isspace()
#include <errno.h> // for errno
#include <stdarg.h> // for va_arg, ...
@@ -55,20 +60,21 @@
size_t maxcount_; // how many times option can be invoked
size_t count_; // how many times it has been invoked
- unsigned arg_ : 1; // option takes an argument?
+ unsigned arg_ : 1; // option takes an argument
unsigned inv_ : 1; // callback invocation inverted
+ unsigned toggle_ : 1; // option is a toggle
unsigned envseen_ : 1; // environment option already processed
};
// total number of registered options
-static size_t ncmdopts;
+static size_t _rw_ncmdopts;
// number of default (always defined) options
-static size_t ndefopts;
-static cmdopts_t cmdoptbuf [32];
-static cmdopts_t *cmdopts = cmdoptbuf;
-static size_t optbufsize = sizeof cmdoptbuf / sizeof *cmdoptbuf;
+static size_t _rw_ndefopts;
+static cmdopts_t _rw_cmdoptbuf [32];
+static cmdopts_t *_rw_cmdopts = _rw_cmdoptbuf;
+static size_t _rw_optbufsize = sizeof _rw_cmdoptbuf / sizeof *_rw_cmdoptbuf;
/**************************************************************************/
@@ -104,15 +110,17 @@
// set to a non-zero when the specified option is found
int option_found = 0;
- for (size_t i = 0; i != ncmdopts; ++i) {
+ for (size_t i = 0; i != _rw_ncmdopts; ++i) {
+
+ // for convenience
+ const cmdopts_t* const opt = _rw_cmdopts + i;
// get a pointer to the name of the long option, if any
- const char* const lopt =
- cmdopts [i].lopt_ ? cmdopts [i].lopt_ : cmdopts [i].loptbuf_;
+ const char* const lopt = opt->lopt_ ? opt->lopt_ : opt->loptbuf_;
if (opthelp && *opthelp) {
- if ( cmdopts [i].sopt_ == opthelp [0] && '\0' == opthelp [1]
+ if ( opt->sopt_ == opthelp [0] && '\0' == opthelp [1]
|| *lopt && 0 == strcmp (lopt + 1, opthelp)) {
// remember that we found the option whose (short
@@ -131,13 +139,13 @@
// separate options with help functionality (which typically
// produce multiline output) from previous options without
// it (and thus very brief output)
- if (i && 0 == cmdopts [i - 1].callback_ && cmdopts [i].callback_)
+ if (i && 0 == _rw_cmdopts [i - 1].callback_ && opt->callback_)
puts ("");
printf (" ");
- if (cmdopts [i].sopt_) {
- printf ("-%c", cmdopts [i].sopt_);
+ if (opt->sopt_) {
+ printf ("-%c", opt->sopt_);
if (lopt)
printf (" | ");
@@ -148,53 +156,52 @@
if (lopt) {
printf ("-%s", lopt);
- if ( cmdopts [i].arg_
- && '=' != lopt [strlen (lopt) - 1]) {
+ if (opt->arg_ && '=' != lopt [strlen (lopt) - 1]) {
pfx = " [ ";
sfx = " ]";
}
}
- const char* arg =
- _RWSTD_INT_MIN < cmdopts [i].minval_
- || cmdopts [i].maxval_ < _RWSTD_INT_MAX ? "int" : "arg";
+ const char* const arg =
+ _RWSTD_INT_MIN < opt->minval_
+ || opt->maxval_ < _RWSTD_INT_MAX ? "int" : "arg";
- if (cmdopts [i].arg_) {
+ if (opt->arg_) {
// print argument (in brackets when it's optional)
printf ("%s<%s>%s", pfx, arg, sfx);
}
- if (cmdopts [i].pcntr_)
+ if (opt->pcntr_)
printf (" | -%s=<%s>", lopt, arg);
if ('i' == *arg) {
printf (", with ");
- if (_RWSTD_INT_MIN < cmdopts [i].minval_)
- printf ("%d <= ", cmdopts [i].minval_);
+ if (_RWSTD_INT_MIN < opt->minval_)
+ printf ("%d <= ", opt->minval_);
printf ("<%s>", arg);
- if (cmdopts [i].maxval_ < _RWSTD_INT_MAX)
- printf (" <= %d", cmdopts [i].maxval_);
+ if (opt->maxval_ < _RWSTD_INT_MAX)
+ printf (" <= %d", opt->maxval_);
printf ("\n ");
}
- if (_RWSTD_SIZE_MAX == cmdopts [i].maxcount_)
+ if (_RWSTD_SIZE_MAX == opt->maxcount_)
printf (" (each occurrence evaluated)\n");
- else if (1 < cmdopts [i].maxcount_)
+ else if (1 < opt->maxcount_)
printf (" (at most %u occurrences evaluated)\n",
- unsigned (cmdopts [i].maxcount_));
+ unsigned (opt->maxcount_));
else
printf (" (only the first occurrence evaluated)\n");
// invoke callback with the "--help" option
- if (cmdopts [i].callback_) {
+ if (opt->callback_) {
char* help [2] = { 0, 0 };
- cmdopts [i].callback_ (1, help);
+ opt->callback_ (1, help);
for (const char *line = help [0]; line; ) {
@@ -249,41 +256,41 @@
extern "C" {
static void
-rw_clear_opts ()
+_rw_clear_opts ()
{
// reset all options, deallocating dynamically allocated storage
- for (size_t i = 0; i != ncmdopts; ++i) {
+ for (size_t i = 0; i != _rw_ncmdopts; ++i) {
// free any storage allocated for the option name
- free (cmdopts [i].lopt_);
+ free (_rw_cmdopts [i].lopt_);
}
- if (cmdopts != cmdoptbuf) {
+ if (_rw_cmdopts != _rw_cmdoptbuf) {
// free the storage allocated for all the options
- free (cmdopts);
+ free (_rw_cmdopts);
}
// reset the options pointer to point at the statically
// allocated buffer and the count back to 0
- ncmdopts = 0;
- cmdopts = cmdoptbuf;
- optbufsize = sizeof cmdoptbuf / sizeof *cmdoptbuf;
+ _rw_ncmdopts = 0;
+ _rw_cmdopts = _rw_cmdoptbuf;
+ _rw_optbufsize = sizeof _rw_cmdoptbuf / sizeof *_rw_cmdoptbuf;
}
}
static void
-rw_set_myopts ()
+_rw_set_myopts ()
{
static int cleanup_handler_registered;
if (0 == cleanup_handler_registered) {
- atexit (rw_clear_opts);
+ atexit (_rw_clear_opts);
cleanup_handler_registered = 1;
}
- if (0 != ncmdopts)
+ if (0 != _rw_ncmdopts)
return;
static int recursive;
@@ -299,7 +306,7 @@
_rw_print_help,
_rw_set_ignenv);
- ndefopts = ncmdopts;
+ _rw_ndefopts = _rw_ncmdopts;
recursive = 0;
}
@@ -346,7 +353,7 @@
next = end ? end : next + 1;
- cmdopts [ncmdopts].minval_ = minval;
+ _rw_cmdopts [_rw_ncmdopts].minval_ = minval;
if ('-' == *next) {
++next;
@@ -384,7 +391,7 @@
}
next = end ? end : next + 1;
- cmdopts [ncmdopts].maxval_ = int (maxval);
+ _rw_cmdopts [_rw_ncmdopts].maxval_ = int (maxval);
}
else {
// syntax error in range
@@ -403,19 +410,19 @@
}
else {
// no upper bound on the value of the option argument
- cmdopts [ncmdopts].maxval_ = _RWSTD_INT_MAX;
+ _rw_cmdopts [_rw_ncmdopts].maxval_ = _RWSTD_INT_MAX;
}
}
else {
// no minimum/maximum value for this option is set
- cmdopts [ncmdopts].minval_ = _RWSTD_INT_MIN;
- cmdopts [ncmdopts].maxval_ = _RWSTD_INT_MAX;
+ _rw_cmdopts [_rw_ncmdopts].minval_ = _RWSTD_INT_MIN;
+ _rw_cmdopts [_rw_ncmdopts].maxval_ = _RWSTD_INT_MAX;
}
// an unlimited number of occurrences of the option
// are allowed and will be counted
- cmdopts [ncmdopts].maxcount_ = _RWSTD_SIZE_MAX;
+ _rw_cmdopts [_rw_ncmdopts].maxcount_ = _RWSTD_SIZE_MAX;
return next;
}
@@ -426,15 +433,15 @@
{
if (0 == opts) {
- rw_clear_opts ();
+ _rw_clear_opts ();
return 0;
}
- rw_set_myopts ();
+ _rw_set_myopts ();
const char *next = opts;
- for ( ; ; ++ncmdopts) {
+ for ( ; ; ++_rw_ncmdopts) {
while (isspace (*next))
++next;
@@ -443,9 +450,9 @@
break;
}
- if (ncmdopts == optbufsize) {
+ if (_rw_ncmdopts == _rw_optbufsize) {
- const size_t newbufsize = 2 * ncmdopts + 1;
+ const size_t newbufsize = 2 * _rw_ncmdopts + 1;
cmdopts_t* const newopts =
(cmdopts_t*)malloc (newbufsize * sizeof (cmdopts_t));
@@ -456,26 +463,29 @@
abort ();
}
- memcpy (newopts, cmdopts, ncmdopts * sizeof (cmdopts_t));
+ memcpy (newopts, _rw_cmdopts, _rw_ncmdopts * sizeof (cmdopts_t));
- if (cmdopts != cmdoptbuf)
- free (cmdopts);
+ if (_rw_cmdopts != _rw_cmdoptbuf)
+ free (_rw_cmdopts);
- cmdopts = newopts;
- optbufsize = newbufsize;
+ _rw_cmdopts = newopts;
+ _rw_optbufsize = newbufsize;
}
// clear the next option info
- memset (cmdopts + ncmdopts, 0, sizeof *cmdopts);
+ memset (_rw_cmdopts + _rw_ncmdopts, 0, sizeof *_rw_cmdopts);
+
+ // for convenience
+ cmdopts_t* const lastopt = _rw_cmdopts + _rw_ncmdopts;
- cmdopts [ncmdopts].minval_ = _RWSTD_INT_MIN;
- cmdopts [ncmdopts].maxval_ = _RWSTD_INT_MAX;
+ lastopt->minval_ = _RWSTD_INT_MIN;
+ lastopt->maxval_ = _RWSTD_INT_MAX;
if ('|' != *next)
- cmdopts [ncmdopts].sopt_ = *next++;
+ lastopt->sopt_ = *next++;
if ('|' == *next) {
- const char* end = strpbrk (++next, "|@:=*!# ");
+ const char* end = strpbrk (++next, "|@:=*!#~ ");
if (0 == end)
end = next + strlen (next);
@@ -486,11 +496,11 @@
char *lopt = 0;
- if (optlen < sizeof cmdopts [ncmdopts].loptbuf_)
- lopt = cmdopts [ncmdopts].loptbuf_;
+ if (optlen < sizeof lastopt->loptbuf_)
+ lopt = lastopt->loptbuf_;
else {
lopt = (char*)malloc (optlen + 1);
- cmdopts [ncmdopts].lopt_ = lopt;
+ lastopt->lopt_ = lopt;
}
memcpy (lopt, next, optlen);
@@ -502,7 +512,7 @@
// only the first occurrence of each command line option
// causes an invocation of the callback, all subsequent
// ones will be ignored by default
- cmdopts [ncmdopts].maxcount_ = 1;
+ lastopt->maxcount_ = 1;
int arg_is_callback = true;
@@ -520,10 +530,20 @@
arg_is_callback = false;
}
+ else if ('~' == *next) {
+ ++next;
+
+ // unlimited number of toggles are allowed
+ lastopt->toggle_ = 1;
+ lastopt->maxcount_ = _RWSTD_SIZE_MAX;
+
+ // no callback function expected
+ arg_is_callback = false;
+ }
else if (':' == *next || '=' == *next) {
// ':' : argument optional
// '=' : argument required
- cmdopts [ncmdopts].arg_ = true;
+ lastopt->arg_ = true;
// check if the value of the argument is restricted
next = _rw_getbounds (next, RW_VA_LIST_ARG_TO_PTR (va));
@@ -539,18 +559,18 @@
// at most how many occurrences of an option can be processed?
if ('*' == *next) {
// unlimited
- cmdopts [ncmdopts].maxcount_ = _RWSTD_SIZE_MAX;
+ lastopt->maxcount_ = _RWSTD_SIZE_MAX;
++next;
}
else {
// at most this many
char *end;
- cmdopts [ncmdopts].maxcount_ = strtoul (next, &end, 10);
+ lastopt->maxcount_ = strtoul (next, &end, 10);
next = end;
}
}
else if ('!' == *next) {
- cmdopts [ncmdopts].inv_ = true;
+ lastopt->inv_ = true;
++next;
}
@@ -559,35 +579,35 @@
// (null callback is permitted in the special case when
// the short option is '-', i.e., when setting up or
// resetting an "unknown option" handler)
- cmdopts [ncmdopts].callback_ = va_arg (va, optcallback_t*);
+ lastopt->callback_ = va_arg (va, optcallback_t*);
}
else {
// retrieve the address of the int counter where to keep
// track of the number of occurrences of the option, or
// where to store the value of the numeric argument of
// the option
- cmdopts [ncmdopts].pcntr_ = va_arg (va, int*);
+ lastopt->pcntr_ = va_arg (va, int*);
}
- if ( '-' != cmdopts [ncmdopts].sopt_
- && 0 == cmdopts [ncmdopts].callback_
- && 0 == cmdopts [ncmdopts].pcntr_) {
+ if ( '-' != lastopt->sopt_
+ && 0 == lastopt->callback_
+ && 0 == lastopt->pcntr_) {
// get a pointer to the long option name
- const char* const lopt = cmdopts [ncmdopts].lopt_
- ? cmdopts [ncmdopts].lopt_ : cmdopts [ncmdopts].loptbuf_;
+ const char* const lopt = lastopt->lopt_
+ ? lastopt->lopt_ : lastopt->loptbuf_;
if (*lopt)
fprintf (stderr, "null handler for option -%s\n", lopt);
else
fprintf (stderr, "null handler for option -%c\n",
- cmdopts [ncmdopts].sopt_);
+ lastopt->sopt_);
abort ();
}
}
- return int (ncmdopts - ndefopts);
+ return int (_rw_ncmdopts - _rw_ndefopts);
}
/**************************************************************************/
@@ -608,8 +628,8 @@
static int
_rw_getarg (cmdopts_t *optspec, const char *opt, const char *arg)
{
- assert (0 != optspec);
- assert (0 != arg);
+ RW_ASSERT (0 != optspec);
+ RW_ASSERT (0 != arg);
// obtain the numeric argument
char *end = 0;
@@ -664,8 +684,8 @@
static int
_rw_runopt (cmdopts_t *optspec, int argc, char *argv[])
{
- assert (0 != optspec);
- assert (0 != argv);
+ RW_ASSERT (0 != optspec);
+ RW_ASSERT (0 != argv);
// ignore the option if invoked recursively (by processing options
// set in the environment) and the option has already been seen
@@ -727,15 +747,16 @@
}
}
else if (equals) {
-
// option takes an optional numeric argument
- assert (0 != optspec->pcntr_);
+ RW_ASSERT (0 != optspec->pcntr_);
status = _rw_getarg (optspec, argv [0], equals + 1);
}
else {
- assert (0 != optspec->pcntr_);
+ // option must not be a toggle (those are handled elsewhere)
+ RW_ASSERT (0 == optspec->toggle_);
+ RW_ASSERT (0 != optspec->pcntr_);
++*optspec->pcntr_;
}
@@ -749,10 +770,59 @@
/**************************************************************************/
+// tries to match the option named by optname with the option
+// specification opt and returns a non-zero value on success,
+// 0 otherwise; the returned value is negative when the matched
+// option is being disabled and positive when it's being
+// enabled
+static int
+_rw_match_toggle (const cmdopts_t *opt, const char *optname)
+{
+ RW_ASSERT (0 != opt);
+ RW_ASSERT (0 != optname);
+
+ static const char* const prefix[] = {
+ "+enable", "+use", "+with",
+ "-disable", "-no", "-without",
+ 0
+ };
+
+ int toggle = 0;
+
+ if ('-' == optname [0] && '-' != optname [2]) {
+
+ ++optname;
+
+ const size_t optlen = strlen (optname);
+
+ for (size_t i = 0; prefix [i]; ++i) {
+ const char* const pfx = prefix [i] + 1;
+ const size_t pfxlen = strlen (pfx);
+
+ if (pfxlen < optlen && 0 == memcmp (optname, pfx, pfxlen)) {
+ const char* const name = optname + pfxlen;
+
+ // return -1 to disable, +1 to enable, 0 when not found
+ const char* const lopt =
+ opt->lopt_ ? opt->lopt_ : opt->loptbuf_;
+
+ if (0 == strcmp (lopt, name)) {
+ toggle = '+' == prefix [i][0] ? 1 : -1;
+ break;
+ }
+ }
+ }
+ }
+
+ return toggle;
+}
+
+/**************************************************************************/
+
_TEST_EXPORT int
rw_runopts (int argc, char *argv[])
{
- rw_set_myopts ();
+ _rw_set_myopts ();
// ignore options set in the environment?
int ignenv = _rw_runopt_recursive;
@@ -763,9 +833,9 @@
// number of options processed
int nopts = 0;
- // index of registered option whose callback should be invoked
+ // pointer to the option whose callback will be invoked
// for command line options that do not match any other
- size_t not_found_inx = _RWSTD_SIZE_MAX;
+ cmdopts_t* not_found_opt = 0;
// iterate over the command line arguments until a callback
// returns a non-zero value or until all options have been
@@ -787,6 +857,10 @@
// the name of the option without the leading dash
const char* const optname = argv [i] + 1;
+ // the argc and argv to pass to the option handler
+ const int opt_argc = argc - i;
+ char** const opt_argv = argv + i;
+
// look for the first equals sign
const char* const eq = strchr (optname, '=');
@@ -797,34 +871,58 @@
// look up each command line option (i.e., a string that starts
// with a dash ('-')) and invoke the callback associated with it
- for (size_t j = 0; j != ncmdopts; ++j) {
+ for (size_t j = 0; j != _rw_ncmdopts; ++j) {
+
+ // for convenience
+ cmdopts_t* const opt = _rw_cmdopts + j;
- if ('-' == cmdopts [j].sopt_)
- not_found_inx = j;
+ if ('-' == opt->sopt_)
+ not_found_opt = opt;
if ('-' == argv [i][0]) {
const size_t cmplen =
- eq && cmdopts [j].pcntr_ ? optlen - 1 : optlen;
+ eq && opt->pcntr_ ? optlen - 1 : optlen;
// get a pointer to the (possibly empty) name
// of the long option
- const char* const lopt = cmdopts [j].lopt_ ?
- cmdopts [j].lopt_ : cmdopts [j].loptbuf_;
+ const char* const lopt = opt->lopt_ ?
+ opt->lopt_ : opt->loptbuf_;
+
+ if (opt->toggle_) {
+ // option specification denotes a toggle, see if it
+ // matches and if so, whether it's being disabled or
+ // enabled (-1 or +1, respectively)
+ const int toggle = _rw_match_toggle (opt, optname);
+
+ if (toggle) {
+ RW_ASSERT (0 != opt->pcntr_);
+ *opt->pcntr_ = toggle < 0 ? -1 : 1;
+
+ // matching option has been found
+ found = true;
+
+ // increment the number of options processed
+ ++nopts;
+ }
+
+ // avoid ordinary option processing below
+ continue;
+ }
// try to match the long option first, and only if it
// doesn't match try the short single-character option
if ( cmplen == strlen (lopt)
&& 0 == memcmp (optname, lopt, cmplen)
- || cmdopts [j].sopt_
- && optname [0] == cmdopts [j].sopt_
- && (1 == optlen || cmdopts [j].arg_)) {
+ || opt->sopt_
+ && optname [0] == opt->sopt_
+ && (1 == optlen || opt->arg_)) {
// matching option has been found
found = true;
// process it and its arguments, if any
- status = _rw_runopt (cmdopts + j, int (argc - i), argv + i);
+ status = _rw_runopt (opt, opt_argc, opt_argv);
// increment the number of options processed
// (whether successfully or otherwise)
@@ -846,12 +944,12 @@
// invoke the appropriate error handler for an option
// that was not found
- if (_RWSTD_SIZE_MAX != not_found_inx) {
+ if (0 != not_found_opt) {
// invoke the error handler set up through rw_setopts()
// and let the handler decide whether to go on processing
// other options or whether to abort
- status = cmdopts [not_found_inx].callback_ (argc - i, argv + i);
+ status = not_found_opt->callback_ (opt_argc, opt_argv);
if (status) {
// no further processing done
ignenv = true;
@@ -883,20 +981,23 @@
// invoke any inverted callbacks or bump their user-specified counters,
// and reset internal counters indicating if/how many times each option
// has been processed
- for (size_t j = 0; j != ncmdopts; ++j) {
+ for (size_t j = 0; j != _rw_ncmdopts; ++j) {
+
+ // for convenience
+ cmdopts_t* const opt = _rw_cmdopts + j;
- if (cmdopts [j].inv_ && 0 == cmdopts [j].count_ && 0 == status) {
+ if (opt->inv_ && 0 == opt->count_ && 0 == status) {
- if (cmdopts [j].callback_)
- status = cmdopts [j].callback_ (0, 0);
+ if (opt->callback_)
+ status = opt->callback_ (0, 0);
else {
- assert (0 != cmdopts [j].pcntr_);
- ++*cmdopts [j].pcntr_;
+ RW_ASSERT (0 != opt->pcntr_);
+ ++*opt->pcntr_;
}
}
- cmdopts [j].count_ = 0;
- cmdopts [j].envseen_ = false;
+ opt->count_ = 0;
+ opt->envseen_ = false;
}
return status;
@@ -907,9 +1008,9 @@
_TEST_EXPORT int
rw_runopts (const char *str)
{
- assert (0 != str);
+ RW_ASSERT (0 != str);
- rw_set_myopts ();
+ _rw_set_myopts ();
char buf [80]; // fixed size buffer to copy `str' into
char *pbuf = buf; // a modifiable copy of `str'