1 /** 2 * @file check.c 3 * 4 * @brief Hunt for options in the option descriptor list 5 * 6 * This file contains the routines that deal with processing quoted strings 7 * into an internal format. 8 * 9 * @addtogroup autoopts 10 * @{ 11 */ 12 /* 13 * This file is part of AutoOpts, a companion to AutoGen. 14 * AutoOpts is free software. 15 * AutoOpts is Copyright (C) 1992-2018 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 sha256 sums: 28 * 29 * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 30 * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 31 * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 32 */ 33 34 /** 35 * find the name and name length we are looking for 36 */ 37 static int 38 parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz) 39 { 40 int res = 0; 41 char const * p = *nm_pp; 42 *arg_pp = NULL; 43 44 for (;;) { 45 switch (*(p++)) { 46 case NUL: return res; 47 48 case '=': 49 memcpy(buf, *nm_pp, (size_t)res); 50 51 buf[res] = NUL; 52 *nm_pp = buf; 53 *arg_pp = (char *)p; 54 return res; 55 56 default: 57 if (++res >= (int)bufsz) 58 return -1; 59 } 60 } 61 } 62 63 /** 64 * print out the options that match the given name. 65 * 66 * @param pOpts option data 67 * @param opt_name name of option to look for 68 */ 69 static void 70 opt_ambiguities(tOptions * opts, char const * name, int nm_len) 71 { 72 char const * const hyph = 73 NAMED_OPTS(opts) ? "" : LONG_OPT_MARKER; 74 75 tOptDesc * pOD = opts->pOptDesc; 76 int idx = 0; 77 78 fputs(zambig_list_msg, stderr); 79 do { 80 if (pOD->pz_Name == NULL) 81 continue; /* doc option */ 82 83 if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) 84 fprintf(stderr, zambig_file, hyph, pOD->pz_Name); 85 86 else if ( (pOD->pz_DisableName != NULL) 87 && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) 88 ) 89 fprintf(stderr, zambig_file, hyph, pOD->pz_DisableName); 90 } while (pOD++, (++idx < opts->optCt)); 91 } 92 93 /** 94 * Determine the number of options that match the name 95 * 96 * @param pOpts option data 97 * @param opt_name name of option to look for 98 * @param nm_len length of provided name 99 * @param index pointer to int for option index 100 * @param disable pointer to bool to mark disabled option 101 * @return count of options that match 102 */ 103 static int 104 opt_match_ct(tOptions * opts, char const * name, int nm_len, 105 int * ixp, bool * disable) 106 { 107 int matchCt = 0; 108 int idx = 0; 109 int idxLim = opts->optCt; 110 tOptDesc * pOD = opts->pOptDesc; 111 112 do { 113 /* 114 * If option disabled or a doc option, skip to next 115 */ 116 if (pOD->pz_Name == NULL) 117 continue; 118 119 if ( SKIP_OPT(pOD) 120 && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) 121 continue; 122 123 if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) { 124 /* 125 * IF we have a complete match 126 * THEN it takes priority over any already located partial 127 */ 128 if (pOD->pz_Name[ nm_len ] == NUL) { 129 *ixp = idx; 130 return 1; 131 } 132 } 133 134 /* 135 * IF there is a disable name 136 * *AND* the option name matches the disable name 137 * THEN ... 138 */ 139 else if ( (pOD->pz_DisableName != NULL) 140 && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) 141 ) { 142 *disable = true; 143 144 /* 145 * IF we have a complete match 146 * THEN it takes priority over any already located partial 147 */ 148 if (pOD->pz_DisableName[ nm_len ] == NUL) { 149 *ixp = idx; 150 return 1; 151 } 152 } 153 154 else 155 continue; /* does not match any option */ 156 157 /* 158 * We found a full or partial match, either regular or disabling. 159 * Remember the index for later. 160 */ 161 *ixp = idx; 162 ++matchCt; 163 164 } while (pOD++, (++idx < idxLim)); 165 166 return matchCt; 167 } 168 169 /** 170 * Set the option to the indicated option number. 171 * 172 * @param opts option data 173 * @param arg option argument (if glued to name) 174 * @param idx option index 175 * @param disable mark disabled option 176 * @param st state about current option 177 */ 178 static tSuccess 179 opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st) 180 { 181 tOptDesc * pOD = opts->pOptDesc + idx; 182 183 if (SKIP_OPT(pOD)) { 184 if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) 185 return FAILURE; 186 187 fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name); 188 if (pOD->pzText != NULL) 189 fprintf(stderr, SET_OFF_FMT, pOD->pzText); 190 fputc(NL, stderr); 191 (*opts->pUsageProc)(opts, EXIT_FAILURE); 192 /* NOTREACHED */ 193 _exit(EXIT_FAILURE); /* to be certain */ 194 } 195 196 /* 197 * IF we found a disablement name, 198 * THEN set the bit in the callers' flag word 199 */ 200 if (disable) 201 st->flags |= OPTST_DISABLED; 202 203 st->pOD = pOD; 204 st->pzOptArg = arg; 205 st->optType = TOPT_LONG; 206 207 return SUCCESS; 208 } 209 210 /** 211 * An option was not found. Check for default option and set it 212 * if there is one. Otherwise, handle the error. 213 * 214 * @param opts option data 215 * @param name name of option to look for 216 * @param arg option argument 217 * @param st state about current option 218 * 219 * @return success status 220 */ 221 static tSuccess 222 opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st) 223 { 224 /* 225 * IF there is no equal sign 226 * *AND* we are using named arguments 227 * *AND* there is a default named option, 228 * THEN return that option. 229 */ 230 if ( (arg == NULL) 231 && NAMED_OPTS(opts) 232 && (opts->specOptIdx.default_opt != NO_EQUIVALENT)) { 233 234 st->pOD = opts->pOptDesc + opts->specOptIdx.default_opt; 235 st->pzOptArg = name; 236 st->optType = TOPT_DEFAULT; 237 return SUCCESS; 238 } 239 240 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { 241 fprintf(stderr, zIllOptStr, opts->pzProgPath, name); 242 (*opts->pUsageProc)(opts, EXIT_FAILURE); 243 /* NOTREACHED */ 244 _exit(EXIT_FAILURE); /* to be certain */ 245 } 246 247 return FAILURE; 248 } 249 250 /** 251 * Several options match the provided name. 252 * 253 * @param opts option data 254 * @param name name of option to look for 255 * @param match_ct number of matching options 256 * 257 * @return success status (always FAILURE, if it returns) 258 */ 259 static tSuccess 260 opt_ambiguous(tOptions * opts, char const * name, int match_ct) 261 { 262 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { 263 fprintf(stderr, zambig_opt_fmt, opts->pzProgPath, name, match_ct); 264 if (match_ct <= 4) 265 opt_ambiguities(opts, name, (int)strlen(name)); 266 (*opts->pUsageProc)(opts, EXIT_FAILURE); 267 /* NOTREACHED */ 268 _exit(EXIT_FAILURE); /* to be certain */ 269 } 270 return FAILURE; 271 } 272 273 /*=export_func optionVendorOption 274 * private: 275 * 276 * what: Process a vendor option 277 * arg: + tOptions * + pOpts + program options descriptor + 278 * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + 279 * 280 * doc: 281 * For POSIX specified utilities, the options are constrained to the options, 282 * @xref{config attributes, Program Configuration}. AutoOpts clients should 283 * never specify this directly. It gets referenced when the option 284 * definitions contain a "vendor-opt" attribute. 285 =*/ 286 void 287 optionVendorOption(tOptions * pOpts, tOptDesc * pOD) 288 { 289 tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); 290 char const * vopt_str = pOD->optArg.argString; 291 292 if (pOpts <= OPTPROC_EMIT_LIMIT) 293 return; 294 295 if ((pOD->fOptState & OPTST_RESET) != 0) 296 return; 297 298 if ((pOD->fOptState & OPTPROC_IMMEDIATE) == 0) 299 opt_st.flags = OPTST_DEFINED; 300 301 if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) == 0) 302 || ! SUCCESSFUL(opt_find_long(pOpts, vopt_str, &opt_st)) 303 || ! SUCCESSFUL(get_opt_arg(pOpts, &opt_st)) ) 304 { 305 fprintf(stderr, zIllVendOptStr, pOpts->pzProgName, vopt_str); 306 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 307 /* NOTREACHED */ 308 _exit(EXIT_FAILURE); /* to be certain */ 309 } 310 311 /* 312 * See if we are in immediate handling state. 313 */ 314 if (pOpts->fOptSet & OPTPROC_IMMEDIATE) { 315 /* 316 * See if the enclosed option is okay with that state. 317 */ 318 if (DO_IMMEDIATELY(opt_st.flags)) 319 (void)handle_opt(pOpts, &opt_st); 320 321 } else { 322 /* 323 * non-immediate direction. 324 * See if the enclosed option is okay with that state. 325 */ 326 if (DO_NORMALLY(opt_st.flags) || DO_SECOND_TIME(opt_st.flags)) 327 (void)handle_opt(pOpts, &opt_st); 328 } 329 } 330 331 /** 332 * Find the option descriptor by full name. 333 * 334 * @param opts option data 335 * @param opt_name name of option to look for 336 * @param state state about current option 337 * 338 * @return success status 339 */ 340 static tSuccess 341 opt_find_long(tOptions * opts, char const * opt_name, tOptState * state) 342 { 343 char name_buf[128]; 344 char * opt_arg; 345 int nm_len = parse_opt(&opt_name, &opt_arg, name_buf, sizeof(name_buf)); 346 347 int idx = 0; 348 bool disable = false; 349 int ct; 350 351 if (nm_len <= 1) { 352 if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) 353 return FAILURE; 354 355 fprintf(stderr, zInvalOptName, opts->pzProgName, opt_name); 356 (*opts->pUsageProc)(opts, EXIT_FAILURE); 357 /* NOTREACHED */ 358 _exit(EXIT_FAILURE); /* to be certain */ 359 } 360 361 ct = opt_match_ct(opts, opt_name, nm_len, &idx, &disable); 362 363 /* 364 * See if we found one match, no matches or multiple matches. 365 */ 366 switch (ct) { 367 case 1: return opt_set(opts, opt_arg, idx, disable, state); 368 case 0: return opt_unknown(opts, opt_name, opt_arg, state); 369 default: return opt_ambiguous(opts, opt_name, ct); 370 } 371 } 372 373 374 /** 375 * Find the short option descriptor for the current option 376 * 377 * @param pOpts option data 378 * @param optValue option flag character 379 * @param pOptState state about current option 380 */ 381 static tSuccess 382 opt_find_short(tOptions * pOpts, uint_t optValue, tOptState * pOptState) 383 { 384 tOptDesc * pRes = pOpts->pOptDesc; 385 int ct = pOpts->optCt; 386 387 /* 388 * Search the option list 389 */ 390 do { 391 if (optValue != pRes->optValue) 392 continue; 393 394 if (SKIP_OPT(pRes)) { 395 if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) 396 && (pRes->pz_Name != NULL)) { 397 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0) 398 return FAILURE; 399 400 fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name); 401 if (pRes->pzText != NULL) 402 fprintf(stderr, SET_OFF_FMT, pRes->pzText); 403 fputc(NL, stderr); 404 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 405 /* NOTREACHED */ 406 _exit(EXIT_FAILURE); /* to be certain */ 407 } 408 goto short_opt_error; 409 } 410 411 pOptState->pOD = pRes; 412 pOptState->optType = TOPT_SHORT; 413 return SUCCESS; 414 415 } while (pRes++, --ct > 0); 416 417 /* 418 * IF the character value is a digit 419 * AND there is a special number option ("-n") 420 * THEN the result is the "option" itself and the 421 * option is the specially marked "number" option. 422 */ 423 if ( IS_DEC_DIGIT_CHAR(optValue) 424 && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) { 425 pOptState->pOD = \ 426 pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option; 427 (pOpts->pzCurOpt)--; 428 pOptState->optType = TOPT_SHORT; 429 return SUCCESS; 430 } 431 432 short_opt_error: 433 434 /* 435 * IF we are to stop on errors (the default, actually) 436 * THEN call the usage procedure. 437 */ 438 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { 439 fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue); 440 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); 441 /* NOTREACHED */ 442 _exit(EXIT_FAILURE); /* to be certain */ 443 } 444 445 return FAILURE; 446 } 447 448 /** 449 * Process option with a required argument. Long options can either have a 450 * separate command line argument, or an argument attached by the '=' 451 * character. Figure out which. 452 * 453 * @param[in,out] opts the program option descriptor 454 * @param[in,out] o_st the option processing state 455 * @returns SUCCESS or FAILURE 456 */ 457 static tSuccess 458 get_opt_arg_must(tOptions * opts, tOptState * o_st) 459 { 460 switch (o_st->optType) { 461 case TOPT_SHORT: 462 /* 463 * See if an arg string follows the flag character 464 */ 465 if (*++(opts->pzCurOpt) == NUL) 466 opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx++ ]; 467 o_st->pzOptArg = opts->pzCurOpt; 468 break; 469 470 case TOPT_LONG: 471 /* 472 * See if an arg string has already been assigned (glued on 473 * with an `=' character) 474 */ 475 if (o_st->pzOptArg == NULL) 476 o_st->pzOptArg = opts->origArgVect[ opts->curOptIdx++ ]; 477 break; 478 479 default: 480 #ifdef DEBUG 481 fputs("AutoOpts lib error: option type not selected\n", stderr); 482 option_exits(EXIT_FAILURE); 483 #endif 484 485 case TOPT_DEFAULT: 486 /* 487 * The option was selected by default. The current token is 488 * the option argument. 489 */ 490 break; 491 } 492 493 /* 494 * Make sure we did not overflow the argument list. 495 */ 496 if (opts->curOptIdx > opts->origArgCt) { 497 fprintf(stderr, zMisArg, opts->pzProgPath, o_st->pOD->pz_Name); 498 return FAILURE; 499 } 500 501 opts->pzCurOpt = NULL; /* next time advance to next arg */ 502 return SUCCESS; 503 } 504 505 /** 506 * Process an option with an optional argument. For short options, it looks 507 * at the character after the option character, or it consumes the next full 508 * argument. For long options, it looks for an '=' character attachment to 509 * the long option name before deciding to take the next command line 510 * argument. 511 * 512 * @param pOpts the option descriptor 513 * @param o_st a structure for managing the current processing state 514 * @returns SUCCESS or does not return 515 */ 516 static tSuccess 517 get_opt_arg_may(tOptions * pOpts, tOptState * o_st) 518 { 519 /* 520 * An option argument is optional. 521 */ 522 switch (o_st->optType) { 523 case TOPT_SHORT: 524 if (*++pOpts->pzCurOpt != NUL) 525 o_st->pzOptArg = pOpts->pzCurOpt; 526 else { 527 char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; 528 529 /* 530 * BECAUSE it is optional, we must make sure 531 * we did not find another flag and that there 532 * is such an argument. 533 */ 534 if ((pzLA == NULL) || (*pzLA == '-')) 535 o_st->pzOptArg = NULL; 536 else { 537 pOpts->curOptIdx++; /* argument found */ 538 o_st->pzOptArg = pzLA; 539 } 540 } 541 break; 542 543 case TOPT_LONG: 544 /* 545 * Look for an argument if we don't already have one (glued on 546 * with a `=' character) *AND* we are not in named argument mode 547 */ 548 if ( (o_st->pzOptArg == NULL) 549 && (! NAMED_OPTS(pOpts))) { 550 char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; 551 552 /* 553 * BECAUSE it is optional, we must make sure 554 * we did not find another flag and that there 555 * is such an argument. 556 */ 557 if ((pzLA == NULL) || (*pzLA == '-')) 558 o_st->pzOptArg = NULL; 559 else { 560 pOpts->curOptIdx++; /* argument found */ 561 o_st->pzOptArg = pzLA; 562 } 563 } 564 break; 565 566 default: 567 case TOPT_DEFAULT: 568 ao_bug(zbad_default_msg); 569 } 570 571 /* 572 * After an option with an optional argument, we will 573 * *always* start with the next option because if there 574 * were any characters following the option name/flag, 575 * they would be interpreted as the argument. 576 */ 577 pOpts->pzCurOpt = NULL; 578 return SUCCESS; 579 } 580 581 /** 582 * Process option that does not have an argument. 583 * 584 * @param[in,out] opts the program option descriptor 585 * @param[in,out] o_st the option processing state 586 * @returns SUCCESS or FAILURE 587 */ 588 static tSuccess 589 get_opt_arg_none(tOptions * pOpts, tOptState * o_st) 590 { 591 /* 592 * No option argument. Make sure next time around we find 593 * the correct option flag character for short options 594 */ 595 if (o_st->optType == TOPT_SHORT) 596 (pOpts->pzCurOpt)++; 597 598 /* 599 * It is a long option. Make sure there was no ``=xxx'' argument 600 */ 601 else if (o_st->pzOptArg != NULL) { 602 fprintf(stderr, zNoArg, pOpts->pzProgPath, o_st->pOD->pz_Name); 603 return FAILURE; 604 } 605 606 /* 607 * It is a long option. Advance to next command line argument. 608 */ 609 else 610 pOpts->pzCurOpt = NULL; 611 612 return SUCCESS; 613 } 614 615 /** 616 * Process option. Figure out whether or not to look for an option argument. 617 * 618 * @param[in,out] opts the program option descriptor 619 * @param[in,out] o_st the option processing state 620 * @returns SUCCESS or FAILURE 621 */ 622 static tSuccess 623 get_opt_arg(tOptions * opts, tOptState * o_st) 624 { 625 o_st->flags |= (o_st->pOD->fOptState & OPTST_PERSISTENT_MASK); 626 627 /* 628 * Disabled options and options specified to not have arguments 629 * are handled with the "none" procedure. Otherwise, check the 630 * optional flag and call either the "may" or "must" function. 631 */ 632 if ((o_st->flags & OPTST_DISABLED) != 0) 633 return get_opt_arg_none(opts, o_st); 634 635 switch (OPTST_GET_ARGTYPE(o_st->flags)) { 636 case OPARG_TYPE_STATIC: 637 { 638 /* 639 * Propagate the static arg 640 */ 641 tSuccess res = get_opt_arg_none(opts, o_st); 642 o_st->pzOptArg = o_st->pOD->optArg.argString; 643 return res; 644 } 645 646 case OPARG_TYPE_NONE: 647 return get_opt_arg_none(opts, o_st); 648 } 649 650 if (o_st->flags & OPTST_ARG_OPTIONAL) 651 return get_opt_arg_may( opts, o_st); 652 653 return get_opt_arg_must(opts, o_st); 654 } 655 656 /** 657 * Find the option descriptor for the current option. 658 * 659 * @param[in,out] opts the program option descriptor 660 * @param[in,out] o_st the option processing state 661 * @returns SUCCESS or FAILURE 662 */ 663 static tSuccess 664 find_opt(tOptions * opts, tOptState * o_st) 665 { 666 /* 667 * IF we are continuing a short option list (e.g. -xyz...) 668 * THEN continue a single flag option. 669 * OTHERWISE see if there is room to advance and then do so. 670 */ 671 if ((opts->pzCurOpt != NULL) && (*opts->pzCurOpt != NUL)) 672 return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st); 673 674 if (opts->curOptIdx >= opts->origArgCt) 675 return PROBLEM; /* NORMAL COMPLETION */ 676 677 opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx ]; 678 679 /* 680 * IF all arguments must be named options, ... 681 */ 682 if (NAMED_OPTS(opts)) { 683 char * pz = opts->pzCurOpt; 684 int def; 685 tSuccess res; 686 uint16_t * def_opt; 687 688 opts->curOptIdx++; 689 690 if (*pz != '-') 691 return opt_find_long(opts, pz, o_st); 692 693 /* 694 * The name is prefixed with one or more hyphens. Strip them off 695 * and disable the "default_opt" setting. Use heavy recasting to 696 * strip off the "const" quality of the "default_opt" field. 697 */ 698 while (*(++pz) == '-') ; 699 def_opt = VOIDP(&(opts->specOptIdx.default_opt)); 700 def = *def_opt; 701 *def_opt = NO_EQUIVALENT; 702 res = opt_find_long(opts, pz, o_st); 703 *def_opt = (uint16_t)def; 704 return res; 705 } 706 707 /* 708 * Note the kind of flag/option marker 709 */ 710 if (*((opts->pzCurOpt)++) != '-') 711 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ 712 713 /* 714 * Special hack for a hyphen by itself 715 */ 716 if (*(opts->pzCurOpt) == NUL) 717 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ 718 719 /* 720 * The current argument is to be processed as an option argument 721 */ 722 opts->curOptIdx++; 723 724 /* 725 * We have an option marker. 726 * Test the next character for long option indication 727 */ 728 if (opts->pzCurOpt[0] == '-') { 729 if (*++(opts->pzCurOpt) == NUL) 730 /* 731 * NORMAL COMPLETION - NOT this arg, but rest are operands 732 */ 733 return PROBLEM; 734 735 /* 736 * We do not allow the hyphen to be used as a flag value. 737 * Therefore, if long options are not to be accepted, we punt. 738 */ 739 if ((opts->fOptSet & OPTPROC_LONGOPT) == 0) { 740 fprintf(stderr, zIllOptStr, opts->pzProgPath, opts->pzCurOpt-2); 741 return FAILURE; 742 } 743 744 return opt_find_long(opts, opts->pzCurOpt, o_st); 745 } 746 747 /* 748 * If short options are not allowed, then do long 749 * option processing. Otherwise the character must be a 750 * short (i.e. single character) option. 751 */ 752 if ((opts->fOptSet & OPTPROC_SHORTOPT) != 0) 753 return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st); 754 755 return opt_find_long(opts, opts->pzCurOpt, o_st); 756 } 757 758 /** @} 759 * 760 * Local Variables: 761 * mode: C 762 * c-file-style: "stroustrup" 763 * indent-tabs-mode: nil 764 * End: 765 * end of autoopts/find.c */ 766