VirtualBox

Changeset 26485 in vbox


Ignore:
Timestamp:
Feb 14, 2010 6:59:06 AM (15 years ago)
Author:
vboxsync
Message:

iprt/getopt: Added two standard options: h: --help/-help/-h/-?, V: --version,-version,-V. These can be disabled by giving using RTGETOPTINIT_FLAGS_NO_STD_OPTS. Added another init flag, RTGETOPTINIT_FLAGS_OPTS_FIRST, for making RTGetOpt return options first and then non-options. Converted tstGetOpt to RTTest.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/getopt.h

    r26476 r26485  
    205205    /** The index of an index option, otherwise UINT32_MAX. */
    206206    uint32_t        uIndex;
    207     /* More members will be added later for dealing with initial
    208        call, optional sorting, '--' and so on. */
     207    /** The flags passed to RTGetOptInit.  */
     208    uint32_t        fFlags;
     209    /** Number of non-options that we're skipping during a sorted get.  The value
     210     * INT32_MAX is used to indicate that there are no more options.  This is used
     211     * to implement '--'.   */
     212    int32_t         cNonOptions;
     213
     214    /* More members may be added later for dealing with new features. */
    209215} RTGETOPTSTATE;
    210216/** Pointer to RTGetOpt state. */
     
    235241                         PCRTGETOPTDEF paOptions, size_t cOptions,
    236242                         int iFirst, uint32_t fFlags);
     243
     244/** @name RTGetOptInit flags.
     245 * @{ */
     246/** Sort the arguments so that options comes first, then non-options. */
     247#define RTGETOPTINIT_FLAGS_OPTS_FIRST   RT_BIT_32(0)
     248/** Prevent add the standard version and help options:
     249 *     - "--help", "-h" and "-?" returns 'h'.
     250 *     - "--version" and "-V" return 'V'.
     251 */
     252#define RTGETOPTINIT_FLAGS_NO_STD_OPTS  RT_BIT_32(1)
     253/** @} */
    237254
    238255/**
  • trunk/src/VBox/Runtime/common/misc/getopt.cpp

    r25323 r26485  
    55
    66/*
    7  * Copyright (C) 2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2007-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4444
    4545
     46/*******************************************************************************
     47*   Global Variables                                                           *
     48*******************************************************************************/
     49/**
     50 * Standard options that gets included unless RTGETOPTINIT_FLAGS_NO_STD_OPTS is
     51 * set.
     52 */
     53static RTGETOPTDEF const g_aStdOptions[] =
     54{
     55    {  "--help",        'h',    RTGETOPT_REQ_NOTHING },
     56    {  "-help",         'h',    RTGETOPT_REQ_NOTHING },
     57    {  "--version",     'V',    RTGETOPT_REQ_NOTHING },
     58    {  "-version",      'V',    RTGETOPT_REQ_NOTHING },
     59};
     60/** The index of --help in g_aStdOptions.  Used for some trickery.  */
     61#define RTGETOPT_STD_OPTIONS_HELP_IDX   0
     62
     63
    4664
    4765RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv,
     
    4967                         int iFirst, uint32_t fFlags)
    5068{
    51     AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
     69    AssertReturn(!(fFlags & ~(RTGETOPTINIT_FLAGS_OPTS_FIRST | RTGETOPTINIT_FLAGS_NO_STD_OPTS)), VERR_INVALID_PARAMETER);
    5270
    5371    pState->argv         = argv;
     
    5876    pState->pszNextShort = NULL;
    5977    pState->pDef         = NULL;
     78    pState->uIndex       = UINT32_MAX;
     79    pState->fFlags       = fFlags;
     80    pState->cNonOptions  = 0;
    6081
    6182    /* validate the options. */
     
    6889    }
    6990
    70     /** @todo Add an flag for sorting the arguments so that all the options comes
    71      *        first. */
    7291    return VINF_SUCCESS;
    7392}
     
    180199 * @param   paOptions       Option array.
    181200 * @param   cOptions        Number of items in the array.
    182  */
    183 static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions)
     201 * @param   fFlags          Init flags.
     202 */
     203static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags)
    184204{
    185205    PCRTGETOPTDEF pOpt = paOptions;
     
    233253        pOpt++;
    234254    }
     255
     256    if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS))
     257        for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++)
     258            if (!strcmp(pszOption, g_aStdOptions[i].pszLong))
     259                return &g_aStdOptions[i];
     260
    235261    return NULL;
    236262}
     
    244270 * @param   paOptions       Option array.
    245271 * @param   cOptions        Number of items in the array.
    246  */
    247 static PCRTGETOPTDEF rtGetOptSearchShort(int chOption, PCRTGETOPTDEF paOptions, size_t cOptions)
     272 * @param   fFlags          Init flags.
     273 */
     274static PCRTGETOPTDEF rtGetOptSearchShort(int chOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags)
    248275{
    249276    PCRTGETOPTDEF pOpt = paOptions;
     
    253280            return pOpt;
    254281        pOpt++;
     282    }
     283
     284    if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS))
     285    {
     286        for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++)
     287            if (g_aStdOptions[i].iShort == chOption)
     288                return &g_aStdOptions[i];
     289        if (chOption == '?')
     290            return &g_aStdOptions[RTGETOPT_STD_OPTIONS_HELP_IDX];
    255291    }
    256292    return NULL;
     
    395431
    396432
     433/**
     434 * Moves one argv option entries.
     435 *
     436 * @param   papszTo             Destination.
     437 * @param   papszFrom           Source.
     438 */
     439static void rtGetOptMoveArgvEntries(char **papszTo, char **papszFrom)
     440{
     441    if (papszTo != papszFrom)
     442    {
     443        Assert((uintptr_t)papszTo < (uintptr_t)papszFrom);
     444        char * const pszMoved = papszFrom[0];
     445        memmove(&papszTo[1], &papszTo[0], (uintptr_t)papszFrom - (uintptr_t)papszTo);
     446        papszTo[0] = pszMoved;
     447    }
     448}
     449
     450
    397451RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion)
    398452{
     
    408462    pValueUnion->u64 = 0;
    409463    pValueUnion->pDef = NULL;
    410 
    411     /** @todo Handle '--' (end of options).*/
    412     /** @todo Add a flag to RTGetOptInit for handling the various help options in
    413      *        a common way. (-?,-h,-help,--help,++) */
    414     /** @todo Add a flag to RTGetOptInit for handling the standard version options
    415      *        in a common way. (-V,--version) */
    416464
    417465    /*
     
    428476         * We've got short options left over from the previous call.
    429477         */
    430         pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions);
     478        pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags);
    431479        if (!pOpt)
    432480        {
     
    442490    {
    443491        /*
    444          * Pop off the next argument.
     492         * Pop off the next argument.  Sorting options and dealing with the
     493         * dash-dash makes this a little extra complicated.
    445494         */
    446         if (pState->iNext >= pState->argc)
    447             return 0;
    448         iThis = pState->iNext++;
    449         pszArgThis = pState->argv[iThis];
    450 
    451         /*
    452          * Do a long option search first and then a short option one.
    453          * This way we can make sure single dash long options doesn't
    454          * get mixed up with short ones.
    455          */
    456         pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions);
    457         if (    !pOpt
    458             &&  pszArgThis[0] == '-'
    459             &&  pszArgThis[1] != '-'
    460             &&  pszArgThis[1] != '\0')
    461         {
    462             pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions);
    463             fShort = pOpt != NULL;
    464         }
    465         else
    466             fShort = false;
     495        for (;;)
     496        {
     497            if (pState->iNext >= pState->argc)
     498                return 0;
     499
     500            if (pState->cNonOptions)
     501            {
     502                if (pState->cNonOptions == INT32_MAX)
     503                {
     504                    pValueUnion->psz = pState->argv[pState->iNext++];
     505                    return VINF_GETOPT_NOT_OPTION;
     506                }
     507
     508                if (pState->iNext + pState->cNonOptions >= pState->argc)
     509                {
     510                    pState->cNonOptions = INT32_MAX;
     511                    continue;
     512                }
     513            }
     514
     515            iThis = pState->iNext++;
     516            pszArgThis = pState->argv[iThis + pState->cNonOptions];
     517
     518            /*
     519             * Do a long option search first and then a short option one.
     520             * This way we can make sure single dash long options doesn't
     521             * get mixed up with short ones.
     522             */
     523            pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags);
     524            if (    !pOpt
     525                &&  pszArgThis[0] == '-'
     526                &&  pszArgThis[1] != '-'
     527                &&  pszArgThis[1] != '\0')
     528            {
     529                pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags);
     530                fShort = pOpt != NULL;
     531            }
     532            else
     533                fShort = false;
     534
     535            /* Look for dash-dash. */
     536            if (!pOpt && !strcmp(pszArgThis, "--"))
     537            {
     538                rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
     539                pState->cNonOptions = INT32_MAX;
     540                continue;
     541            }
     542
     543            /* Options first hacks. */
     544            if (pState->fFlags & RTGETOPTINIT_FLAGS_OPTS_FIRST)
     545            {
     546                if (pOpt)
     547                    rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
     548                else if (*pszArgThis == '-')
     549                {
     550                    pValueUnion->psz = pszArgThis;
     551                    return VERR_GETOPT_UNKNOWN_OPTION;
     552                }
     553                else
     554                {
     555                    /* not an option, add it to the non-options and try again. */
     556                    pState->iNext--;
     557                    pState->cNonOptions++;
     558
     559                    /* Switch to returning non-options if we've reached the end. */
     560                    if (pState->iNext + pState->cNonOptions >= pState->argc)
     561                        pState->cNonOptions = INT32_MAX;
     562                    continue;
     563                }
     564            }
     565
     566            /* done */
     567            break;
     568        }
    467569    }
    468570
     
    492594                    if (iThis + 1 >= pState->argc)
    493595                        return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    494                     pszValue = pState->argv[iThis + 1];
     596                    pszValue = pState->argv[iThis + pState->cNonOptions + 1];
     597                    rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    495598                    pState->iNext++;
    496599                }
     
    528631                            return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    529632                        pState->uIndex = uIndex;
    530                         pszValue = pState->argv[iThis + 1];
     633                        pszValue = pState->argv[iThis + pState->cNonOptions + 1];
     634                        rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    531635                        pState->iNext++;
    532636                    }
     
    541645                        if (iThis + 1 >= pState->argc)
    542646                            return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    543                         pszValue = pState->argv[iThis + 1];
     647                        pszValue = pState->argv[iThis + pState->cNonOptions + 1];
     648                        rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    544649                        pState->iNext++;
    545650                    }
     
    600705     * fail with unkown option, and if it doesn't we'll return it as a non-option.
    601706     */
    602 
    603707    if (*pszArgThis == '-')
    604708    {
     
    635739        return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    636740    int         iThis    = pState->iNext++;
    637     const char *pszValue = pState->argv[iThis];
     741    const char *pszValue = pState->argv[iThis + (pState->cNonOptions != INT32_MAX ? pState->cNonOptions : 0)];
    638742    pValueUnion->pDef    = pOpt; /* in case of no value or error. */
     743
     744    if (pState->cNonOptions && pState->cNonOptions != INT32_MAX)
     745        rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
    639746
    640747    return rtGetOptProcessValue(fFlags, pszValue, pValueUnion);
  • trunk/src/VBox/Runtime/testcase/tstGetOpt.cpp

    r25323 r26485  
    3535#include <iprt/net.h>
    3636#include <iprt/getopt.h>
    37 #include <iprt/stream.h>
    38 #include <iprt/initterm.h>
     37
     38#include <iprt/err.h>
    3939#include <iprt/string.h>
    40 #include <iprt/err.h>
     40#include <iprt/test.h>
    4141
    4242
    4343int main()
    4444{
    45     int cErrors = 0;
    46     RTR3Init();
    47     RTPrintf("tstGetOpt: TESTING...\n");
     45    RTTEST hTest;
     46    int rc = RTTestInitAndCreate("tstRTGetOpt", &hTest);
     47    if (rc)
     48        return rc;
    4849
    4950    RTGETOPTSTATE GetState;
    5051    RTGETOPTUNION Val;
    51 #define CHECK(expr)  do { if (!(expr)) { RTPrintf("tstGetOpt: error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); cErrors++; } } while (0)
     52#define CHECK(expr)  do { if (!(expr)) { RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); } } while (0)
    5253#define CHECK2(expr, fmt) \
    5354    do { \
    5455        if (!(expr)) { \
    55             RTPrintf("tstGetOpt: error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); \
    56             RTPrintf fmt; \
    57             cErrors++; \
     56            RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); \
     57            RTTestIFailureDetails fmt; \
    5858         } \
    5959    } while (0)
     
    6565    do { \
    6666        const int iPrev = GetState.iNext; \
    67         const int rc = (expr); \
    68         CHECK2(rc == (chRet), ("got %d, expected %d\n", rc, (chRet))); \
     67        const int rcGetOpt = (expr); \
     68        CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \
    6969        CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \
    7070        GetState.iNext = (iInc) + iPrev; \
    7171    } while (0)
    7272
     73#define CHECK_GETOPT_STR(expr, chRet, iInc, str) \
     74    do { \
     75        const int iPrev = GetState.iNext; \
     76        const int rcGetOpt = (expr); \
     77        CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \
     78        CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \
     79        CHECK2(VALID_PTR(Val.psz) && !strcmp(Val.psz, (str)), ("got %s, expected %s\n", Val.psz, (str))); \
     80        GetState.iNext = (iInc) + iPrev; \
     81    } while (0)
     82
    7383
    7484    /*
    7585     * The basics.
    7686     */
     87    RTTestSub(hTest, "Basics");
    7788    static const RTGETOPTDEF s_aOpts2[] =
    7889    {
     
    157168        "--threevalues",     "1",          "0xC",          "thirdvalue",
    158169
     170        /* bool on/off */
    159171        "--boolean",         "on",
    160172        "--boolean",         "off",
     
    164176        "--booleanindex9",   "invalid",
    165177
     178        /* standard options */
     179        "--help",
     180        "-help",
     181        "-?",
     182        "-h",
     183        "--version",
     184        "-version",
     185        "-V",
     186
     187        /* done */
    166188        NULL
    167189    };
     
    240262
    241263    /* IPv4 */
     264    RTTestSub(hTest, "RTGetOpt - IPv4");
    242265    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'g', 1);
    243266    CHECK(Val.IPv4Addr.u == RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(192,168,1,1))));
    244267
    245268    /* Ethernet MAC address. */
     269    RTTestSub(hTest, "RTGetOpt - MAC Address");
    246270    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'm', 1);
    247271    CHECK(   Val.MacAddr.au8[0] == 0x08
     
    260284
    261285    /* string with indexed argument */
     286    RTTestSub(hTest, "RTGetOpt - Option w/ Index");
    262287    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 2);
    263288    CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string4"));
     
    304329
    305330    /* RTGetOptFetchValue tests */
     331    RTTestSub(hTest, "RTGetOptFetchValue");
    306332    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 405, 2);
    307333    CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "firstvalue"));
     
    343369
    344370    /* bool on/off tests */
     371    RTTestSub(hTest, "RTGetOpt - bool on/off");
    345372    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 408, 2);
    346373    CHECK(Val.f);
     
    360387    CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid"));
    361388
     389    /* standard options. */
     390    RTTestSub(hTest, "Standard options");
     391    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1);
     392    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1);
     393    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1);
     394    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1);
     395    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1);
     396    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1);
     397    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1);
     398
    362399    /* the end */
    363400    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0);
     
    365402    CHECK(argc2 == GetState.iNext);
    366403
     404    /*
     405     * Options first.
     406     */
     407    RTTestSub(hTest, "Options first");
     408    const char *argv3[] =
     409    {
     410        "foo1",
     411        "-s",               "string1",
     412        "foo2",
     413        "--optwithstring",  "string2",
     414        "foo3",
     415        "-i",               "-42",
     416        "foo4",
     417        "-i:-42",
     418        "-i=-42",
     419        "foo5",
     420        "foo6",
     421        "foo7",
     422        "-i:",              "-42",
     423        "-i=",              "-42",
     424        "foo8",
     425        "--twovalues",       "firstvalue", "secondvalue",
     426        "foo9",
     427        "--twovalues:firstvalue",          "secondvalue",
     428        "foo10",
     429        "--",
     430        "--optwithstring",
     431        "foo11",
     432        "foo12",
     433
     434        /* done */
     435        NULL
     436    };
     437    int argc3 = (int)RT_ELEMENTS(argv3) - 1;
     438
     439    CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc3, (char **)argv3, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0,
     440                                  RTGETOPTINIT_FLAGS_OPTS_FIRST)));
     441
     442    /* -s */
     443    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1");
     444    CHECK(GetState.uIndex == UINT32_MAX);
     445    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2");
     446    CHECK(GetState.uIndex == UINT32_MAX);
     447
     448    /* -i */
     449    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     450    CHECK(Val.i32 == -42);
     451    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1);
     452    CHECK(Val.i32 == -42);
     453    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1);
     454    CHECK(Val.i32 == -42);
     455    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     456    CHECK(Val.i32 == -42);
     457    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     458    CHECK(Val.i32 == -42);
     459
     460    /* --twovalues */
     461    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue");
     462    CHECK(GetState.uIndex == UINT32_MAX);
     463    CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue");
     464    CHECK(GetState.uIndex == UINT32_MAX);
     465
     466    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue");
     467    CHECK(GetState.uIndex == UINT32_MAX);
     468    CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue");
     469    CHECK(GetState.uIndex == UINT32_MAX);
     470
     471    /* -- */
     472    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 2, "foo1");
     473    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2");
     474    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3");
     475    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4");
     476    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5");
     477    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6");
     478    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7");
     479    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8");
     480    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9");
     481    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10");
     482    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "--optwithstring");
     483    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11");
     484    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12");
     485
     486    /* the end */
     487    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0);
     488    CHECK(Val.pDef == NULL);
     489    CHECK(argc3 == GetState.iNext);
     490
     491    /*
     492     * Options first, part 2: No dash-dash.
     493     */
     494    const char *argv4[] =
     495    {
     496        "foo1",
     497        "-s",               "string1",
     498        "foo2",
     499        "--optwithstring",  "string2",
     500        "foo3",
     501        "-i",               "-42",
     502        "foo4",
     503        "-i:-42",
     504        "-i=-42",
     505        "foo5",
     506        "foo6",
     507        "foo7",
     508        "-i:",              "-42",
     509        "-i=",              "-42",
     510        "foo8",
     511        "--twovalues",       "firstvalue", "secondvalue",
     512        "foo9",
     513        "--twovalues:firstvalue",          "secondvalue",
     514        "foo10",
     515        "foo11",
     516        "foo12",
     517
     518        /* done */
     519        NULL
     520    };
     521    int argc4 = (int)RT_ELEMENTS(argv4) - 1;
     522
     523    CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc4, (char **)argv4, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0,
     524                                  RTGETOPTINIT_FLAGS_OPTS_FIRST)));
     525
     526    /* -s */
     527    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1");
     528    CHECK(GetState.uIndex == UINT32_MAX);
     529    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2");
     530    CHECK(GetState.uIndex == UINT32_MAX);
     531
     532    /* -i */
     533    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     534    CHECK(Val.i32 == -42);
     535    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1);
     536    CHECK(Val.i32 == -42);
     537    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1);
     538    CHECK(Val.i32 == -42);
     539    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     540    CHECK(Val.i32 == -42);
     541    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2);
     542    CHECK(Val.i32 == -42);
     543
     544    /* --twovalues */
     545    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue");
     546    CHECK(GetState.uIndex == UINT32_MAX);
     547    CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue");
     548    CHECK(GetState.uIndex == UINT32_MAX);
     549
     550    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue");
     551    CHECK(GetState.uIndex == UINT32_MAX);
     552    CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue");
     553    CHECK(GetState.uIndex == UINT32_MAX);
     554
     555    /* -- */
     556    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo1");
     557    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2");
     558    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3");
     559    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4");
     560    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5");
     561    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6");
     562    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7");
     563    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8");
     564    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9");
     565    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10");
     566    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11");
     567    CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12");
     568
     569    /* the end */
     570    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0);
     571    CHECK(Val.pDef == NULL);
     572    CHECK(argc4 == GetState.iNext);
     573
     574
    367575
    368576    /*
    369577     * Summary.
    370578     */
    371     if (!cErrors)
    372         RTPrintf("tstGetOpt: SUCCESS\n");
    373     else
    374         RTPrintf("tstGetOpt: FAILURE - %d errors\n", cErrors);
    375 
    376     return !!cErrors;
     579    return RTTestSummaryAndDestroy(hTest);
    377580}
    378581
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette