stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/cmdopt.cpp
author William Roberts <williamr@symbian.org>
Thu, 22 Jul 2010 16:48:56 +0100
branchGCC_SURGE
changeset 45 4b03adbd26ca
parent 22 ddc455616bd6
parent 31 ce057bb09d0b
permissions -rw-r--r--
Catchup to latest Symbian^4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
31
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     1
/***************************************************************************
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     2
 *
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     3
 * $Id: cmdopt.cpp 348342 2005-11-23 02:03:26Z sebor $
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     4
 *
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     5
 ************************************************************************
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     6
 *
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     7
 * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     8
 * Software division. Licensed under the Apache License, Version 2.0 (the
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
     9
 * "License");  you may  not use this file except  in compliance with the
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    10
 * License.    You    may   obtain   a   copy   of    the   License    at
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    11
 * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    12
 * applicable law  or agreed to  in writing,  software  distributed under
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    13
 * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    14
 * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    15
 * for the specific language governing permissions  and limitations under
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    16
 * the License.
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    17
 * 
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    18
 **************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    19
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    20
// expand _TEST_EXPORT macros
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    21
#define _RWSTD_TEST_SRC
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    22
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    23
#include <cmdopt.h>
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    24
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    25
#include <assert.h>   // for assert
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    26
#include <errno.h>    // for errno
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    27
#include <stdarg.h>   // for va_arg, ...
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    28
#include <stdio.h>    // for fprintf
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    29
#include <stdlib.h>   // for atexit, free, malloc
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    30
#include <string.h>   // for memcpy, strcpy, strcmp, ...
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    31
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    32
#ifdef __ARMCC__
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    33
#pragma diag_suppress 61
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    34
#pragma diag_suppress 63
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    35
#endif
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    36
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    37
#ifndef EINVAL
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    38
#  define EINVAL   22   /* e.g., HP-UX, Linux, Solaris */
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    39
#endif   // EINVAL
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    40
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    41
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    42
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    43
typedef int (optcallback_t)(int, char*[]);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    44
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    45
struct cmdopts_t
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    46
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    47
    char           loptbuf_ [32];   // buffer for long option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    48
    optcallback_t *callback_;       // function to call to process option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    49
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    50
    // counter to increment for each occurrence of an option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    51
    // or to set to the numeric argument (when specified)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    52
    int           *pcntr_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    53
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    54
    char          *lopt_;           // long option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    55
    char           sopt_;           // short option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    56
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    57
    size_t         maxcalls_;       // how many times option can be invoked
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    58
    size_t         ncalls_;         // how many times it has been invoked
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    59
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    60
    unsigned       arg_ : 1;        // option takes an argument?
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    61
    unsigned       inv_ : 1;        // callback invocation inverted
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    62
    unsigned       envseen_ : 1;    // environment option already processed
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    63
};
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    64
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    65
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    66
// total number of registered options
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    67
static size_t ncmdopts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    68
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    69
// number of default (always defined) options
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    70
static size_t ndefopts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    71
static cmdopts_t cmdoptbuf [32];
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    72
static cmdopts_t *cmdopts = cmdoptbuf;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    73
static size_t optbufsize = sizeof cmdoptbuf / sizeof *cmdoptbuf;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    74
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    75
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    76
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    77
static int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    78
rw_print_help (int argc, char *argv[])
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    79
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    80
    if (1 == argc && argv && 0 == argv [0]) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    81
        static const char helpstr[] = {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    82
            "Without an argument, prints this help to stdout and exits with\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    83
            "a status of 0 without further processing.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    84
            "With the optional argument prints help on the option with that\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    85
            "name, if one exists, and exits with a status of 0. If an option\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    86
            "with the specified name does not exist, prints an error message\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    87
            "to stderr and exits with a status of 1.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    88
            "The leading underscores in the name of an option are optional.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    89
        };
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    90
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    91
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    92
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    93
        return 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    94
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    95
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    96
    // the option name to get help on, if any
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    97
    const char* opthelp = 1 < argc ? argv [1] : 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    98
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
    99
    // remove the optional one or two leading underscores
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   100
    if (opthelp && '-' == opthelp [0] && opthelp [1])
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   101
        opthelp += 1 + ('-' == opthelp [1]);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   102
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   103
    if (0 == opthelp)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   104
        printf ("OPTIONS\n");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   105
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   106
    // set to a non-zero when the specified option is found
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   107
    int option_found = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   108
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   109
    for (size_t i = 0; i != ncmdopts; ++i) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   110
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   111
        // get a pointer to the name of the long option, if any
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   112
        const char* const lopt =
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   113
            cmdopts [i].lopt_ ? cmdopts [i].lopt_ : cmdopts [i].loptbuf_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   114
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   115
        if (opthelp && *opthelp) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   116
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   117
            if (   cmdopts [i].sopt_ == opthelp [0] && '\0' == opthelp [1]
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   118
                || *lopt && 0 == strcmp (lopt + 1, opthelp)) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   119
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   120
                // remember that we found the option whose (short
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   121
                // or long) name we're to give help on; after printing
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   122
                // the help text on the option keep looping in case
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   123
                // there is another option and callback with the same
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   124
                // name (unlikely but possible)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   125
                option_found = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   126
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   127
            else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   128
                // the option doesn't match, continue searching
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   129
                continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   130
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   131
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   132
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   133
        printf ("     ");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   134
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   135
        if (cmdopts [i].sopt_) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   136
            printf ("-%c", cmdopts [i].sopt_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   137
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   138
            if (lopt)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   139
                printf (" | ");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   140
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   141
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   142
        const char *pfx = "";
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   143
        const char *sfx = pfx;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   144
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   145
        if (lopt) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   146
            printf ("-%s", lopt);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   147
            if (   cmdopts [i].arg_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   148
                && '=' != lopt [strlen (lopt) - 1]) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   149
                pfx = " [ ";
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   150
                sfx = " ]";
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   151
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   152
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   153
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   154
        printf ("%s%s%s", pfx, cmdopts [i].arg_ ? "<arg>" : "", sfx);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   155
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   156
        if (_RWSTD_SIZE_MAX == cmdopts [i].maxcalls_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   157
            printf (" (each occurrence evaluated)\n");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   158
        else if (1 < cmdopts [i].maxcalls_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   159
            printf (" (at most %u occurrences evaluated)\n",
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   160
                    unsigned (cmdopts [i].maxcalls_));
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   161
        else
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   162
            printf (" (only the first occurrence evaluated)\n");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   163
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   164
        // invoke callback with the "--help" option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   165
        if (cmdopts [i].callback_) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   166
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   167
            char* help [2] = { 0, 0 };
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   168
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   169
            cmdopts [i].callback_ (1, help);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   170
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   171
            for (const char *line = help [0]; line; ) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   172
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   173
                const char* const nl = strchr (line, '\n');
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   174
                const int len = nl ? int (nl - line) : int (strlen (line));
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   175
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   176
                printf ("       %.*s\n", len, line);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   177
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   178
                line = nl;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   179
                if (nl)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   180
                    ++line;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   181
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   182
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   183
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   184
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   185
    if (opthelp && !option_found) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   186
        fprintf (stderr, "Unknown option \"%s\".\n", opthelp);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   187
        exit (1);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   188
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   189
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   190
    exit (0);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   191
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   192
    return 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   193
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   194
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   195
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   196
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   197
static int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   198
rw_set_ignenv (int argc, char *argv[])
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   199
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   200
    if (1 == argc && argv && 0 == argv [0]) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   201
        static const char helpstr[] = {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   202
            "Prevents options specified in the RWSTD_TESTOPTS environment\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   203
            "variable from taking effect.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   204
            "Unless this option is specified, the RWSTD_TESTOPTS environment\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   205
            "variable is processed as if its value were specified on the \n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   206
            "command line.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   207
            "For example, setting the value of the variable to the string\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   208
            "\"--verbose --no-wchar\" and invoking this program with no\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   209
            "command line arguments will have the same effect as invoking\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   210
            "it with the two arguments on the command line.\n"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   211
        };
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   212
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   213
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   214
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   215
        return 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   216
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   217
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   218
    return 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   219
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   220
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   221
extern "C" {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   222
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   223
static void
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   224
rw_clear_opts ()
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   225
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   226
    // reset all options, deallocating dynamically allocated storage
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   227
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   228
    for (size_t i = 0; i != ncmdopts; ++i) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   229
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   230
        // free any storage allocated for the option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   231
        free (cmdopts [i].lopt_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   232
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   233
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   234
    if (cmdopts != cmdoptbuf) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   235
        // free the storage allocated for all the options
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   236
        free (cmdopts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   237
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   238
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   239
    // reset the options pointer to point at the statically
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   240
    // allocated buffer and the count back to 0
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   241
    ncmdopts   = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   242
    cmdopts    = cmdoptbuf;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   243
    optbufsize = sizeof cmdoptbuf / sizeof *cmdoptbuf;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   244
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   245
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   246
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   247
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   248
static void
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   249
rw_set_myopts ()
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   250
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   251
    static int cleanup_handler_registered;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   252
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   253
    if (0 == cleanup_handler_registered) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   254
        atexit (rw_clear_opts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   255
        cleanup_handler_registered = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   256
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   257
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   258
    if (0 != ncmdopts)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   259
        return;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   260
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   261
    static int recursive;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   262
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   263
    if (recursive)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   264
        return;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   265
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   266
    ++recursive;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   267
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   268
    rw_setopts ("|-help: "   // argument optional
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   269
                "|-ignenv ",
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   270
                rw_print_help,
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   271
                rw_set_ignenv);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   272
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   273
    ndefopts = ncmdopts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   274
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   275
    recursive = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   276
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   277
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   278
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   279
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   280
//////////////////////////////////////////////////////////////////////
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   281
// syntax of the option description string:
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   282
//
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   283
// opts ::= opt [ ':' | '=' | '#' ] [ @N | @* | '!' ] [ opts ]
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   284
// opt  ::= <sopt> [ '|' <lopt>]
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   285
//      ::= '|' <lopt>
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   286
// sopt ::= char
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   287
// lopt ::= char char*
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   288
// char ::= A-Z a-z _ 0-9
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   289
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   290
_TEST_EXPORT int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   291
rw_vsetopts (const char *opts, va_list va)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   292
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   293
    if (0 == opts) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   294
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   295
        rw_clear_opts ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   296
        return 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   297
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   298
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   299
    rw_set_myopts ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   300
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   301
    const char *next = opts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   302
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   303
    for ( ; ; ++ncmdopts) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   304
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   305
        while (' ' == *next)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   306
            ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   307
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   308
        if ('\0' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   309
            break;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   310
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   311
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   312
        if (ncmdopts == optbufsize) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   313
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   314
            const size_t newbufsize = 2 * ncmdopts + 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   315
            
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   316
            cmdopts_t* const newopts =
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   317
                (cmdopts_t*)malloc (newbufsize * sizeof (cmdopts_t));
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   318
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   319
            if (0 == newopts) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   320
                fprintf (stderr, "%s%d: failed to allocate memory\n",
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   321
                         __FILE__, __LINE__);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   322
                abort ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   323
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   324
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   325
            memcpy (newopts, cmdopts, ncmdopts * sizeof (cmdopts_t));
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   326
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   327
            if (cmdopts != cmdoptbuf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   328
                free (cmdopts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   329
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   330
            cmdopts    = newopts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   331
            optbufsize = newbufsize;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   332
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   333
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   334
        // clear the next option info
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   335
        memset (cmdopts + ncmdopts, 0, sizeof *cmdopts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   336
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   337
        if ('|' != *next)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   338
            cmdopts [ncmdopts].sopt_ = *next++;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   339
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   340
        if ('|' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   341
            const char* end = strpbrk (++next, "|@:=*!# ");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   342
            if (0 == end)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   343
                end = next + strlen (next);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   344
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   345
            // copy the option name up to but not including the delimiter
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   346
            // (except when the delimiter is the equals sign ('='), which
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   347
            // becomes the last character of the option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   348
            const size_t optlen = size_t (end - next) + ('=' == *end);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   349
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   350
            char *lopt = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   351
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   352
            if (optlen < sizeof cmdopts [ncmdopts].loptbuf_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   353
                lopt = cmdopts [ncmdopts].loptbuf_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   354
            else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   355
                lopt = (char*)malloc (optlen + 1);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   356
                cmdopts [ncmdopts].lopt_ = lopt;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   357
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   358
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   359
            memcpy (lopt, next, optlen);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   360
            lopt [optlen] = '\0';
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   361
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   362
            next = end;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   363
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   364
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   365
        // only the first occurrence of each command line option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   366
        // causes an invocation of the callback, all subsequent
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   367
        // ones will be ignored by default
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   368
        cmdopts [ncmdopts].maxcalls_ = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   369
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   370
        int arg_is_callback = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   371
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   372
        if ('#' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   373
            // insead of a pointer to a callback, the argument
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   374
            // is a pointer to an int counter that is to be
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   375
            // incremented for each occurrence of the option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   376
            // during processing; when the option is immediately
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   377
            // followed by the equals sign ('=') and a numeric
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   378
            // argument the value of the argument will be stored
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   379
            arg_is_callback = false;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   380
            ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   381
            
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   382
            // an unlimited number of occurrences of the option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   383
            // are allowed and will be counted
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   384
            cmdopts [ncmdopts].maxcalls_ = _RWSTD_SIZE_MAX;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   385
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   386
        else if (':' == *next || '=' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   387
            // ':' : argument optional
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   388
            // '=' : argument required
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   389
            cmdopts [ncmdopts].arg_ = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   390
            ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   391
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   392
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   393
        if ('@' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   394
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   395
            ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   396
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   397
            // at most how many occurrences of an option can be processed?
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   398
            if ('*' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   399
                // unlimited
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   400
                cmdopts [ncmdopts].maxcalls_ = _RWSTD_SIZE_MAX;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   401
                ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   402
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   403
            else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   404
                // at most this many
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   405
                char *end;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   406
                cmdopts [ncmdopts].maxcalls_ = strtoul (next, &end, 10);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   407
                next = end;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   408
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   409
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   410
        else if ('!' == *next) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   411
            cmdopts [ncmdopts].inv_ = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   412
            ++next;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   413
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   414
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   415
        if (arg_is_callback) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   416
            // retrieve the callback and verify it's not null
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   417
            // (null callback is permitted in the special case when
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   418
            // the short option is '-', i.e., when setting up or
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   419
            // resetting an "unknown option" handler)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   420
            cmdopts [ncmdopts].callback_ = va_arg (va, optcallback_t*);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   421
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   422
        else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   423
            // retrieve the address of the int counter where to keep
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   424
            // track of the number of occurrences of the option, or
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   425
            // where to store the value of the numeric argument of
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   426
            // the option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   427
            cmdopts [ncmdopts].pcntr_ = va_arg (va, int*);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   428
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   429
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   430
        if (   '-' != cmdopts [ncmdopts].sopt_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   431
            && 0 == cmdopts [ncmdopts].callback_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   432
            && 0 == cmdopts [ncmdopts].pcntr_) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   433
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   434
            // get a pointer to the long option name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   435
            const char* const lopt = cmdopts [ncmdopts].lopt_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   436
                ? cmdopts [ncmdopts].lopt_ : cmdopts [ncmdopts].loptbuf_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   437
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   438
            if (*lopt)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   439
                fprintf (stderr, "null handler for option -%s\n", lopt);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   440
            else
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   441
                fprintf (stderr, "null handler for option -%c\n",
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   442
                         cmdopts [ncmdopts].sopt_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   443
                
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   444
            abort ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   445
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   446
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   447
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   448
    return int (ncmdopts - ndefopts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   449
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   450
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   451
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   452
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   453
_TEST_EXPORT int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   454
rw_setopts (const char *opts, ...)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   455
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   456
    va_list va;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   457
    va_start (va, opts);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   458
    const int result = rw_vsetopts (opts, va);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   459
    va_end (va);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   460
    return result;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   461
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   462
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   463
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   464
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   465
_TEST_EXPORT int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   466
rw_runopts (int argc, char *argv[])
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   467
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   468
    rw_set_myopts ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   469
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   470
    static int recursive = false;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   471
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   472
    // ignore options set in the environment?
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   473
    int ignenv = recursive;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   474
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   475
    // return status
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   476
    int status = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   477
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   478
    // number of options processed
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   479
    int nopts = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   480
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   481
    // index of registered option whose callback should be invoked
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   482
    // for command line options that do not match any other
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   483
    size_t not_found_inx = _RWSTD_SIZE_MAX;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   484
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   485
    // iterate over the command line arguments until a callback
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   486
    // returns a non-zero value or until all options have been
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   487
    // successfully processed
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   488
    for (int i = 0; i < argc && argv [i] && 0 == status; ++i) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   489
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   490
        if (0 == strcmp ("--ignore-environment", argv [i])) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   491
            // ignore options set in the environment
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   492
            ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   493
            continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   494
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   495
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   496
        if (0 == strcmp ("--", argv [i])) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   497
            // "--" terminates options, everything
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   498
            // after it is treated as an argument
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   499
            break;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   500
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   501
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   502
        // the name of the option without the leading dash
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   503
        const char* const optname = argv [i] + 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   504
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   505
        // look for the first equals sign
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   506
        const char* const eq = strchr (optname, '=');
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   507
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   508
        // compute the length of the option including the equals sign (if any)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   509
        const size_t optlen = eq ? size_t (eq - optname + 1) : strlen (optname);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   510
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   511
        int found = false;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   512
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   513
        // look up each command line option (i.e., a string that starts
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   514
        // with a dash ('-')) and invoke the callback associated with it
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   515
        for (size_t j = 0; j != ncmdopts; ++j) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   516
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   517
            if ('-' == cmdopts [j].sopt_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   518
                not_found_inx = j;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   519
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   520
            if ('-' == argv [i][0]) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   521
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   522
                const size_t cmplen =
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   523
                    eq && cmdopts [j].pcntr_ ? optlen - 1 : optlen;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   524
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   525
                // get a pointer to the (possibly empty) name
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   526
                // of the long option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   527
                const char* const lopt = cmdopts [j].lopt_ ? 
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   528
                    cmdopts [j].lopt_ : cmdopts [j].loptbuf_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   529
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   530
                // try to match the long option first, and only if it
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   531
                // doesn't match try the short single-character option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   532
                if (   cmplen == strlen (lopt)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   533
                    && 0 == memcmp (optname, lopt, cmplen)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   534
                    || cmdopts [j].sopt_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   535
                    && optname [0] == cmdopts [j].sopt_
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   536
                    && (1 == optlen || cmdopts [j].arg_)) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   537
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   538
                    // matching option has been found
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   539
                    found = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   540
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   541
                    // ignore the option if invoked recursively (by processing
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   542
                    // options set in the environment) and the option has
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   543
                    // already been seen (this prevents duplicate processing
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   544
                    // of options that are set both on the command line and
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   545
                    // in the environment and allows option with an argument
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   546
                    // set on the command line to override those set in the
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   547
                    // environment)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   548
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   549
                    if (cmdopts [j].ncalls_ && recursive)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   550
                        continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   551
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   552
                    // if the option has been evaluated the maximum number
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   553
                    // of times, avoid evaluating it and continue processing
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   554
                    if (cmdopts [j].maxcalls_ <= cmdopts [j].ncalls_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   555
                        continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   556
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   557
                    if (cmdopts [j].callback_) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   558
                        if (!cmdopts [j].inv_) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   559
                            // when the command line argument matched
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   560
                            // the option,  invoke the callback function
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   561
                            status = cmdopts [j].callback_ (argc - i, argv + i);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   562
                        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   563
                    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   564
                    else if (eq) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   565
                        assert (0 != cmdopts [j].pcntr_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   566
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   567
                        // obtain the numeric argument
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   568
                        char *end = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   569
                        const long optval = strtol (eq + 1, &end, 0);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   570
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   571
                        if (end && '\0' != *end) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   572
                            fprintf (stderr, "expected numeric argument: %s\n",
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   573
                                     optname);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   574
                            ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   575
                            errno  = EINVAL;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   576
                            status = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   577
                        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   578
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   579
#if _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   580
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   581
                        else if (   optval < _RWSTD_INT_MIN
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   582
                                 || _RWSTD_INT_MAX < optval) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   583
                            fprintf (stderr, "numeric argument %ld out of range"
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   584
                                     " [%d, %d]: %s\n", optval,
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   585
                                     _RWSTD_INT_MIN, _RWSTD_INT_MAX, optname);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   586
                            ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   587
                            errno  = EINVAL;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   588
                            status = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   589
                        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   590
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   591
#endif   // _RWSTD_INT_SIZE < _RWSTD_LONG_SIZE
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   592
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   593
                        else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   594
                            *cmdopts [j].pcntr_ = optval;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   595
                        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   596
                    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   597
                    else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   598
                        assert (0 != cmdopts [j].pcntr_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   599
                        ++*cmdopts [j].pcntr_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   600
                    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   601
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   602
                    ++cmdopts [j].ncalls_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   603
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   604
                    if (recursive)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   605
                        cmdopts [j].envseen_ = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   606
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   607
                    ++nopts;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   608
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   609
                    if (status) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   610
                        // when the status returned from the last callback
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   611
                        // is non-0 stop further processing (including
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   612
                        // any options set in the environment) and return
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   613
                        // status to the caller
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   614
                        ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   615
                        break;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   616
                    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   617
                }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   618
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   619
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   620
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   621
        if (!found && '-' == argv [i][0]) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   622
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   623
            // invoke the appropriate error handler for an option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   624
            // that was not found
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   625
            if (_RWSTD_SIZE_MAX != not_found_inx) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   626
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   627
                // invoke the error handler set up through rw_setopts()
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   628
                // and let the handler decide whether to go on processing
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   629
                // other options or whether to abort
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   630
                status = cmdopts [not_found_inx].callback_ (argc - i, argv + i);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   631
                if (status) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   632
                    // no further processing done
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   633
                    ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   634
                    break;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   635
                }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   636
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   637
            else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   638
                // print an error message to stderr when no error
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   639
                // handler has been set up
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   640
                fprintf (stderr, "unknown option: %s\n", argv [i]);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   641
                ignenv = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   642
                errno  = EINVAL;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   643
                status = 1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   644
                break;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   645
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   646
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   647
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   648
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   649
    if (!ignenv) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   650
        // process options from the environment
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   651
        const char* const envar = getenv ("RWSTD_TESTOPTS");
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   652
        if (envar) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   653
            recursive = true;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   654
            rw_runopts (envar);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   655
            recursive = false;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   656
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   657
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   658
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   659
    // invoke any inverted callbacks or bump their user-specified counters,
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   660
    // and reset internal counters indicating if/how many times each option
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   661
    // has been processed
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   662
    for (size_t j = 0; j != ncmdopts; ++j) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   663
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   664
        if (cmdopts [j].inv_ && 0 == cmdopts [j].ncalls_ && 0 == status) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   665
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   666
            if (cmdopts [j].callback_)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   667
                status = cmdopts [j].callback_ (0, 0);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   668
            else {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   669
                assert (0 != cmdopts [j].pcntr_);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   670
                ++*cmdopts [j].pcntr_;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   671
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   672
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   673
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   674
        cmdopts [j].ncalls_  = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   675
        cmdopts [j].envseen_ = false;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   676
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   677
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   678
    return status;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   679
}
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   680
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   681
/**************************************************************************/
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   682
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   683
_TEST_EXPORT int
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   684
rw_runopts (const char *str)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   685
{
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   686
    assert (0 != str);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   687
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   688
    rw_set_myopts ();
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   689
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   690
    char buf [80];      // fixed size buffer to copy `str' into
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   691
    char *pbuf = buf;   // a modifiable copy of `str'
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   692
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   693
    size_t len = strlen (str);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   694
    if (len >= sizeof buf) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   695
        // allocate if necessary
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   696
        pbuf = (char*)malloc (len + 1);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   697
        if (!pbuf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   698
            return -1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   699
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   700
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   701
    // copy `str' to modifiable buffer
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   702
    memcpy (pbuf, str, len + 1);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   703
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   704
    char *tmp_argv_buf [32] = { 0 };   // fixed size argv buffer
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   705
    char **argv = tmp_argv_buf;        // array of arguments
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   706
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   707
    // initial size of argument array (will grow as necessary)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   708
    size_t argv_size = sizeof tmp_argv_buf / sizeof *tmp_argv_buf;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   709
    size_t argc = 0;   // number of arguments in array
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   710
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   711
    int in_quotes = 0;   // quoted argument being processed
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   712
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   713
    for (char *s = pbuf; *s; ++s) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   714
        if ('"' == *s) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   715
            in_quotes = !in_quotes;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   716
            continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   717
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   718
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   719
        if (in_quotes)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   720
            continue;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   721
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   722
        // split up unquoted space-separated arguments
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   723
        if (argc == 0 || ' ' == *s) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   724
            if (argc > 0) 
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   725
                *s = 0;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   726
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   727
            // skip over leading spaces
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   728
            if (argc > 0 || ' ' == *s)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   729
                while (' ' == *++s);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   730
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   731
            if (*s) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   732
                if (argc == argv_size) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   733
                    // grow `argv' as necessary
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   734
                    char **tmp = (char**)malloc (sizeof *tmp * argv_size * 2);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   735
                    if (!tmp) {
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   736
                        if (argv != tmp_argv_buf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   737
                            free (argv);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   738
                        return -1;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   739
                    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   740
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   741
                    // copy existing elementes and zero out any new entries
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   742
                    memcpy (tmp, argv, sizeof *tmp * argv_size);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   743
                    memset (tmp + argv_size, 0, sizeof *tmp * argv_size);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   744
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   745
                    // free existing buffer if necessary
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   746
                    if (argv != tmp_argv_buf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   747
                        free (argv);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   748
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   749
                    // reassign buffer and increase size
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   750
                    argv       = tmp;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   751
                    argv_size *= 2;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   752
                }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   753
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   754
                // add argument to array
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   755
                argv [argc++] = s;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   756
            }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   757
        }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   758
    }
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   759
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   760
    // process `argc' options pointed to by `argv'
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   761
    const int status = rw_runopts (int (argc), argv);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   762
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   763
    // free buffers if necessary
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   764
    if (argv != tmp_argv_buf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   765
        free (argv);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   766
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   767
    if (pbuf != buf)
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   768
        free (pbuf);
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   769
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   770
    return status;
ce057bb09d0b Revert last code drop.
Pat Downey <patd@symbian.org>
parents:
diff changeset
   771
}