VirtualBox

Changeset 99246 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Mar 31, 2023 8:48:57 AM (22 months ago)
Author:
vboxsync
Message:

IPRT/RTGetOpt: Interpret non-breaking hypen and a handful other unicode dashes like the asci '-' when parsing command line, so that the manual, blog entries and such are free to use other dash variants for typesetting reasons w/o prevent the reader from copying & pasting the examples directly onto the command line. bugref:10302

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/getopt.cpp

    r98103 r99246  
    4949#include <iprt/message.h>
    5050#include <iprt/string.h>
     51#include <iprt/uni.h>
    5152#include <iprt/uuid.h>
    5253
     
    5556*   Defined Constants And Macros                                                                                                 *
    5657*********************************************************************************************************************************/
    57 #ifdef IN_RT_STATIC  /* We don't need full unicode case insensitive if we ASSUME basic latin only. */
    58 # define RTStrICmp  RTStrICmpAscii
    59 # define RTStrNICmp RTStrNICmpAscii
     58#ifdef IN_RT_STATIC /* We don't need full unicode case insensitive if we ASSUME basic latin only. */
     59# define RTUniCpToLower(a_uc)   ((RTUNICP)RT_C_TO_LOWER(a_uc))
     60# define RTUniCpToUpper(a_uc)   ((RTUNICP)RT_C_TO_UPPER(a_uc))
    6061#endif
    6162
     
    112113            unsigned char ch;
    113114            while ((ch = *psz++) != '\0')
    114                 Assert(ch <= 0x7f); /* ASSUMPTION that we can use RTStrICmpAscii and RTStrNICmpAscii. */
     115                Assert(ch <= 0x7f); /* ASSUMPTION that we can use also RTStrICmpAscii and RTStrNICmpAscii for static builds
     116                                       and that we don't need to use RTStrGetCp on pszLong strings. */
    115117        }
    116118    }
     
    160162
    161163#endif /* IPRT_GETOPT_WITHOUT_NETWORK_ADDRESSES */
     164
     165
     166/**
     167 * Checks if the given unicode codepoint is an alternative dash or not.
     168 *
     169 * ASSUMES caller checks for the ascii hypen-minus.
     170 *
     171 * @returns true / false.
     172 * @param   uc      The codepoint to check.
     173 */
     174DECLINLINE(bool) rtGetOptIsAlternativeDash(RTUNICP uc)
     175{
     176    return uc == 0x2011 /* non-breaking hypen */
     177        || uc == 0x2010 /* hypen */
     178        || uc == 0x2012 /* figure dash */
     179        || uc == 0x2013 /* en dash */
     180        || uc == 0x2014 /* em dash */
     181        || uc == 0x2212 /* minus sign */
     182        || uc == 0xfe58 /* small em dash */
     183        || uc == 0xfe63 /* small em hypen-minus */
     184        || uc == 0xff0d /* fullwidth hypen-minus */
     185        ;
     186}
     187
     188
     189/**
     190 * Checks if the given unicode codepoint is an any kind of dash.
     191 *
     192 * @returns true / false.
     193 * @param   uc      The codepoint to check.
     194 */
     195DECLINLINE(bool) rtGetOptIsDash(RTUNICP uc)
     196{
     197    return uc == (RTUNICP)'-' || rtGetOptIsAlternativeDash(uc);
     198}
     199
     200
     201/**
     202 * Compares a user specific argument with a RTGETOPTDEF long string, taking
     203 * RTGETOPT_FLAG_ICASE into account.
     204 *
     205 * This differs from strcmp/RTStrICmp in that it matches the minus-hyphen
     206 * (U+002D) codepoint in a RTGETOPTDEF string with non-breaking hyphen (U+2011)
     207 * and some others.  This allows copy & paste from manuals, documentation and
     208 * similar that needs to use the non-breaking variant for typographical reasons.
     209 *
     210 * @returns true if matches, false if not.
     211 * @param   pszUserArg          Ther user specified argument string.
     212 * @param   pszOption           The RTGETOPTDEF::pszLong string.
     213 * @param   fOptFlags           The RTGETOPTDEF::fFlags.
     214 * @param   cchMax              RT_STR_MAX if full string compare, otherwise
     215 *                              number of @a pszOption characters to compare.
     216 * @param   poffUserArgNext     Where to return offset of the first character
     217 *                              after the match in @a pszUserArg. Optional.
     218 */
     219static bool rtGetOptLongStrEquals(const char *pszUserArg, const char *pszOption, size_t cchMax, uint32_t fOptFlags,
     220                                  size_t *poffUserArgNext)
     221{
     222    const char * const pszUserArgStart = pszUserArg;
     223    while (cchMax-- > 0)
     224    {
     225        char const ch1 = *pszUserArg++;
     226        char const ch2 = *pszOption++;
     227        if (ch1 == ch2)
     228        {
     229            if (!ch1)
     230                break;
     231        }
     232        /* If the long option contains a dash, consider alternative unicode dashes
     233           like non-breaking and such. */
     234        else if (ch2 == '-')
     235        {
     236            if (!((unsigned char)ch1 & 0x80))
     237                return false;
     238
     239            pszUserArg--;
     240            RTUNICP uc;
     241            int rc = RTStrGetCpEx(&pszUserArg, &uc);
     242            AssertRCReturn(rc, false);
     243
     244            if (!rtGetOptIsAlternativeDash(uc))
     245                return false;
     246        }
     247        /* Do case folding if configured for this option. */
     248        else if (!(fOptFlags & RTGETOPT_FLAG_ICASE))
     249            return false;
     250        else
     251        {
     252            pszUserArg--;
     253            RTUNICP uc;
     254            int rc = RTStrGetCpEx(&pszUserArg, &uc);
     255            AssertRCReturn(rc, false);
     256
     257            if (   RTUniCpToLower(uc) != (RTUNICP)RT_C_TO_LOWER(ch2)
     258                && RTUniCpToUpper(uc) != (RTUNICP)RT_C_TO_UPPER(ch2))
     259                return false;
     260        }
     261    }
     262    if (poffUserArgNext)
     263        *poffUserArgNext = (size_t)(pszUserArg - pszUserArgStart);
     264    return true;
     265}
     266
     267
     268/**
     269 * Skips the optional dash for options with the RTGETOPT_FLAG_INDEX_DEF_DASH
     270 * flag.
     271 */
     272static size_t rtGetOptSkipIndexDefDash(const char *pszOption, size_t cchLong)
     273{
     274    const char *pszNext = &pszOption[cchLong];
     275    RTUNICP     uc;
     276    int rc = RTStrGetCpEx(&pszNext, &uc);
     277    AssertRCReturn(rc, cchLong);
     278
     279    /* given "--long" we match "--long-1" but not "--long-". */
     280    if (   rtGetOptIsDash(uc)
     281        && RT_C_IS_DIGIT(*pszNext))
     282        return (size_t)(pszNext - pszOption);
     283
     284    return cchLong;
     285}
     286
    162287
    163288/**
     
    169294 * @param   cOptions        Number of items in the array.
    170295 * @param   fFlags          Init flags.
    171  */
    172 static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags)
     296 * @param   pcchMatch       Where to return the length of the matching option
     297 *                          section, including any RTGETOPT_FLAG_INDEX_DEF_DASH
     298 *                          dash, but _not_ the actual index or value separator.
     299 */
     300static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags,
     301                                        size_t *pcchMatch)
    173302{
    174303    PCRTGETOPTDEF pOpt = paOptions;
     
    191320                 */
    192321                size_t cchLong = strlen(pOpt->pszLong);
    193                 if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    194                     || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    195                         && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    196                 {
    197                     if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
    198                         && pszOption[cchLong] == '-'
    199                         && RT_C_IS_DIGIT(pszOption[cchLong + 1])) /* given "--long" we match "--long-1" but not "--long-". */
    200                         cchLong++;
     322                if (rtGetOptLongStrEquals(pszOption, pOpt->pszLong, cchLong, fOptFlags, &cchLong))
     323                {
     324                    if (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     325                        cchLong = rtGetOptSkipIndexDefDash(pszOption, cchLong);
     326                    size_t const cchMatch = cchLong;
    201327                    if (fOptFlags & RTGETOPT_FLAG_INDEX)
    202328                        while (RT_C_IS_DIGIT(pszOption[cchLong]))
     
    205331                        || pszOption[cchLong] == ':'
    206332                        || pszOption[cchLong] == '=')
     333                    {
     334                        *pcchMatch = cchMatch;
    207335                        return pOpt;
     336                    }
    208337                }
    209338            }
     
    215344                 */
    216345                size_t cchLong = strlen(pOpt->pszLong);
    217                 if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    218                     || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    219                         && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    220                 {
    221                     if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
    222                         && pszOption[cchLong] == '-'
    223                         && RT_C_IS_DIGIT(pszOption[cchLong + 1]))
    224                         cchLong++;
     346                if (rtGetOptLongStrEquals(pszOption, pOpt->pszLong, cchLong, fOptFlags, &cchLong))
     347                {
     348                    if (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     349                        cchLong = rtGetOptSkipIndexDefDash(pszOption, cchLong);
     350                    size_t const cchMatch = cchLong;
    225351                    while (RT_C_IS_DIGIT(pszOption[cchLong]))
    226352                        cchLong++;
    227353                    if (pszOption[cchLong] == '\0')
     354                    {
     355                        *pcchMatch = cchMatch;
    228356                        return pOpt;
    229                 }
    230             }
    231             else if (   !strcmp(pszOption, pOpt->pszLong)
    232                      || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    233                          && !RTStrICmp(pszOption, pOpt->pszLong)))
     357                    }
     358                }
     359            }
     360            else if (rtGetOptLongStrEquals(pszOption, pOpt->pszLong, RTSTR_MAX, fOptFlags, NULL))
    234361                return pOpt;
    235362        }
     
    239366    if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS))
    240367        for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++)
    241             if (   !strcmp(pszOption, g_aStdOptions[i].pszLong)
    242                 || (   g_aStdOptions[i].fFlags & RTGETOPT_FLAG_ICASE
    243                     && !RTStrICmp(pszOption, g_aStdOptions[i].pszLong)))
     368        {
     369            size_t cchMatch = 0;
     370            if (rtGetOptLongStrEquals(pszOption, g_aStdOptions[i].pszLong, RTSTR_MAX, g_aStdOptions[i].fFlags, &cchMatch))
     371            {
     372                *pcchMatch = cchMatch;
    244373                return &g_aStdOptions[i];
     374            }
     375        }
    245376
    246377    return NULL;
     
    306437
    307438        case RTGETOPT_REQ_BOOL:
    308             if (   !RTStrICmp(pszValue, "true")
    309                 || !RTStrICmp(pszValue, "t")
    310                 || !RTStrICmp(pszValue, "yes")
    311                 || !RTStrICmp(pszValue, "y")
    312                 || !RTStrICmp(pszValue, "enabled")
    313                 || !RTStrICmp(pszValue, "enable")
    314                 || !RTStrICmp(pszValue, "en")
    315                 || !RTStrICmp(pszValue, "e")
    316                 || !RTStrICmp(pszValue, "on")
    317                 || !RTStrCmp(pszValue, "1")
    318                 )
     439        {
     440            static struct RTGETOPTUPPERLOWERBOOL
     441            {
     442                bool        f;
     443                const char *pszLower;
     444                const char *pszUpper;
     445                const char *pszMarkers; /**< characters with '+' are okay to stop after, '-' aren't.*/
     446            } const s_aKeywords[] =
     447            {
     448                { true,  "true",      "TRUE",       "+--+"     },
     449                { true,  "yes",       "YES",        "+-+"      },
     450                { true,  "enabled",   "ENABLED",    "++---++"  },
     451                { true,  "on",        "ON",         "-+"       },
     452                { true,  "1",         "1",          "+"        },
     453                { false, "false",     "FALSE",      "+---+"    },
     454                { false, "no",        "NO",         "++"       },
     455                { false, "disabled",  "DISABLED",   "+-+---++" },
     456                { false, "off",       "OFF",        "--+"      },
     457                { false, "0",         "0",          "+"        },
     458            };
     459            for (size_t i = 0; i < RT_ELEMENTS(s_aKeywords); i++)
     460                for (size_t off = 0;; off++)
     461                {
     462                    char const ch = pszValue[off];
     463                    if (!ch)
     464                    {
     465                        if (off > 0 && s_aKeywords[i].pszMarkers[off - 1] == '+')
     466                        {
     467                            pValueUnion->f = s_aKeywords[i].f;
     468                            return VINF_SUCCESS;
     469                        }
     470                        break;
     471                    }
     472                    if (   s_aKeywords[i].pszLower[off] != ch
     473                        && s_aKeywords[i].pszUpper[off] != ch)
     474                        break;
     475                }
     476            pValueUnion->psz = pszValue;
     477            return VERR_GETOPT_UNKNOWN_OPTION;
     478        }
     479
     480        case RTGETOPT_REQ_BOOL_ONOFF:
     481            if (   (pszValue[0] == 'o' || pszValue[0] == 'O')
     482                && (pszValue[1] == 'n' || pszValue[1] == 'N')
     483                &&  pszValue[2] == '\0')
    319484                pValueUnion->f = true;
    320             else if (   !RTStrICmp(pszValue, "false")
    321                      || !RTStrICmp(pszValue, "f")
    322                      || !RTStrICmp(pszValue, "no")
    323                      || !RTStrICmp(pszValue, "n")
    324                      || !RTStrICmp(pszValue, "disabled")
    325                      || !RTStrICmp(pszValue, "disable")
    326                      || !RTStrICmp(pszValue, "dis")
    327                      || !RTStrICmp(pszValue, "d")
    328                      || !RTStrICmp(pszValue, "off")
    329                      || !RTStrCmp(pszValue, "0")
    330                      )
    331                 pValueUnion->f = false;
    332             else
    333             {
    334                 pValueUnion->psz = pszValue;
    335                 return VERR_GETOPT_UNKNOWN_OPTION;
    336             }
    337             break;
    338 
    339         case RTGETOPT_REQ_BOOL_ONOFF:
    340             if (!RTStrICmp(pszValue, "on"))
    341                 pValueUnion->f = true;
    342             else if (!RTStrICmp(pszValue, "off"))
     485            else if (   (pszValue[0] == 'o' || pszValue[0] == 'O')
     486                     && (pszValue[1] == 'f' || pszValue[1] == 'F')
     487                     && (pszValue[2] == 'f' || pszValue[2] == 'F')
     488                     &&  pszValue[3] == '\0')
    343489                pValueUnion->f = false;
    344490            else
     
    567713    int             iThis;
    568714    const char     *pszArgThis;
     715    size_t          cchMatch;
    569716    PCRTGETOPTDEF   pOpt;
    570717
     
    580727            return VERR_GETOPT_UNKNOWN_OPTION;
    581728        }
    582         pState->pszNextShort++;
    583         pszArgThis = pState->pszNextShort - 2;
     729        pszArgThis = pState->pszNextShort++;
     730        cchMatch = 1;
    584731        iThis = pState->iNext;
    585732        fShort = true;
     
    619766             * get mixed up with short ones.
    620767             */
    621             pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags);
    622             if (    !pOpt
    623                 &&  pszArgThis[0] == '-'
    624                 &&  pszArgThis[1] != '-'
    625                 &&  pszArgThis[1] != '\0')
    626             {
    627                 pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags);
    628                 fShort = pOpt != NULL;
    629             }
    630             else
    631                 fShort = false;
     768            pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags, &cchMatch);
     769            fShort = false;
     770            if (!pOpt)
     771            {
     772                const char *pszNext = pszArgThis;
     773                RTUNICP     uc;
     774                int         vrc = RTStrGetCpEx(&pszNext, &uc);
     775                AssertRCReturn(vrc, vrc);
     776                char        chNext;
     777                if (   rtGetOptIsDash(uc)
     778                    && (chNext = *pszNext) != '-'
     779                    && chNext != '\0'
     780                    && !((unsigned char)chNext & 0x80))
     781                {
     782                    pOpt = rtGetOptSearchShort(chNext, pState->paOptions, pState->cOptions, pState->fFlags);
     783                    if (pOpt)
     784                    {
     785                        cchMatch = (size_t)(&pszNext[1] - pszArgThis);
     786                        fShort  = true;
     787                    }
     788                }
     789            }
    632790
    633791            /* Look for dash-dash. */
    634             if (!pOpt && !strcmp(pszArgThis, "--"))
     792            if (!pOpt && rtGetOptLongStrEquals(pszArgThis, "--", RTSTR_MAX, 0, NULL))
    635793            {
    636794                rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
     
    644802                if (pOpt)
    645803                    rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
    646                 else if (*pszArgThis == '-')
     804                else if (rtGetOptIsDash(RTStrGetCp(pszArgThis)))
    647805                {
    648806                    pValueUnion->psz = pszArgThis;
     
    685843            if (fShort)
    686844            {
    687                 if (pszArgThis[2] == '\0')
     845                if (pszArgThis[cchMatch] == '\0')
    688846                {
    689847                    if (iThis + 1 >= pState->argc)
     
    694852                }
    695853                else /* same argument. */
    696                     pszValue = &pszArgThis[2  + (pszArgThis[2] == ':' || pszArgThis[2] == '=')];
     854                    pszValue = &pszArgThis[cchMatch + (pszArgThis[cchMatch] == ':' || pszArgThis[cchMatch] == '=')];
    697855                if (pState->pszNextShort)
    698856                {
     
    703861            else
    704862            {
    705                 size_t cchLong = strlen(pOpt->pszLong);
    706863                if (fOptFlags & RTGETOPT_FLAG_INDEX)
    707864                {
    708                     if (   pszArgThis[cchLong] != '\0'
     865                    if (   pszArgThis[cchMatch] != '\0'
    709866                        || (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK))
    710867                    {
    711                         if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
    712                             && pszArgThis[cchLong] == '-')
    713                             cchLong++;
    714 
    715                         uint32_t uIndex;
    716                         char *pszRet = NULL;
    717                         int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex);
     868                        const char *pszNext = &pszArgThis[cchMatch];
     869                        uint32_t    uIndex;
     870                        int rc = RTStrToUInt32Ex(pszNext, (char **)&pszNext, 10, &uIndex);
    718871                        if (   rc == VERR_NO_DIGITS
    719872                            && (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK))
    720873                        {
    721874                            uIndex = ((fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) >> RTGETOPT_FLAG_INDEX_DEF_SHIFT) - 1;
    722                             rc = pszRet[0] == '\0' ? VINF_SUCCESS : VWRN_TRAILING_CHARS;
     875                            rc = pszNext[0] == '\0' ? VINF_SUCCESS : VWRN_TRAILING_CHARS;
    723876                        }
    724877                        if (rc == VWRN_TRAILING_CHARS)
    725878                        {
    726                             if (   pszRet[0] != ':'
    727                                 && pszRet[0] != '=')
     879                            if (   pszNext[0] != ':'
     880                                && pszNext[0] != '=')
    728881                                return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    729882                            pState->uIndex = uIndex;
    730                             pszValue = pszRet + 1;
     883                            pszValue = pszNext + 1;
    731884                        }
    732885                        else if (rc == VINF_SUCCESS)
     
    747900                else
    748901                {
    749                     if (pszArgThis[cchLong] == '\0')
     902                    if (pszArgThis[cchMatch] == '\0')
    750903                    {
    751904                        if (iThis + 1 + pState->cNonOptions >= pState->argc)
     
    756909                    }
    757910                    else /* same argument. */
    758                         pszValue = &pszArgThis[cchLong + 1];
     911                        pszValue = &pszArgThis[cchMatch + 1];
    759912                }
    760913            }
     
    773926             * state variables for the start and end cases.
    774927             */
    775             if (pszArgThis[2])
     928            if (pszArgThis[cchMatch])
    776929            {
    777930                if (!pState->pszNextShort)
    778931                {
    779932                    /* start */
    780                     pState->pszNextShort = &pszArgThis[2];
     933                    pState->pszNextShort = &pszArgThis[cchMatch];
    781934                    pState->iNext--;
    782935                }
     
    791944        else if (fOptFlags & RTGETOPT_FLAG_INDEX)
    792945        {
    793             size_t   cchLong = strlen(pOpt->pszLong);
    794946            uint32_t uIndex;
    795             if (pszArgThis[cchLong] != '\0')
    796             {
    797                 if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
    798                     && pszArgThis[cchLong] == '-')
    799                     cchLong++;
    800                 if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)
     947            if (pszArgThis[cchMatch] != '\0')
     948            {
     949                if (RTStrToUInt32Full(&pszArgThis[cchMatch], 10, &uIndex) == VINF_SUCCESS)
    801950                    pState->uIndex = uIndex;
    802951                else
  • trunk/src/VBox/Runtime/testcase/tstRTGetOpt.cpp

    r98103 r99246  
    222222        "--optpair64", "0x128",
    223223
     224        /* various utf-8 dashes: */
     225#define DASH_HYPHEN             "\xE2\x80\x90"  // U+2010
     226#define DASH_NON_BREAKING       "\xE2\x80\x91"  // U+2011
     227#define DASH_FIGURE             "\xE2\x80\x92"  // U+2012
     228#define DASH_EN                 "\xE2\x80\x93"  // U+2013
     229#define DASH_EM                 "\xE2\x80\x94"  // U+2014
     230#define DASH_MINUS_SIGN         "\xE2\x88\x92"  // U+2212
     231#define DASH_SMALL_EM           "\xEF\xB9\x98"  // U+fe58
     232#define DASH_SMALL_HYPEN_MINUS  "\xEF\xB9\xA3"  // U+fe63
     233#define DASH_FULLWIDTH          "\xEF\xBC\x8D"  // U+ff0d
     234        DASH_HYPHEN DASH_NON_BREAKING "quiet",
     235        DASH_FIGURE DASH_EN "boolean" DASH_EM "dash" DASH_MINUS_SIGN "idx" DASH_FULLWIDTH "2", "off",
     236        DASH_NON_BREAKING "qV",
     237        DASH_SMALL_EM DASH_SMALL_HYPEN_MINUS "boolean1index42",    "on",
     238        DASH_NON_BREAKING DASH_FULLWIDTH "indexnovalue2",
     239
    224240        /* done */
    225241        NULL
     
    514530    CHECK(Val.PairU64.uFirst == 0x128);
    515531    CHECK(Val.PairU64.uSecond == UINT64_MAX);
     532
     533    /* various utf-8 dashes: */
     534    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 384, 1);
     535    CHECK_pDef(s_aOpts2, 4);
     536
     537    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 2);
     538    CHECK(!Val.f);
     539    CHECK(GetState.uIndex == 2);
     540
     541    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 0);
     542    CHECK_pDef(s_aOpts2, 3);
     543    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1);
     544
     545    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 414, 2);
     546    CHECK(Val.f);
     547    CHECK(GetState.uIndex == 42);
     548
     549    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 403, 1);
     550    CHECK(GetState.uIndex == 2);
    516551
    517552    /* the end */
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