VirtualBox

Ignore:
Timestamp:
Feb 14, 2010 6:59:06 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
57654
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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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);
Note: See TracChangeset for help on using the changeset viewer.

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