1
0

find.c 21 KB

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