1 /* $NetBSD: autoopts.c,v 1.2 2012/02/03 21:36:40 christos Exp $ */ 2 3 4 /** 5 * \file autoopts.c 6 * 7 * Time-stamp: "2011-03-25 17:55:07 bkorb" 8 * 9 * This file contains all of the routines that must be linked into 10 * an executable to use the generated option processing. The optional 11 * routines are in separately compiled modules so that they will not 12 * necessarily be linked in. 13 * 14 * This file is part of AutoOpts, a companion to AutoGen. 15 * AutoOpts is free software. 16 * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved 17 * 18 * AutoOpts is available under any one of two licenses. The license 19 * in use must be one of these two and the choice is under the control 20 * of the user of the license. 21 * 22 * The GNU Lesser General Public License, version 3 or later 23 * See the files "COPYING.lgplv3" and "COPYING.gplv3" 24 * 25 * The Modified Berkeley Software Distribution License 26 * See the file "COPYING.mbsd" 27 * 28 * These files have the following md5sums: 29 * 30 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 31 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 32 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd 33 */ 34 35 #ifndef PKGDATADIR 36 # define PKGDATADIR "" 37 #endif 38 39 static char const zNil[] = ""; 40 static arg_types_t argTypes = { .pzStr = NULL }; 41 static char zOptFmtLine[16] = { NUL }; 42 static ag_bool displayEnum = AG_FALSE; 43 static char const pkgdatadir_default[] = PKGDATADIR; 44 static char const * program_pkgdatadir = pkgdatadir_default; 45 static tOptionLoadMode option_load_mode = OPTION_LOAD_UNCOOKED; 46 static tePagerState pagerState = PAGER_STATE_INITIAL; 47 48 FILE * option_usage_fp = NULL; 49 50 /* = = = START-STATIC-FORWARD = = = */ 51 static tSuccess 52 findOptDesc(tOptions* pOpts, tOptState* pOptState); 53 54 static tSuccess 55 next_opt_arg_must(tOptions* pOpts, tOptState* pOptState); 56 57 static tSuccess 58 next_opt_arg_may(tOptions* pOpts, tOptState* pOptState); 59 60 static tSuccess 61 next_opt_arg_none(tOptions* pOpts, tOptState* pOptState); 62 63 static tSuccess 64 nextOption(tOptions* pOpts, tOptState* pOptState); 65 66 static tSuccess 67 doPresets(tOptions* pOpts); 68 69 static int 70 checkConsistency(tOptions* pOpts); 71 /* = = = END-STATIC-FORWARD = = = */ 72 73 LOCAL void * 74 ao_malloc(size_t sz) 75 { 76 void * res = malloc(sz); 77 if (res == NULL) { 78 fprintf(stderr, zAO_Alloc, (int)sz); 79 exit(EXIT_FAILURE); 80 } 81 return res; 82 } 83 #undef malloc 84 #define malloc(_s) ao_malloc(_s) 85 86 LOCAL void * 87 ao_realloc(void *p, size_t sz) 88 { 89 void * res = (p == NULL) ? malloc(sz) : realloc(p, sz); 90 if (res == NULL) { 91 fprintf(stderr, zAO_Realloc, (int)sz, p); 92 exit(EXIT_FAILURE); 93 } 94 return res; 95 } 96 #undef realloc 97 #define realloc(_p,_s) ao_realloc(_p,_s) 98 99 LOCAL char * 100 ao_strdup(char const *str) 101 { 102 char * res = strdup(str); 103 if (res == NULL) { 104 fprintf(stderr, zAO_Strdup, (int)strlen(str)); 105 exit(EXIT_FAILURE); 106 } 107 return res; 108 } 109 #undef strdup 110 #define strdup(_p) ao_strdup(_p) 111 112 #ifndef HAVE_PATHFIND 113 # include "compat/pathfind.c" 114 #endif 115 116 #ifndef HAVE_SNPRINTF 117 # include "compat/snprintf.c" 118 #endif 119 120 #ifndef HAVE_STRDUP 121 # include "compat/strdup.c" 122 #endif 123 124 #ifndef HAVE_STRCHR 125 # include "compat/strchr.c" 126 #endif 127 128 /* 129 * handle_opt 130 * 131 * This routine handles equivalencing, sets the option state flags and 132 * invokes the handler procedure, if any. 133 */ 134 LOCAL tSuccess 135 handle_opt(tOptions* pOpts, tOptState* pOptState) 136 { 137 /* 138 * Save a copy of the option procedure pointer. 139 * If this is an equivalence class option, we still want this proc. 140 */ 141 tOptDesc* pOD = pOptState->pOD; 142 tOptProc* pOP = pOD->pOptProc; 143 if (pOD->fOptState & OPTST_ALLOC_ARG) 144 AGFREE(pOD->optArg.argString); 145 146 pOD->optArg.argString = pOptState->pzOptArg; 147 148 /* 149 * IF we are presetting options, then we will ignore any un-presettable 150 * options. They are the ones either marked as such. 151 */ 152 if ( ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0) 153 && ((pOD->fOptState & OPTST_NO_INIT) != 0) 154 ) 155 return PROBLEM; 156 157 /* 158 * IF this is an equivalence class option, 159 * THEN 160 * Save the option value that got us to this option 161 * entry. (It may not be pOD->optChar[0], if this is an 162 * equivalence entry.) 163 * set the pointer to the equivalence class base 164 */ 165 if (pOD->optEquivIndex != NO_EQUIVALENT) { 166 tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex; 167 168 /* 169 * IF the current option state has not been defined (set on the 170 * command line), THEN we will allow continued resetting of 171 * the value. Once "defined", then it must not change. 172 */ 173 if ((pOD->fOptState & OPTST_DEFINED) != 0) { 174 /* 175 * The equivalenced-to option has been found on the command 176 * line before. Make sure new occurrences are the same type. 177 * 178 * IF this option has been previously equivalenced and 179 * it was not the same equivalenced-to option, 180 * THEN we have a usage problem. 181 */ 182 if (p->optActualIndex != pOD->optIndex) { 183 fprintf(stderr, (const char*)zMultiEquiv, p->pz_Name, 184 pOD->pz_Name, 185 (pOpts->pOptDesc + p->optActualIndex)->pz_Name); 186 return FAILURE; 187 } 188 } else { 189 /* 190 * Set the equivalenced-to actual option index to no-equivalent 191 * so that we set all the entries below. This option may either 192 * never have been selected before, or else it was selected by 193 * some sort of "presetting" mechanism. 194 */ 195 p->optActualIndex = NO_EQUIVALENT; 196 } 197 198 if (p->optActualIndex != pOD->optIndex) { 199 /* 200 * First time through, copy over the state 201 * and add in the equivalence flag 202 */ 203 p->optActualValue = pOD->optValue; 204 p->optActualIndex = pOD->optIndex; 205 pOptState->flags |= OPTST_EQUIVALENCE; 206 } 207 208 /* 209 * Copy the most recent option argument. set membership state 210 * is kept in ``p->optCookie''. Do not overwrite. 211 */ 212 p->optArg.argString = pOD->optArg.argString; 213 pOD = p; 214 215 } else { 216 pOD->optActualValue = pOD->optValue; 217 pOD->optActualIndex = pOD->optIndex; 218 } 219 220 pOD->fOptState &= OPTST_PERSISTENT_MASK; 221 pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT_MASK); 222 223 /* 224 * Keep track of count only for DEFINED (command line) options. 225 * IF we have too many, build up an error message and bail. 226 */ 227 if ( (pOD->fOptState & OPTST_DEFINED) 228 && (++pOD->optOccCt > pOD->optMaxCt) ) { 229 230 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 231 char const * pzEqv = 232 (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil; 233 234 fputs(zErrOnly, stderr); 235 236 if (pOD->optMaxCt > 1) 237 fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv); 238 else 239 fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv); 240 } 241 242 return FAILURE; 243 } 244 245 /* 246 * If provided a procedure to call, call it 247 */ 248 if (pOP != NULL) 249 (*pOP)(pOpts, pOD); 250 251 return SUCCESS; 252 } 253 254 255 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 256 * 257 * HUNT FOR OPTIONS IN THE ARGUMENT LIST 258 * 259 * The next four procedures are "private" to nextOption(). 260 * nextOption() uses findOptDesc() to find the next descriptor and it, in 261 * turn, uses longOptionFind() and shortOptionFind() to actually do the hunt. 262 * 263 * longOptionFind 264 * 265 * Find the long option descriptor for the current option 266 */ 267 LOCAL tSuccess 268 longOptionFind(tOptions* pOpts, char* pzOptName, tOptState* pOptState) 269 { 270 ag_bool disable = AG_FALSE; 271 char* pzEq = strchr(pzOptName, '='); 272 tOptDesc* pOD = pOpts->pOptDesc; 273 int idx = 0; 274 int idxLim = pOpts->optCt; 275 int matchCt = 0; 276 int matchIdx = 0; 277 size_t nameLen; 278 char opt_name_buf[128]; 279 280 /* 281 * IF the value is attached to the name, 282 * copy it off so we can NUL terminate. 283 */ 284 if (pzEq != NULL) { 285 nameLen = (size_t)(pzEq - pzOptName); 286 if (nameLen >= sizeof(opt_name_buf)) 287 return FAILURE; 288 memcpy(opt_name_buf, pzOptName, nameLen); 289 opt_name_buf[nameLen] = NUL; 290 pzOptName = opt_name_buf; 291 pzEq++; 292 293 } else nameLen = strlen(pzOptName); 294 295 do { 296 /* 297 * If option disabled or a doc option, skip to next 298 */ 299 if (pOD->pz_Name == NULL) 300 continue; 301 302 if ( SKIP_OPT(pOD) 303 && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) 304 continue; 305 306 if (strneqvcmp(pzOptName, pOD->pz_Name, nameLen) == 0) { 307 /* 308 * IF we have a complete match 309 * THEN it takes priority over any already located partial 310 */ 311 if (pOD->pz_Name[ nameLen ] == NUL) { 312 matchCt = 1; 313 matchIdx = idx; 314 break; 315 } 316 } 317 318 /* 319 * IF there is a disable name 320 * *AND* no argument value has been supplied 321 * (disabled options may have no argument) 322 * *AND* the option name matches the disable name 323 * THEN ... 324 */ 325 else if ( (pOD->pz_DisableName != NULL) 326 && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0) 327 ) { 328 disable = AG_TRUE; 329 330 /* 331 * IF we have a complete match 332 * THEN it takes priority over any already located partial 333 */ 334 if (pOD->pz_DisableName[ nameLen ] == NUL) { 335 matchCt = 1; 336 matchIdx = idx; 337 break; 338 } 339 } 340 341 else 342 continue; 343 344 /* 345 * We found a partial match, either regular or disabling. 346 * Remember the index for later. 347 */ 348 matchIdx = idx; 349 350 if (++matchCt > 1) 351 break; 352 353 } while (pOD++, (++idx < idxLim)); 354 355 /* 356 * Make sure we either found an exact match or found only one partial 357 */ 358 if (matchCt == 1) { 359 pOD = pOpts->pOptDesc + matchIdx; 360 361 if (SKIP_OPT(pOD)) { 362 fprintf(stderr, zDisabledErr, pOpts->pzProgName, pOD->pz_Name); 363 if (pOD->pzText != NULL) 364 fprintf(stderr, " -- %s", pOD->pzText); 365 fputc('\n', stderr); 366 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 367 /* NOTREACHED */ 368 } 369 370 /* 371 * IF we found a disablement name, 372 * THEN set the bit in the callers' flag word 373 */ 374 if (disable) 375 pOptState->flags |= OPTST_DISABLED; 376 377 pOptState->pOD = pOD; 378 pOptState->pzOptArg = pzEq; 379 pOptState->optType = TOPT_LONG; 380 return SUCCESS; 381 } 382 383 /* 384 * IF there is no equal sign 385 * *AND* we are using named arguments 386 * *AND* there is a default named option, 387 * THEN return that option. 388 */ 389 if ( (pzEq == NULL) 390 && NAMED_OPTS(pOpts) 391 && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) { 392 pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt; 393 394 pOptState->pzOptArg = pzOptName; 395 pOptState->optType = TOPT_DEFAULT; 396 return SUCCESS; 397 } 398 399 /* 400 * IF we are to stop on errors (the default, actually) 401 * THEN call the usage procedure. 402 */ 403 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 404 fprintf(stderr, (matchCt == 0) ? zIllOptStr : zAmbigOptStr, 405 pOpts->pzProgPath, pzOptName); 406 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 407 } 408 409 return FAILURE; 410 } 411 412 413 /* 414 * shortOptionFind 415 * 416 * Find the short option descriptor for the current option 417 */ 418 LOCAL tSuccess 419 shortOptionFind(tOptions* pOpts, uint_t optValue, tOptState* pOptState) 420 { 421 tOptDesc* pRes = pOpts->pOptDesc; 422 int ct = pOpts->optCt; 423 424 /* 425 * Search the option list 426 */ 427 do { 428 if (optValue != pRes->optValue) 429 continue; 430 431 if (SKIP_OPT(pRes)) { 432 if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) 433 && (pRes->pz_Name != NULL)) { 434 fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name); 435 if (pRes->pzText != NULL) 436 fprintf(stderr, " -- %s", pRes->pzText); 437 fputc('\n', stderr); 438 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 439 /* NOTREACHED */ 440 } 441 goto short_opt_error; 442 } 443 444 pOptState->pOD = pRes; 445 pOptState->optType = TOPT_SHORT; 446 return SUCCESS; 447 448 } while (pRes++, --ct > 0); 449 450 /* 451 * IF the character value is a digit 452 * AND there is a special number option ("-n") 453 * THEN the result is the "option" itself and the 454 * option is the specially marked "number" option. 455 */ 456 if ( IS_DEC_DIGIT_CHAR(optValue) 457 && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) { 458 pOptState->pOD = \ 459 pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option; 460 (pOpts->pzCurOpt)--; 461 pOptState->optType = TOPT_SHORT; 462 return SUCCESS; 463 } 464 465 short_opt_error: 466 467 /* 468 * IF we are to stop on errors (the default, actually) 469 * THEN call the usage procedure. 470 */ 471 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 472 fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue); 473 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 474 } 475 476 return FAILURE; 477 } 478 479 480 /* 481 * findOptDesc 482 * 483 * Find the option descriptor for the current option 484 */ 485 static tSuccess 486 findOptDesc(tOptions* pOpts, tOptState* pOptState) 487 { 488 /* 489 * IF we are continuing a short option list (e.g. -xyz...) 490 * THEN continue a single flag option. 491 * OTHERWISE see if there is room to advance and then do so. 492 */ 493 if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL)) 494 return shortOptionFind(pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState); 495 496 if (pOpts->curOptIdx >= pOpts->origArgCt) 497 return PROBLEM; /* NORMAL COMPLETION */ 498 499 pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ]; 500 501 /* 502 * IF all arguments must be named options, ... 503 */ 504 if (NAMED_OPTS(pOpts)) { 505 char * pz = pOpts->pzCurOpt; 506 int def; 507 tSuccess res; 508 tAoUS * def_opt; 509 510 pOpts->curOptIdx++; 511 512 if (*pz != '-') 513 return longOptionFind(pOpts, pz, pOptState); 514 515 /* 516 * The name is prefixed with one or more hyphens. Strip them off 517 * and disable the "default_opt" setting. Use heavy recasting to 518 * strip off the "const" quality of the "default_opt" field. 519 */ 520 while (*(++pz) == '-') ; 521 def_opt = (void *)(intptr_t)&(pOpts->specOptIdx.default_opt); 522 def = *def_opt; 523 *def_opt = NO_EQUIVALENT; 524 res = longOptionFind(pOpts, pz, pOptState); 525 *def_opt = def; 526 return res; 527 } 528 529 /* 530 * Note the kind of flag/option marker 531 */ 532 if (*((pOpts->pzCurOpt)++) != '-') 533 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ 534 535 /* 536 * Special hack for a hyphen by itself 537 */ 538 if (*(pOpts->pzCurOpt) == NUL) 539 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ 540 541 /* 542 * The current argument is to be processed as an option argument 543 */ 544 pOpts->curOptIdx++; 545 546 /* 547 * We have an option marker. 548 * Test the next character for long option indication 549 */ 550 if (pOpts->pzCurOpt[0] == '-') { 551 if (*++(pOpts->pzCurOpt) == NUL) 552 /* 553 * NORMAL COMPLETION - NOT this arg, but rest are operands 554 */ 555 return PROBLEM; 556 557 /* 558 * We do not allow the hyphen to be used as a flag value. 559 * Therefore, if long options are not to be accepted, we punt. 560 */ 561 if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) { 562 fprintf(stderr, zIllOptStr, pOpts->pzProgPath, 563 zIllegal, pOpts->pzCurOpt-2); 564 return FAILURE; 565 } 566 567 return longOptionFind(pOpts, pOpts->pzCurOpt, pOptState); 568 } 569 570 /* 571 * If short options are not allowed, then do long 572 * option processing. Otherwise the character must be a 573 * short (i.e. single character) option. 574 */ 575 if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0) 576 return shortOptionFind(pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState); 577 578 return longOptionFind(pOpts, pOpts->pzCurOpt, pOptState); 579 } 580 581 582 static tSuccess 583 next_opt_arg_must(tOptions* pOpts, tOptState* pOptState) 584 { 585 /* 586 * An option argument is required. Long options can either have 587 * a separate command line argument, or an argument attached by 588 * the '=' character. Figure out which. 589 */ 590 switch (pOptState->optType) { 591 case TOPT_SHORT: 592 /* 593 * See if an arg string follows the flag character 594 */ 595 if (*++(pOpts->pzCurOpt) == NUL) 596 pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ]; 597 pOptState->pzOptArg = pOpts->pzCurOpt; 598 break; 599 600 case TOPT_LONG: 601 /* 602 * See if an arg string has already been assigned (glued on 603 * with an `=' character) 604 */ 605 if (pOptState->pzOptArg == NULL) 606 pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ]; 607 break; 608 609 default: 610 #ifdef DEBUG 611 fputs("AutoOpts lib error: option type not selected\n", stderr); 612 exit(EXIT_FAILURE); 613 #endif 614 615 case TOPT_DEFAULT: 616 /* 617 * The option was selected by default. The current token is 618 * the option argument. 619 */ 620 break; 621 } 622 623 /* 624 * Make sure we did not overflow the argument list. 625 */ 626 if (pOpts->curOptIdx > pOpts->origArgCt) { 627 fprintf(stderr, zMisArg, pOpts->pzProgPath, pOptState->pOD->pz_Name); 628 return FAILURE; 629 } 630 631 pOpts->pzCurOpt = NULL; /* next time advance to next arg */ 632 return SUCCESS; 633 } 634 635 636 static tSuccess 637 next_opt_arg_may(tOptions* pOpts, tOptState* pOptState) 638 { 639 /* 640 * An option argument is optional. 641 */ 642 switch (pOptState->optType) { 643 case TOPT_SHORT: 644 if (*++pOpts->pzCurOpt != NUL) 645 pOptState->pzOptArg = pOpts->pzCurOpt; 646 else { 647 char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; 648 649 /* 650 * BECAUSE it is optional, we must make sure 651 * we did not find another flag and that there 652 * is such an argument. 653 */ 654 if ((pzLA == NULL) || (*pzLA == '-')) 655 pOptState->pzOptArg = NULL; 656 else { 657 pOpts->curOptIdx++; /* argument found */ 658 pOptState->pzOptArg = pzLA; 659 } 660 } 661 break; 662 663 case TOPT_LONG: 664 /* 665 * Look for an argument if we don't already have one (glued on 666 * with a `=' character) *AND* we are not in named argument mode 667 */ 668 if ( (pOptState->pzOptArg == NULL) 669 && (! NAMED_OPTS(pOpts))) { 670 char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; 671 672 /* 673 * BECAUSE it is optional, we must make sure 674 * we did not find another flag and that there 675 * is such an argument. 676 */ 677 if ((pzLA == NULL) || (*pzLA == '-')) 678 pOptState->pzOptArg = NULL; 679 else { 680 pOpts->curOptIdx++; /* argument found */ 681 pOptState->pzOptArg = pzLA; 682 } 683 } 684 break; 685 686 default: 687 case TOPT_DEFAULT: 688 fputs(zAO_Woops, stderr ); 689 exit(EX_SOFTWARE); 690 } 691 692 /* 693 * After an option with an optional argument, we will 694 * *always* start with the next option because if there 695 * were any characters following the option name/flag, 696 * they would be interpreted as the argument. 697 */ 698 pOpts->pzCurOpt = NULL; 699 return SUCCESS; 700 } 701 702 703 static tSuccess 704 next_opt_arg_none(tOptions* pOpts, tOptState* pOptState) 705 { 706 /* 707 * No option argument. Make sure next time around we find 708 * the correct option flag character for short options 709 */ 710 if (pOptState->optType == TOPT_SHORT) 711 (pOpts->pzCurOpt)++; 712 713 /* 714 * It is a long option. Make sure there was no ``=xxx'' argument 715 */ 716 else if (pOptState->pzOptArg != NULL) { 717 fprintf(stderr, zNoArg, pOpts->pzProgPath, pOptState->pOD->pz_Name); 718 return FAILURE; 719 } 720 721 /* 722 * It is a long option. Advance to next command line argument. 723 */ 724 else 725 pOpts->pzCurOpt = NULL; 726 return SUCCESS; 727 } 728 729 /* 730 * nextOption 731 * 732 * Find the option descriptor and option argument (if any) for the 733 * next command line argument. DO NOT modify the descriptor. Put 734 * all the state in the state argument so that the option can be skipped 735 * without consequence (side effect). 736 */ 737 static tSuccess 738 nextOption(tOptions* pOpts, tOptState* pOptState) 739 { 740 { 741 tSuccess res; 742 res = findOptDesc(pOpts, pOptState); 743 if (! SUCCESSFUL(res)) 744 return res; 745 } 746 747 if ( ((pOptState->flags & OPTST_DEFINED) != 0) 748 && ((pOptState->pOD->fOptState & OPTST_NO_COMMAND) != 0)) { 749 fprintf(stderr, zNotCmdOpt, pOptState->pOD->pz_Name); 750 return FAILURE; 751 } 752 753 pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT_MASK); 754 755 /* 756 * Figure out what to do about option arguments. An argument may be 757 * required, not associated with the option, or be optional. We detect the 758 * latter by examining for an option marker on the next possible argument. 759 * Disabled mode option selection also disables option arguments. 760 */ 761 { 762 enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE; 763 tSuccess res; 764 765 if ((pOptState->flags & OPTST_DISABLED) != 0) 766 arg_type = ARG_NONE; 767 768 else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE) 769 arg_type = ARG_NONE; 770 771 else if (pOptState->flags & OPTST_ARG_OPTIONAL) 772 arg_type = ARG_MAY; 773 774 else 775 arg_type = ARG_MUST; 776 777 switch (arg_type) { 778 case ARG_MUST: res = next_opt_arg_must(pOpts, pOptState); break; 779 case ARG_MAY: res = next_opt_arg_may( pOpts, pOptState); break; 780 case ARG_NONE: res = next_opt_arg_none(pOpts, pOptState); break; 781 } 782 783 return res; 784 } 785 } 786 787 788 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 789 * 790 * DO PRESETS 791 * 792 * The next several routines do the immediate action pass on the command 793 * line options, then the environment variables, then the config files in 794 * reverse order. Once done with that, the order is reversed and all 795 * the config files and environment variables are processed again, this 796 * time only processing the non-immediate action options. doPresets() 797 * will then return for optionProcess() to do the final pass on the command 798 * line arguments. 799 */ 800 801 /** 802 * scan the command line for immediate action options. 803 * This is only called the first time through. 804 */ 805 LOCAL tSuccess 806 doImmediateOpts(tOptions* pOpts) 807 { 808 pOpts->curOptIdx = 1; /* start by skipping program name */ 809 pOpts->pzCurOpt = NULL; 810 811 /* 812 * Examine all the options from the start. We process any options that 813 * are marked for immediate processing. 814 */ 815 for (;;) { 816 tOptState optState = OPTSTATE_INITIALIZER(PRESET); 817 818 switch (nextOption(pOpts, &optState)) { 819 case FAILURE: goto failed_option; 820 case PROBLEM: return SUCCESS; /* no more args */ 821 case SUCCESS: break; 822 } 823 824 /* 825 * IF this is an immediate-attribute option, then do it. 826 */ 827 if (! DO_IMMEDIATELY(optState.flags)) 828 continue; 829 830 if (! SUCCESSFUL(handle_opt(pOpts, &optState))) 831 break; 832 } failed_option:; 833 834 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) 835 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 836 837 return FAILURE; 838 } 839 840 /** 841 * Process all the options from our current position onward. (This allows 842 * interspersed options and arguments for the few non-standard programs that 843 * require it.) Thus, do not rewind option indexes because some programs 844 * choose to re-invoke after a non-option. 845 */ 846 LOCAL tSuccess 847 doRegularOpts(tOptions* pOpts) 848 { 849 for (;;) { 850 tOptState optState = OPTSTATE_INITIALIZER(DEFINED); 851 852 switch (nextOption(pOpts, &optState)) { 853 case FAILURE: goto failed_option; 854 case PROBLEM: return SUCCESS; /* no more args */ 855 case SUCCESS: break; 856 } 857 858 /* 859 * IF this is an immediate action option, 860 * THEN skip it (unless we are supposed to do it a second time). 861 */ 862 if (! DO_NORMALLY(optState.flags)) { 863 if (! DO_SECOND_TIME(optState.flags)) 864 continue; 865 optState.pOD->optOccCt--; /* don't count this repetition */ 866 } 867 868 if (! SUCCESSFUL(handle_opt(pOpts, &optState))) 869 break; 870 } failed_option:; 871 872 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) 873 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 874 875 return FAILURE; 876 } 877 878 879 /** 880 * check for preset values from a config files or envrionment variables 881 */ 882 static tSuccess 883 doPresets(tOptions* pOpts) 884 { 885 tOptDesc * pOD = NULL; 886 887 if (! SUCCESSFUL(doImmediateOpts(pOpts))) 888 return FAILURE; 889 890 /* 891 * IF this option set has a --save-opts option, then it also 892 * has a --load-opts option. See if a command line option has disabled 893 * option presetting. 894 */ 895 if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) 896 && (pOpts->specOptIdx.save_opts != 0)) { 897 pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1; 898 if (DISABLED_OPT(pOD)) 899 return SUCCESS; 900 } 901 902 /* 903 * Until we return from this procedure, disable non-presettable opts 904 */ 905 pOpts->fOptSet |= OPTPROC_PRESETTING; 906 /* 907 * IF there are no config files, 908 * THEN do any environment presets and leave. 909 */ 910 if (pOpts->papzHomeList == NULL) { 911 doEnvPresets(pOpts, ENV_ALL); 912 } 913 else { 914 doEnvPresets(pOpts, ENV_IMM); 915 916 /* 917 * Check to see if environment variables have disabled presetting. 918 */ 919 if ((pOD != NULL) && ! DISABLED_OPT(pOD)) 920 internalFileLoad(pOpts); 921 922 /* 923 * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment 924 * variable options. Only the loading of .rc files. 925 */ 926 doEnvPresets(pOpts, ENV_NON_IMM); 927 } 928 pOpts->fOptSet &= ~OPTPROC_PRESETTING; 929 930 return SUCCESS; 931 } 932 933 934 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 935 * 936 * VERIFY OPTION CONSISTENCY 937 * 938 * Make sure that the argument list passes our consistency tests. 939 */ 940 static int 941 checkConsistency(tOptions* pOpts) 942 { 943 int errCt = 0; 944 tOptDesc* pOD = pOpts->pOptDesc; 945 int oCt = pOpts->presetOptCt; 946 947 /* 948 * FOR each of "oCt" options, ... 949 */ 950 for (;;) { 951 const int* pMust = pOD->pOptMust; 952 const int* pCant = pOD->pOptCant; 953 954 /* 955 * IF the current option was provided on the command line 956 * THEN ensure that any "MUST" requirements are not 957 * "DEFAULT" (unspecified) *AND* ensure that any 958 * "CANT" options have not been SET or DEFINED. 959 */ 960 if (SELECTED_OPT(pOD)) { 961 if (pMust != NULL) for (;;) { 962 tOptDesc* p = pOpts->pOptDesc + *(pMust++); 963 if (UNUSED_OPT(p)) { 964 const tOptDesc* pN = pOpts->pOptDesc + pMust[-1]; 965 errCt++; 966 fprintf(stderr, zReqFmt, pOD->pz_Name, pN->pz_Name); 967 } 968 969 if (*pMust == NO_EQUIVALENT) 970 break; 971 } 972 973 if (pCant != NULL) for (;;) { 974 tOptDesc* p = pOpts->pOptDesc + *(pCant++); 975 if (SELECTED_OPT(p)) { 976 const tOptDesc* pN = pOpts->pOptDesc + pCant[-1]; 977 errCt++; 978 fprintf(stderr, zCantFmt, pOD->pz_Name, pN->pz_Name); 979 } 980 981 if (*pCant == NO_EQUIVALENT) 982 break; 983 } 984 } 985 986 /* 987 * IF this option is not equivalenced to another, 988 * OR it is equivalenced to itself (is the equiv. root) 989 * THEN we need to make sure it occurs often enough. 990 */ 991 if ( (pOD->optEquivIndex == NO_EQUIVALENT) 992 || (pOD->optEquivIndex == pOD->optIndex) ) do { 993 /* 994 * IF the occurrence counts have been satisfied, 995 * THEN there is no problem. 996 */ 997 if (pOD->optOccCt >= pOD->optMinCt) 998 break; 999 1000 /* 1001 * IF MUST_SET means SET and PRESET are okay, 1002 * so min occurrence count doesn't count 1003 */ 1004 if ( (pOD->fOptState & OPTST_MUST_SET) 1005 && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) ) 1006 break; 1007 1008 errCt++; 1009 if (pOD->optMinCt > 1) 1010 fprintf(stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt); 1011 else fprintf(stderr, zNeedOne, pOD->pz_Name); 1012 } while (0); 1013 1014 if (--oCt <= 0) 1015 break; 1016 pOD++; 1017 } 1018 1019 /* 1020 * IF we are stopping on errors, check to see if any remaining 1021 * arguments are required to be there or prohibited from being there. 1022 */ 1023 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 1024 1025 /* 1026 * Check for prohibition 1027 */ 1028 if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) { 1029 if (pOpts->origArgCt > pOpts->curOptIdx) { 1030 fprintf(stderr, zNoArgs, pOpts->pzProgName); 1031 ++errCt; 1032 } 1033 } 1034 1035 /* 1036 * ELSE not prohibited, check for being required 1037 */ 1038 else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) { 1039 if (pOpts->origArgCt <= pOpts->curOptIdx) { 1040 fprintf(stderr, zArgsMust, pOpts->pzProgName); 1041 ++errCt; 1042 } 1043 } 1044 } 1045 1046 return errCt; 1047 } 1048 1049 1050 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1051 * 1052 * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE 1053 */ 1054 /*=--subblock=arg=arg_type,arg_name,arg_desc =*/ 1055 /*=* 1056 * library: opts 1057 * header: your-opts.h 1058 * 1059 * lib_description: 1060 * 1061 * These are the routines that libopts users may call directly from their 1062 * code. There are several other routines that can be called by code 1063 * generated by the libopts option templates, but they are not to be 1064 * called from any other user code. The @file{options.h} header is 1065 * fairly clear about this, too. 1066 =*/ 1067 1068 /*=export_func optionProcess 1069 * 1070 * what: this is the main option processing routine 1071 * 1072 * arg: + tOptions* + pOpts + program options descriptor + 1073 * arg: + int + argc + program arg count + 1074 * arg: + char** + argv + program arg vector + 1075 * 1076 * ret_type: int 1077 * ret_desc: the count of the arguments processed 1078 * 1079 * doc: 1080 * 1081 * This is the main entry point for processing options. It is intended 1082 * that this procedure be called once at the beginning of the execution of 1083 * a program. Depending on options selected earlier, it is sometimes 1084 * necessary to stop and restart option processing, or to select completely 1085 * different sets of options. This can be done easily, but you generally 1086 * do not want to do this. 1087 * 1088 * The number of arguments processed always includes the program name. 1089 * If one of the arguments is "--", then it is counted and the processing 1090 * stops. If an error was encountered and errors are to be tolerated, then 1091 * the returned value is the index of the argument causing the error. 1092 * A hyphen by itself ("-") will also cause processing to stop and will 1093 * @emph{not} be counted among the processed arguments. A hyphen by itself 1094 * is treated as an operand. Encountering an operand stops option 1095 * processing. 1096 * 1097 * err: Errors will cause diagnostics to be printed. @code{exit(3)} may 1098 * or may not be called. It depends upon whether or not the options 1099 * were generated with the "allow-errors" attribute, or if the 1100 * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked. 1101 =*/ 1102 int 1103 optionProcess(tOptions * pOpts, int argCt, char ** argVect) 1104 { 1105 if (! SUCCESSFUL(validateOptionsStruct(pOpts, argVect[0]))) 1106 exit(EX_SOFTWARE); 1107 1108 /* 1109 * Establish the real program name, the program full path, 1110 * and do all the presetting the first time thru only. 1111 */ 1112 if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) { 1113 pOpts->origArgCt = argCt; 1114 pOpts->origArgVect = argVect; 1115 pOpts->fOptSet |= OPTPROC_INITDONE; 1116 if (HAS_pzPkgDataDir(pOpts)) 1117 program_pkgdatadir = pOpts->pzPkgDataDir; 1118 1119 if (! SUCCESSFUL(doPresets(pOpts))) 1120 return 0; 1121 1122 /* 1123 * IF option name conversion was suppressed but it is not suppressed 1124 * for the command line, then it's time to translate option names. 1125 * Usage text will not get retranslated. 1126 */ 1127 if ( ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0) 1128 && (pOpts->pTransProc != NULL) 1129 && ((pOpts->fOptSet & OPTPROC_NO_XLAT_MASK) 1130 == OPTPROC_NXLAT_OPT_CFG) ) { 1131 1132 pOpts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG; 1133 (*pOpts->pTransProc)(); 1134 } 1135 1136 if ((pOpts->fOptSet & OPTPROC_REORDER) != 0) 1137 optionSort(pOpts); 1138 1139 pOpts->curOptIdx = 1; 1140 pOpts->pzCurOpt = NULL; 1141 } 1142 1143 /* 1144 * IF we are (re)starting, 1145 * THEN reset option location 1146 */ 1147 else if (pOpts->curOptIdx <= 0) { 1148 pOpts->curOptIdx = 1; 1149 pOpts->pzCurOpt = NULL; 1150 } 1151 1152 if (! SUCCESSFUL(doRegularOpts(pOpts))) 1153 return pOpts->origArgCt; 1154 1155 /* 1156 * IF there were no errors 1157 * AND we have RC/INI files 1158 * AND there is a request to save the files 1159 * THEN do that now before testing for conflicts. 1160 * (conflicts are ignored in preset options) 1161 */ 1162 if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) 1163 && (pOpts->specOptIdx.save_opts != 0)) { 1164 tOptDesc* pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts; 1165 1166 if (SELECTED_OPT(pOD)) { 1167 optionSaveFile(pOpts); 1168 exit(EXIT_SUCCESS); 1169 } 1170 } 1171 1172 /* 1173 * IF we are checking for errors, 1174 * THEN look for too few occurrences of required options 1175 */ 1176 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 1177 if (checkConsistency(pOpts) != 0) 1178 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 1179 } 1180 1181 return pOpts->curOptIdx; 1182 } 1183 1184 /* 1185 * Local Variables: 1186 * mode: C 1187 * c-file-style: "stroustrup" 1188 * indent-tabs-mode: nil 1189 * End: 1190 * end of autoopts/autoopts.c */ 1191