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