Changeset 96729 in vbox
- Timestamp:
- Sep 14, 2022 9:14:53 AM (2 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/getopt.h
r96407 r96729 130 130 /** The index value is attached to the argument - only valid for long arguments. */ 131 131 #define RTGETOPT_FLAG_INDEX RT_BIT(19) 132 /** Used with RTGETOPT_FLAG_INDEX, setting index to zero if none given. 133 * (The default is to fail with VERR_GETOPT_INDEX_MISSING.) */ 134 #define RTGETOPT_FLAG_INDEX_DEF_0 RT_BIT(20) 135 /** Used with RTGETOPT_FLAG_INDEX, setting index to one if none given. 136 * (The default is to fail with VERR_GETOPT_INDEX_MISSING.) */ 137 #define RTGETOPT_FLAG_INDEX_DEF_1 RT_BIT(21) 138 /** For simplicity. */ 139 #define RTGETOPT_FLAG_INDEX_DEF_MASK (RT_BIT(20) | RT_BIT(21)) 140 /** For simple conversion. */ 141 #define RTGETOPT_FLAG_INDEX_DEF_SHIFT 20 142 /** For use with RTGETOPT_FLAG_INDEX_DEF_0 or RTGETOPT_FLAG_INDEX_DEF_1 to 143 * imply a dash before the index when a digit is specified. 144 * This is for transitioning from options without index to optionally allow 145 * index options, i.e. "--long" defaults to either index 1 or 1 using the above 146 * flags, while "--long-1" explicitly gives the index ("--long-" is not valid). 147 * This flag matches an "-" separating the "--long" string 148 * (RTGETOPTDEFS::pszLong) from the index value. */ 149 #define RTGETOPT_FLAG_INDEX_DEF_DASH RT_BIT(22) 132 150 /** Treat the long option as case insensitive. */ 133 #define RTGETOPT_FLAG_ICASE RT_BIT(2 0)151 #define RTGETOPT_FLAG_ICASE RT_BIT(23) 134 152 /** Mask of valid bits - for validation. */ 135 153 #define RTGETOPT_VALID_MASK ( RTGETOPT_REQ_MASK \ … … 138 156 | RTGETOPT_FLAG_DEC \ 139 157 | RTGETOPT_FLAG_INDEX \ 140 | RTGETOPT_FLAG_ICASE) 158 | RTGETOPT_FLAG_INDEX_DEF_0 \ 159 | RTGETOPT_FLAG_INDEX_DEF_1 \ 160 | RTGETOPT_FLAG_INDEX_DEF_DASH \ 161 | RTGETOPT_FLAG_ICASE ) 141 162 /** @} */ 142 163 … … 165 186 * 166 187 * What ends up here depends on argument format in the option definition. 167 *168 * @remarks Integers will bet put in the \a i and \a u members and sign/zero extended169 * according to the signedness indicated by the \a fFlags. So, you can choose170 * use which ever of the integer members for accessing the value regardless171 * of restrictions indicated in the \a fFlags.172 188 */ 173 189 typedef union RTGETOPTUNION -
trunk/src/VBox/Runtime/common/misc/getopt.cpp
r96407 r96729 102 102 { 103 103 Assert(!(paOptions[i].fFlags & ~RTGETOPT_VALID_MASK)); 104 Assert( !(paOptions[i].fFlags & (RTGETOPT_FLAG_INDEX_DEF_MASK | RTGETOPT_FLAG_INDEX_DEF_DASH)) 105 || (paOptions[i].fFlags & RTGETOPT_FLAG_INDEX) ); 104 106 Assert(paOptions[i].iShort > 0); 105 107 Assert(paOptions[i].iShort != VINF_GETOPT_NOT_OPTION); … … 175 177 if (pOpt->pszLong) 176 178 { 177 if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) 179 uint32_t const fOptFlags = pOpt->fFlags; 180 if ((fOptFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) 178 181 { 179 182 /* … … 189 192 size_t cchLong = strlen(pOpt->pszLong); 190 193 if ( !strncmp(pszOption, pOpt->pszLong, cchLong) 191 || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE194 || ( (fOptFlags & RTGETOPT_FLAG_ICASE) 192 195 && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong))) 193 196 { 194 if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) 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++; 201 if (fOptFlags & RTGETOPT_FLAG_INDEX) 195 202 while (RT_C_IS_DIGIT(pszOption[cchLong])) 196 203 cchLong++; … … 201 208 } 202 209 } 203 else if ( pOpt->fFlags & RTGETOPT_FLAG_INDEX)210 else if (fOptFlags & RTGETOPT_FLAG_INDEX) 204 211 { 205 212 /* … … 209 216 size_t cchLong = strlen(pOpt->pszLong); 210 217 if ( !strncmp(pszOption, pOpt->pszLong, cchLong) 211 || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE218 || ( (fOptFlags & RTGETOPT_FLAG_ICASE) 212 219 && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong))) 213 220 { 221 if ( (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH) 222 && pszOption[cchLong] == '-' 223 && RT_C_IS_DIGIT(pszOption[cchLong + 1])) 224 cchLong++; 214 225 while (RT_C_IS_DIGIT(pszOption[cchLong])) 215 226 cchLong++; … … 219 230 } 220 231 else if ( !strcmp(pszOption, pOpt->pszLong) 221 || ( pOpt->fFlags & RTGETOPT_FLAG_ICASE232 || ( (fOptFlags & RTGETOPT_FLAG_ICASE) 222 233 && !RTStrICmp(pszOption, pOpt->pszLong))) 223 234 return pOpt; … … 660 671 pValueUnion->pDef = pOpt; /* in case of no value or error. */ 661 672 662 if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) 673 uint32_t const fOptFlags = pOpt->fFlags; 674 if ((fOptFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) 663 675 { 664 676 /* … … 692 704 { 693 705 size_t cchLong = strlen(pOpt->pszLong); 694 if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) 695 { 696 697 if (pszArgThis[cchLong] == '\0') 698 return VERR_GETOPT_INDEX_MISSING; 699 700 uint32_t uIndex; 701 char *pszRet = NULL; 702 int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex); 703 if (rc == VWRN_TRAILING_CHARS) 706 if (fOptFlags & RTGETOPT_FLAG_INDEX) 707 { 708 if ( pszArgThis[cchLong] != '\0' 709 || (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK)) 704 710 { 705 if ( pszRet[0] != ':' 706 && pszRet[0] != '=') 707 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; 708 pState->uIndex = uIndex; 709 pszValue = pszRet + 1; 710 } 711 else if (rc == VINF_SUCCESS) 712 { 713 if (iThis + 1 + pState->cNonOptions >= pState->argc) 714 return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; 715 pState->uIndex = uIndex; 716 pszValue = pState->argv[iThis + pState->cNonOptions + 1]; 717 rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); 718 pState->iNext++; 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); 718 if ( rc == VERR_NO_DIGITS 719 && (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK)) 720 { 721 uIndex = ((fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) >> RTGETOPT_FLAG_INDEX_DEF_SHIFT) - 1; 722 rc = pszRet[0] == '\0' ? VINF_SUCCESS : VWRN_TRAILING_CHARS; 723 } 724 if (rc == VWRN_TRAILING_CHARS) 725 { 726 if ( pszRet[0] != ':' 727 && pszRet[0] != '=') 728 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; 729 pState->uIndex = uIndex; 730 pszValue = pszRet + 1; 731 } 732 else if (rc == VINF_SUCCESS) 733 { 734 if (iThis + 1 + pState->cNonOptions >= pState->argc) 735 return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; 736 pState->uIndex = uIndex; 737 pszValue = pState->argv[iThis + pState->cNonOptions + 1]; 738 rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); 739 pState->iNext++; 740 } 741 else 742 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ 719 743 } 720 744 else 721 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */745 return VERR_GETOPT_INDEX_MISSING; 722 746 } 723 747 else … … 739 763 * Set up the ValueUnion. 740 764 */ 741 int rc = rtGetOptProcessValue( pOpt->fFlags, pszValue, pValueUnion);765 int rc = rtGetOptProcessValue(fOptFlags, pszValue, pValueUnion); 742 766 if (RT_FAILURE(rc)) 743 767 return rc; … … 765 789 } 766 790 } 767 else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) 768 { 769 size_t cchLong = strlen(pOpt->pszLong); 770 if (pszArgThis[cchLong] == '\0') 791 else if (fOptFlags & RTGETOPT_FLAG_INDEX) 792 { 793 size_t cchLong = strlen(pOpt->pszLong); 794 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) 801 pState->uIndex = uIndex; 802 else 803 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ 804 } 805 else if (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) 806 uIndex = ((fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) >> RTGETOPT_FLAG_INDEX_DEF_SHIFT) - 1; 807 else 771 808 return VERR_GETOPT_INDEX_MISSING; 772 773 uint32_t uIndex;774 if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)775 pState->uIndex = uIndex;776 else777 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */778 809 } 779 810 -
trunk/src/VBox/Runtime/testcase/tstRTGetOpt.cpp
r96407 r96729 119 119 { "--optpair32", 411, RTGETOPT_REQ_UINT32_OPTIONAL_PAIR }, 120 120 { "--optpair64", 412, RTGETOPT_REQ_UINT64_OPTIONAL_PAIR }, 121 { "--boolean0index", 413, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_0 }, 122 { "--boolean1index", 414, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_1 }, 123 { "--boolean-dash-idx", 415, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_0 | RTGETOPT_FLAG_INDEX_DEF_DASH }, 121 124 }; 122 125 … … 191 194 "--booleanindex7", "off", 192 195 "--booleanindex9", "invalid", 196 197 /* bool on/off with optional index */ 198 "--boolean0index9", "on", 199 "--boolean0index", "off", 200 "--boolean1index42", "off", 201 "--boolean1index", "on", 202 "--boolean-dash-idx", "off", 203 "--boolean-dash-idx-2", "on", 204 "--boolean-dash-idx-3=off", 205 "--boolean-dash-idx:on", 193 206 194 207 /* standard options */ … … 437 450 CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2); 438 451 CHECK(RT_VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid")); 452 453 /* bool on/off with optional indexed argument */ 454 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 413, 2); 455 CHECK(Val.f); 456 CHECK(GetState.uIndex == 9); 457 458 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 413, 2); 459 CHECK(!Val.f); 460 CHECK(GetState.uIndex == 0); 461 462 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 414, 2); 463 CHECK(!Val.f); 464 CHECK(GetState.uIndex == 42); 465 466 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 414, 2); 467 CHECK(Val.f); 468 CHECK(GetState.uIndex == 1); 469 470 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 2); 471 CHECK(!Val.f); 472 CHECK(GetState.uIndex == 0); 473 474 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 2); 475 CHECK(Val.f); 476 CHECK(GetState.uIndex == 2); 477 478 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 1); 479 CHECK(!Val.f); 480 CHECK(GetState.uIndex == 3); 481 482 CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 1); 483 CHECK(Val.f); 484 CHECK(GetState.uIndex == 0); 439 485 440 486 /* standard options. */
Note:
See TracChangeset
for help on using the changeset viewer.