Changeset 26485 in vbox for trunk/src/VBox/Runtime/common/misc
- Timestamp:
- Feb 14, 2010 6:59:06 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 57654
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/getopt.cpp
r25323 r26485 5 5 6 6 /* 7 * Copyright (C) 2007 Sun Microsystems, Inc.7 * Copyright (C) 2007-2010 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 44 44 45 45 46 /******************************************************************************* 47 * Global Variables * 48 *******************************************************************************/ 49 /** 50 * Standard options that gets included unless RTGETOPTINIT_FLAGS_NO_STD_OPTS is 51 * set. 52 */ 53 static 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 46 64 47 65 RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv, … … 49 67 int iFirst, uint32_t fFlags) 50 68 { 51 AssertReturn(! fFlags, VERR_INVALID_PARAMETER);69 AssertReturn(!(fFlags & ~(RTGETOPTINIT_FLAGS_OPTS_FIRST | RTGETOPTINIT_FLAGS_NO_STD_OPTS)), VERR_INVALID_PARAMETER); 52 70 53 71 pState->argv = argv; … … 58 76 pState->pszNextShort = NULL; 59 77 pState->pDef = NULL; 78 pState->uIndex = UINT32_MAX; 79 pState->fFlags = fFlags; 80 pState->cNonOptions = 0; 60 81 61 82 /* validate the options. */ … … 68 89 } 69 90 70 /** @todo Add an flag for sorting the arguments so that all the options comes71 * first. */72 91 return VINF_SUCCESS; 73 92 } … … 180 199 * @param paOptions Option array. 181 200 * @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 */ 203 static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags) 184 204 { 185 205 PCRTGETOPTDEF pOpt = paOptions; … … 233 253 pOpt++; 234 254 } 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 235 261 return NULL; 236 262 } … … 244 270 * @param paOptions Option array. 245 271 * @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 */ 274 static PCRTGETOPTDEF rtGetOptSearchShort(int chOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags) 248 275 { 249 276 PCRTGETOPTDEF pOpt = paOptions; … … 253 280 return pOpt; 254 281 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]; 255 291 } 256 292 return NULL; … … 395 431 396 432 433 /** 434 * Moves one argv option entries. 435 * 436 * @param papszTo Destination. 437 * @param papszFrom Source. 438 */ 439 static 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 397 451 RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion) 398 452 { … … 408 462 pValueUnion->u64 = 0; 409 463 pValueUnion->pDef = NULL; 410 411 /** @todo Handle '--' (end of options).*/412 /** @todo Add a flag to RTGetOptInit for handling the various help options in413 * a common way. (-?,-h,-help,--help,++) */414 /** @todo Add a flag to RTGetOptInit for handling the standard version options415 * in a common way. (-V,--version) */416 464 417 465 /* … … 428 476 * We've got short options left over from the previous call. 429 477 */ 430 pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions );478 pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags); 431 479 if (!pOpt) 432 480 { … … 442 490 { 443 491 /* 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. 445 494 */ 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 } 467 569 } 468 570 … … 492 594 if (iThis + 1 >= pState->argc) 493 595 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]); 495 598 pState->iNext++; 496 599 } … … 528 631 return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; 529 632 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]); 531 635 pState->iNext++; 532 636 } … … 541 645 if (iThis + 1 >= pState->argc) 542 646 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]); 544 649 pState->iNext++; 545 650 } … … 600 705 * fail with unkown option, and if it doesn't we'll return it as a non-option. 601 706 */ 602 603 707 if (*pszArgThis == '-') 604 708 { … … 635 739 return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; 636 740 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)]; 638 742 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]); 639 746 640 747 return rtGetOptProcessValue(fFlags, pszValue, pValueUnion);
Note:
See TracChangeset
for help on using the changeset viewer.