autoopts.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * $Id: autoopts.c,v 4.8 2005/03/13 19:51:57 bkorb Exp $
  3. * Time-stamp: "2005-03-13 08:39:23 bkorb"
  4. *
  5. * This file contains all of the routines that must be linked into
  6. * an executable to use the generated option processing. The optional
  7. * routines are in separately compiled modules so that they will not
  8. * necessarily be linked in.
  9. */
  10. /*
  11. * Automated Options copyright 1992-2005 Bruce Korb
  12. *
  13. * Automated Options is free software.
  14. * You may redistribute it and/or modify it under the terms of the
  15. * GNU General Public License, as published by the Free Software
  16. * Foundation; either version 2, or (at your option) any later version.
  17. *
  18. * Automated Options is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with Automated Options. See the file "COPYING". If not,
  25. * write to: The Free Software Foundation, Inc.,
  26. * 59 Temple Place - Suite 330,
  27. * Boston, MA 02111-1307, USA.
  28. *
  29. * As a special exception, Bruce Korb gives permission for additional
  30. * uses of the text contained in his release of AutoOpts.
  31. *
  32. * The exception is that, if you link the AutoOpts library with other
  33. * files to produce an executable, this does not by itself cause the
  34. * resulting executable to be covered by the GNU General Public License.
  35. * Your use of that executable is in no way restricted on account of
  36. * linking the AutoOpts library code into it.
  37. *
  38. * This exception does not however invalidate any other reasons why
  39. * the executable file might be covered by the GNU General Public License.
  40. *
  41. * This exception applies only to the code released by Bruce Korb under
  42. * the name AutoOpts. If you copy code from other sources under the
  43. * General Public License into a copy of AutoOpts, as the General Public
  44. * License permits, the exception does not apply to the code that you add
  45. * in this way. To avoid misleading anyone as to the status of such
  46. * modified files, you must delete this exception notice from them.
  47. *
  48. * If you write modifications of your own for AutoOpts, it is your choice
  49. * whether to permit this exception to apply to your modifications.
  50. * If you do not wish that, delete this exception notice.
  51. */
  52. #ifndef HAVE_PATHFIND
  53. # include "compat/pathfind.c"
  54. #endif
  55. static const char zNil[] = "";
  56. #define SKIP_RC_FILES(po) \
  57. DISABLED_OPT(&((po)->pOptDesc[ (po)->specOptIdx.save_opts+1]))
  58. /* = = = START-STATIC-FORWARD = = = */
  59. /* static forward declarations maintained by :mkfwd */
  60. static tSuccess
  61. findOptDesc( tOptions* pOpts, tOptState* pOptState );
  62. static tSuccess
  63. nextOption( tOptions* pOpts, tOptState* pOptState );
  64. static tSuccess
  65. doPresets( tOptions* pOpts );
  66. static int
  67. checkConsistency( tOptions* pOpts );
  68. /* = = = END-STATIC-FORWARD = = = */
  69. /*
  70. * handleOption
  71. *
  72. * This routine handles equivalencing, sets the option state flags and
  73. * invokes the handler procedure, if any.
  74. */
  75. LOCAL tSuccess
  76. handleOption( tOptions* pOpts, tOptState* pOptState )
  77. {
  78. /*
  79. * Save a copy of the option procedure pointer.
  80. * If this is an equivalence class option, we still want this proc.
  81. */
  82. tOptDesc* pOD = pOptState->pOD;
  83. tOptProc* pOP = pOD->pOptProc;
  84. pOD->pzLastArg = pOptState->pzOptArg;
  85. /*
  86. * IF we are presetting options, then we will ignore any un-presettable
  87. * options. They are the ones either marked as such.
  88. */
  89. if ( ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
  90. && ((pOD->fOptState & OPTST_NO_INIT) != 0)
  91. )
  92. return PROBLEM;
  93. /*
  94. * IF this is an equivalence class option,
  95. * THEN
  96. * Save the option value that got us to this option
  97. * entry. (It may not be pOD->optChar[0], if this is an
  98. * equivalence entry.)
  99. * set the pointer to the equivalence class base
  100. */
  101. if (pOD->optEquivIndex != NO_EQUIVALENT) {
  102. tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
  103. /*
  104. * IF the current option state has not been defined (set on the
  105. * command line), THEN we will allow continued resetting of
  106. * the value. Once "defined", then it must not change.
  107. */
  108. if ((pOD->fOptState & OPTST_DEFINED) != 0) {
  109. /*
  110. * The equivalenced-to option has been found on the command
  111. * line before. Make sure new occurrences are the same type.
  112. *
  113. * IF this option has been previously equivalenced and
  114. * it was not the same equivalenced-to option,
  115. * THEN we have a usage problem.
  116. */
  117. if (p->optActualIndex != pOD->optIndex) {
  118. fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
  119. (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
  120. return FAILURE;
  121. }
  122. } else {
  123. /*
  124. * Set the equivalenced-to actual option index to no-equivalent
  125. * so that we set all the entries below. This option may either
  126. * never have been selected before, or else it was selected by
  127. * some sort of "presetting" mechanism.
  128. */
  129. p->optActualIndex = NO_EQUIVALENT;
  130. }
  131. if (p->optActualIndex != pOD->optIndex) {
  132. /*
  133. * First time through, copy over the state
  134. * and add in the equivalence flag
  135. */
  136. p->optActualValue = pOD->optValue;
  137. p->optActualIndex = pOD->optIndex;
  138. pOptState->flags |= OPTST_EQUIVALENCE;
  139. }
  140. /*
  141. * Copy the most recent option argument. set membership state
  142. * is kept in ``p->optCookie''. Do not overwrite.
  143. */
  144. p->pzLastArg = pOD->pzLastArg;
  145. pOD = p;
  146. } else {
  147. pOD->optActualValue = pOD->optValue;
  148. pOD->optActualIndex = pOD->optIndex;
  149. }
  150. pOD->fOptState &= OPTST_PERSISTENT;
  151. pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT);
  152. /*
  153. * Keep track of count only for DEFINED (command line) options.
  154. * IF we have too many, build up an error message and bail.
  155. */
  156. if ( (pOD->fOptState & OPTST_DEFINED)
  157. && (++pOD->optOccCt > pOD->optMaxCt) ) {
  158. const char* pzEqv =
  159. (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
  160. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  161. const char* pzFmt = (pOD->optMaxCt > 1) ? zAtMost : zOnlyOne;
  162. fputs( zErrOnly, stderr );
  163. fprintf( stderr, pzFmt, pOD->pz_Name, pzEqv,
  164. pOD->optMaxCt );
  165. }
  166. return FAILURE;
  167. }
  168. /*
  169. * If provided a procedure to call, call it
  170. */
  171. if (pOP != (tpOptProc)NULL)
  172. (*pOP)( pOpts, pOD );
  173. return SUCCESS;
  174. }
  175. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  176. *
  177. * HUNT FOR OPTIONS IN THE ARGUMENT LIST
  178. *
  179. * The next four procedures are "private" to nextOption().
  180. * nextOption() uses findOptDesc() to find the next descriptor and it, in
  181. * turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
  182. *
  183. * longOptionFind
  184. *
  185. * Find the long option descriptor for the current option
  186. */
  187. LOCAL tSuccess
  188. longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
  189. {
  190. ag_bool disable = AG_FALSE;
  191. char* pzEq = strchr( pzOptName, '=' );
  192. tOptDesc* pOD = pOpts->pOptDesc;
  193. int idx = 0;
  194. int idxLim = pOpts->optCt;
  195. int matchCt = 0;
  196. int matchIdx = 0;
  197. int nameLen;
  198. /*
  199. * IF the value is attached to the name,
  200. * THEN clip it off.
  201. * Either way, figure out how long our name is
  202. */
  203. if (pzEq != NULL) {
  204. nameLen = (int)(pzEq - pzOptName);
  205. *pzEq = NUL;
  206. } else nameLen = strlen( pzOptName );
  207. do {
  208. if (SKIP_OPT(pOD))
  209. continue;
  210. if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
  211. /*
  212. * IF we have a complete match
  213. * THEN it takes priority over any already located partial
  214. */
  215. if (pOD->pz_Name[ nameLen ] == NUL) {
  216. matchCt = 1;
  217. matchIdx = idx;
  218. break;
  219. }
  220. }
  221. /*
  222. * IF there is a disable name
  223. * *AND* no argument value has been supplied
  224. * (disabled options may have no argument)
  225. * *AND* the option name matches the disable name
  226. * THEN ...
  227. */
  228. else if ( (pOD->pz_DisableName != NULL)
  229. && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
  230. ) {
  231. disable = AG_TRUE;
  232. /*
  233. * IF we have a complete match
  234. * THEN it takes priority over any already located partial
  235. */
  236. if (pOD->pz_DisableName[ nameLen ] == NUL) {
  237. matchCt = 1;
  238. matchIdx = idx;
  239. break;
  240. }
  241. }
  242. else
  243. continue;
  244. /*
  245. * We found a partial match, either regular or disabling.
  246. * Remember the index for later.
  247. */
  248. matchIdx = idx;
  249. if (++matchCt > 1)
  250. break;
  251. } while (pOD++, (++idx < idxLim));
  252. if (pzEq != NULL)
  253. *(pzEq++) = '=';
  254. /*
  255. * Make sure we either found an exact match or found only one partial
  256. */
  257. if (matchCt == 1) {
  258. /*
  259. * IF we found a disablement name,
  260. * THEN set the bit in the callers' flag word
  261. */
  262. if (disable)
  263. pOptState->flags |= OPTST_DISABLED;
  264. pOptState->pOD = pOpts->pOptDesc + matchIdx;
  265. pOptState->pzOptArg = pzEq;
  266. pOptState->optType = TOPT_LONG;
  267. return SUCCESS;
  268. }
  269. /*
  270. * IF there is no equal sign
  271. * *AND* we are using named arguments
  272. * *AND* there is a default named option,
  273. * THEN return that option.
  274. */
  275. if ( (pzEq == NULL)
  276. && NAMED_OPTS(pOpts)
  277. && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
  278. pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
  279. pOptState->pzOptArg = pzOptName;
  280. pOptState->optType = TOPT_DEFAULT;
  281. return SUCCESS;
  282. }
  283. /*
  284. * IF we are to stop on errors (the default, actually)
  285. * THEN call the usage procedure.
  286. */
  287. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  288. fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
  289. (matchCt == 0) ? zIllegal : zAmbiguous, pzOptName );
  290. (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
  291. }
  292. return FAILURE;
  293. }
  294. /*
  295. * shortOptionFind
  296. *
  297. * Find the short option descriptor for the current option
  298. */
  299. LOCAL tSuccess
  300. shortOptionFind( tOptions* pOpts, tUC optValue, tOptState* pOptState )
  301. {
  302. tOptDesc* pRes = pOpts->pOptDesc;
  303. int ct = pOpts->optCt;
  304. /*
  305. * Search the option list
  306. */
  307. for (;;) {
  308. /*
  309. * IF the values match,
  310. * THEN we stop here
  311. */
  312. if ((! SKIP_OPT(pRes)) && (optValue == pRes->optValue)) {
  313. pOptState->pOD = pRes;
  314. pOptState->optType = TOPT_SHORT;
  315. return SUCCESS;
  316. }
  317. /*
  318. * Advance to next option description
  319. */
  320. pRes++;
  321. /*
  322. * IF we have searched everything, ...
  323. */
  324. if (--ct <= 0)
  325. break;
  326. }
  327. /*
  328. * IF the character value is a digit
  329. * AND there is a special number option ("-n")
  330. * THEN the result is the "option" itself and the
  331. * option is the specially marked "number" option.
  332. */
  333. if ( isdigit( optValue )
  334. && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
  335. pOptState->pOD = \
  336. pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
  337. (pOpts->pzCurOpt)--;
  338. pOptState->optType = TOPT_SHORT;
  339. return SUCCESS;
  340. }
  341. /*
  342. * IF we are to stop on errors (the default, actually)
  343. * THEN call the usage procedure.
  344. */
  345. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  346. fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
  347. (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
  348. }
  349. return FAILURE;
  350. }
  351. /*
  352. * findOptDesc
  353. *
  354. * Find the option descriptor for the current option
  355. */
  356. static tSuccess
  357. findOptDesc( tOptions* pOpts, tOptState* pOptState )
  358. {
  359. /*
  360. * IF we are continuing a short option list (e.g. -xyz...)
  361. * THEN continue a single flag option.
  362. * OTHERWISE see if there is room to advance and then do so.
  363. */
  364. if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
  365. return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
  366. if (pOpts->curOptIdx >= pOpts->origArgCt)
  367. return PROBLEM; /* NORMAL COMPLETION */
  368. pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
  369. /*
  370. * IF all arguments must be named options, ...
  371. */
  372. if (NAMED_OPTS(pOpts)) {
  373. char* pz = pOpts->pzCurOpt;
  374. pOpts->curOptIdx++;
  375. /*
  376. * Skip over any flag/option markers.
  377. * In this mode, they are not required.
  378. */
  379. while (*pz == '-') pz++;
  380. return longOptionFind( pOpts, pz, pOptState );
  381. }
  382. /*
  383. * Note the kind of flag/option marker
  384. */
  385. if (*((pOpts->pzCurOpt)++) != '-')
  386. return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
  387. /*
  388. * Special hack for a hyphen by itself
  389. */
  390. if (*(pOpts->pzCurOpt) == NUL)
  391. return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
  392. /*
  393. * The current argument is to be processed as an option argument
  394. */
  395. pOpts->curOptIdx++;
  396. /*
  397. * We have an option marker.
  398. * Test the next character for long option indication
  399. */
  400. if (pOpts->pzCurOpt[0] == '-') {
  401. if (*++(pOpts->pzCurOpt) == NUL)
  402. /*
  403. * NORMAL COMPLETION - NOT this arg, but rest are operands
  404. */
  405. return PROBLEM;
  406. /*
  407. * We do not allow the hyphen to be used as a flag value.
  408. * Therefore, if long options are not to be accepted, we punt.
  409. */
  410. if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
  411. fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
  412. zIllegal, pOpts->pzCurOpt-2 );
  413. return FAILURE;
  414. }
  415. return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
  416. }
  417. /*
  418. * If short options are not allowed, then do long
  419. * option processing. Otherwise the character must be a
  420. * short (i.e. single character) option.
  421. */
  422. if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
  423. return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
  424. return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
  425. }
  426. /*
  427. * nextOption
  428. *
  429. * Find the option descriptor and option argument (if any) for the
  430. * next command line argument. DO NOT modify the descriptor. Put
  431. * all the state in the state argument so that the option can be skipped
  432. * without consequence (side effect).
  433. */
  434. static tSuccess
  435. nextOption( tOptions* pOpts, tOptState* pOptState )
  436. {
  437. tSuccess res;
  438. enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
  439. res = findOptDesc( pOpts, pOptState );
  440. if (! SUCCESSFUL( res ))
  441. return res;
  442. pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT);
  443. /*
  444. * Figure out what to do about option arguments. An argument may be
  445. * required, not associated with the option, or be optional. We detect the
  446. * latter by examining for an option marker on the next possible argument.
  447. * Disabled mode option selection also disables option arguments.
  448. */
  449. if ((pOptState->flags & OPTST_DISABLED) != 0)
  450. arg_type = ARG_NONE;
  451. else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE)
  452. arg_type = ARG_NONE;
  453. else if (pOptState->flags & OPTST_ARG_OPTIONAL)
  454. arg_type = ARG_MAY;
  455. else
  456. arg_type = ARG_MUST;
  457. switch (arg_type) {
  458. case ARG_MUST:
  459. /*
  460. * An option argument is required. Long options can either have
  461. * a separate command line argument, or an argument attached by
  462. * the '=' character. Figure out which.
  463. */
  464. switch (pOptState->optType) {
  465. case TOPT_SHORT:
  466. /*
  467. * See if an arg string follows the flag character
  468. */
  469. if (*++(pOpts->pzCurOpt) == NUL)
  470. pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
  471. pOptState->pzOptArg = pOpts->pzCurOpt;
  472. break;
  473. case TOPT_LONG:
  474. /*
  475. * See if an arg string has already been assigned (glued on
  476. * with an `=' character)
  477. */
  478. if (pOptState->pzOptArg == NULL)
  479. pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
  480. break;
  481. default:
  482. #ifdef DEBUG
  483. fputs( "AutoOpts lib error: option type not selected\n",
  484. stderr );
  485. exit( EXIT_FAILURE );
  486. #endif
  487. case TOPT_DEFAULT:
  488. /*
  489. * The option was selected by default. The current token is
  490. * the option argument.
  491. */
  492. break;
  493. }
  494. /*
  495. * Make sure we did not overflow the argument list.
  496. */
  497. if (pOpts->curOptIdx > pOpts->origArgCt) {
  498. fprintf( stderr, zMisArg, pOpts->pzProgPath,
  499. pOptState->pOD->pz_Name );
  500. return FAILURE;
  501. }
  502. pOpts->pzCurOpt = NULL; /* next time advance to next arg */
  503. break;
  504. case ARG_MAY:
  505. /*
  506. * An option argument is optional.
  507. */
  508. switch (pOptState->optType) {
  509. case TOPT_SHORT:
  510. if (*++pOpts->pzCurOpt != NUL)
  511. pOptState->pzOptArg = pOpts->pzCurOpt;
  512. else {
  513. char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
  514. /*
  515. * BECAUSE it is optional, we must make sure
  516. * we did not find another flag and that there
  517. * is such an argument.
  518. */
  519. if ((pzLA == NULL) || (*pzLA == '-'))
  520. pOptState->pzOptArg = NULL;
  521. else {
  522. pOpts->curOptIdx++; /* argument found */
  523. pOptState->pzOptArg = pzLA;
  524. }
  525. }
  526. break;
  527. case TOPT_LONG:
  528. /*
  529. * Look for an argument if we don't already have one (glued on
  530. * with a `=' character) *AND* we are not in named argument mode
  531. */
  532. if ( (pOptState->pzOptArg == NULL)
  533. && (! NAMED_OPTS(pOpts))) {
  534. char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
  535. /*
  536. * BECAUSE it is optional, we must make sure
  537. * we did not find another flag and that there
  538. * is such an argument.
  539. */
  540. if ((pzLA == NULL) || (*pzLA == '-'))
  541. pOptState->pzOptArg = NULL;
  542. else {
  543. pOpts->curOptIdx++; /* argument found */
  544. pOptState->pzOptArg = pzLA;
  545. }
  546. }
  547. break;
  548. default:
  549. case TOPT_DEFAULT:
  550. fputs( "AutoOpts lib error: defaulted to option with optional arg\n",
  551. stderr );
  552. exit( EXIT_FAILURE );
  553. }
  554. /*
  555. * After an option with an optional argument, we will
  556. * *always* start with the next option because if there
  557. * were any characters following the option name/flag,
  558. * they would be interpreted as the argument.
  559. */
  560. pOpts->pzCurOpt = NULL;
  561. break;
  562. default: /* CANNOT */
  563. /*
  564. * No option argument. Make sure next time around we find
  565. * the correct option flag character for short options
  566. */
  567. if (pOptState->optType == TOPT_SHORT)
  568. (pOpts->pzCurOpt)++;
  569. /*
  570. * It is a long option. Make sure there was no ``=xxx'' argument
  571. */
  572. else if (pOptState->pzOptArg != NULL) {
  573. fprintf( stderr, zNoArg, pOpts->pzProgPath,
  574. pOptState->pOD->pz_Name );
  575. return FAILURE;
  576. }
  577. /*
  578. * It is a long option. Advance to next command line argument.
  579. */
  580. else
  581. pOpts->pzCurOpt = NULL;
  582. }
  583. return SUCCESS;
  584. }
  585. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  586. *
  587. * DO PRESETS
  588. *
  589. * The next several routines do the immediate action pass on the command
  590. * line options, then the environment variables, then the config files in
  591. * reverse order. Once done with that, the order is reversed and all
  592. * the config files and environment variables are processed again, this
  593. * time only processing the non-immediate action options. doPresets()
  594. * will then return for optionProcess() to do the final pass on the command
  595. * line arguments.
  596. */
  597. /*
  598. * doImmediateOpts - scan the command line for immediate action options
  599. */
  600. LOCAL tSuccess
  601. doImmediateOpts( tOptions* pOpts )
  602. {
  603. pOpts->curOptIdx = 1; /* start by skipping program name */
  604. pOpts->pzCurOpt = NULL;
  605. /*
  606. * Examine all the options from the start. We process any options that
  607. * are marked for immediate processing.
  608. */
  609. for (;;) {
  610. tOptState optState = OPTSTATE_INITIALIZER(PRESET);
  611. switch (nextOption( pOpts, &optState )) {
  612. case FAILURE: goto optionsDone;
  613. case PROBLEM: return SUCCESS; /* no more args */
  614. case SUCCESS: break;
  615. }
  616. /*
  617. * IF this *is* an immediate-attribute option, then do it.
  618. */
  619. if (! DO_IMMEDIATELY(optState.flags))
  620. continue;
  621. if (! SUCCESSFUL( handleOption( pOpts, &optState )))
  622. break;
  623. } optionsDone:;
  624. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
  625. (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
  626. return FAILURE;
  627. }
  628. LOCAL tSuccess
  629. doRegularOpts( tOptions* pOpts )
  630. {
  631. /*
  632. * Now, process all the options from our current position onward.
  633. * (This allows interspersed options and arguments for the few
  634. * non-standard programs that require it.)
  635. */
  636. for (;;) {
  637. tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
  638. switch (nextOption( pOpts, &optState )) {
  639. case FAILURE: goto optionsDone;
  640. case PROBLEM: return SUCCESS; /* no more args */
  641. case SUCCESS: break;
  642. }
  643. /*
  644. * IF this is not being processed normally (i.e. is immediate action)
  645. * THEN skip it (unless we are supposed to do it a second time).
  646. */
  647. if (! DO_NORMALLY(optState.flags)) {
  648. if (! DO_SECOND_TIME(optState.flags))
  649. continue;
  650. optState.pOD->optOccCt--; /* don't count last time */
  651. }
  652. if (! SUCCESSFUL( handleOption( pOpts, &optState )))
  653. break;
  654. } optionsDone:;
  655. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
  656. (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
  657. return FAILURE;
  658. }
  659. /*
  660. * doPresets - check for preset values from a config file or the envrionment
  661. */
  662. static tSuccess
  663. doPresets( tOptions* pOpts )
  664. {
  665. if (! SUCCESSFUL( doImmediateOpts( pOpts )))
  666. return FAILURE;
  667. /*
  668. * Until we return from this procedure, disable non-presettable opts
  669. */
  670. pOpts->fOptSet |= OPTPROC_PRESETTING;
  671. /*
  672. * IF there are no config files,
  673. * THEN do any environment presets and leave.
  674. */
  675. if ( (pOpts->papzHomeList == NULL)
  676. || SKIP_RC_FILES(pOpts) ) {
  677. doEnvPresets( pOpts, ENV_ALL );
  678. }
  679. else {
  680. doEnvPresets( pOpts, ENV_IMM );
  681. internalFileLoad( pOpts );
  682. doEnvPresets( pOpts, ENV_NON_IMM );
  683. }
  684. pOpts->fOptSet &= ~OPTPROC_PRESETTING;
  685. return SUCCESS;
  686. }
  687. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  688. *
  689. * VERIFY OPTION CONSISTENCY
  690. *
  691. * Make sure that the argument list passes our consistency tests.
  692. */
  693. static int
  694. checkConsistency( tOptions* pOpts )
  695. {
  696. int errCt = 0;
  697. tOptDesc* pOD = pOpts->pOptDesc;
  698. int oCt = pOpts->presetOptCt;
  699. /*
  700. * FOR each of "oCt" options, ...
  701. */
  702. for (;;) {
  703. const int* pMust = pOD->pOptMust;
  704. const int* pCant = pOD->pOptCant;
  705. /*
  706. * IF the current option was provided on the command line
  707. * THEN ensure that any "MUST" requirements are not
  708. * "DEFAULT" (unspecified) *AND* ensure that any
  709. * "CANT" options have not been SET or DEFINED.
  710. */
  711. if (SELECTED_OPT(pOD)) {
  712. if (pMust != NULL) for (;;) {
  713. tOptDesc* p = pOpts->pOptDesc + *(pMust++);
  714. if (UNUSED_OPT(p)) {
  715. const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
  716. errCt++;
  717. fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
  718. }
  719. if (*pMust == NO_EQUIVALENT)
  720. break;
  721. }
  722. if (pCant != NULL) for (;;) {
  723. tOptDesc* p = pOpts->pOptDesc + *(pCant++);
  724. if (SELECTED_OPT(p)) {
  725. const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
  726. errCt++;
  727. fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
  728. }
  729. if (*pCant == NO_EQUIVALENT)
  730. break;
  731. }
  732. }
  733. /*
  734. * IF this option is not equivalenced to another,
  735. * OR it is equivalenced to itself (is the equiv. root)
  736. * THEN we need to make sure it occurs often enough.
  737. */
  738. if ( (pOD->optEquivIndex == NO_EQUIVALENT)
  739. || (pOD->optEquivIndex == pOD->optIndex) ) do {
  740. /*
  741. * IF the occurrence counts have been satisfied,
  742. * THEN there is no problem.
  743. */
  744. if (pOD->optOccCt >= pOD->optMinCt)
  745. break;
  746. /*
  747. * IF MUST_SET means SET and PRESET are okay,
  748. * so min occurrence count doesn't count
  749. */
  750. if ( (pOD->fOptState & OPTST_MUST_SET)
  751. && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
  752. break;
  753. errCt++;
  754. if (pOD->optMinCt > 1)
  755. fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
  756. else fprintf( stderr, zNeedOne, pOD->pz_Name );
  757. } while (0);
  758. if (--oCt <= 0)
  759. break;
  760. pOD++;
  761. }
  762. /*
  763. * IF we are stopping on errors, check to see if any remaining
  764. * arguments are required to be there or prohibited from being there.
  765. */
  766. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  767. /*
  768. * Check for prohibition
  769. */
  770. if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
  771. if (pOpts->origArgCt > pOpts->curOptIdx) {
  772. fprintf( stderr, zNoArgs, pOpts->pzProgName );
  773. ++errCt;
  774. }
  775. }
  776. /*
  777. * ELSE not prohibited, check for being required
  778. */
  779. else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
  780. if (pOpts->origArgCt <= pOpts->curOptIdx) {
  781. fprintf( stderr, zArgsMust, pOpts->pzProgName );
  782. ++errCt;
  783. }
  784. }
  785. }
  786. return errCt;
  787. }
  788. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  789. *
  790. * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
  791. */
  792. /*=--subblock=arg=arg_type,arg_name,arg_desc =*/
  793. /*=*
  794. * library: opts
  795. * header: your-opts.h
  796. *
  797. * lib_description:
  798. *
  799. * These are the routines that libopts users may call directly from their
  800. * code. There are several other routines that can be called by code
  801. * generated by the libopts option templates, but they are not to be
  802. * called from any other user code. The @file{options.h} header is
  803. * fairly clear about this, too.
  804. =*/
  805. /*=export_func optionProcess
  806. *
  807. * what: this is the main option processing routine
  808. *
  809. * arg: + tOptions* + pOpts + program options descriptor +
  810. * arg: + int + argc + program arg count +
  811. * arg: + char** + argv + program arg vector +
  812. *
  813. * ret_type: int
  814. * ret_desc: the count of the arguments processed
  815. *
  816. * doc:
  817. *
  818. * This is the main entry point for processing options. It is intended
  819. * that this procedure be called once at the beginning of the execution of
  820. * a program. Depending on options selected earlier, it is sometimes
  821. * necessary to stop and restart option processing, or to select completely
  822. * different sets of options. This can be done easily, but you generally
  823. * do not want to do this.
  824. *
  825. * The number of arguments processed always includes the program name.
  826. * If one of the arguments is "--", then it is counted and the processing
  827. * stops. If an error was encountered and errors are to be tolerated, then
  828. * the returned value is the index of the argument causing the error.
  829. * A hyphen by itself ("-") will also cause processing to stop and will
  830. * @emph{not} be counted among the processed arguments. A hyphen by itself
  831. * is treated as an operand. Encountering an operand stops option
  832. * processing.
  833. *
  834. * err: Errors will cause diagnostics to be printed. @code{exit(3)} may
  835. * or may not be called. It depends upon whether or not the options
  836. * were generated with the "allow-errors" attribute, or if the
  837. * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
  838. =*/
  839. int
  840. optionProcess(
  841. tOptions* pOpts,
  842. int argCt,
  843. char** argVect )
  844. {
  845. if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
  846. exit( EXIT_FAILURE );
  847. /*
  848. * Establish the real program name, the program full path,
  849. * and do all the presetting the first time thru only.
  850. */
  851. if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
  852. pOpts->origArgCt = argCt;
  853. pOpts->origArgVect = argVect;
  854. pOpts->fOptSet |= OPTPROC_INITDONE;
  855. if (! SUCCESSFUL( doPresets( pOpts )))
  856. return 0;
  857. if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
  858. optionSort( pOpts );
  859. pOpts->curOptIdx = 1;
  860. pOpts->pzCurOpt = NULL;
  861. }
  862. /*
  863. * IF we are (re)starting,
  864. * THEN reset option location
  865. */
  866. else if (pOpts->curOptIdx <= 0) {
  867. pOpts->curOptIdx = 1;
  868. pOpts->pzCurOpt = NULL;
  869. }
  870. if (! SUCCESSFUL( doRegularOpts( pOpts )))
  871. return pOpts->origArgCt;
  872. /*
  873. * IF there were no errors
  874. * AND we have RC/INI files
  875. * AND there is a request to save the files
  876. * THEN do that now before testing for conflicts.
  877. * (conflicts are ignored in preset options)
  878. */
  879. if (pOpts->specOptIdx.save_opts != 0) {
  880. tOptDesc* pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
  881. if (SELECTED_OPT( pOD )) {
  882. optionSaveFile( pOpts );
  883. exit( EXIT_SUCCESS );
  884. }
  885. }
  886. /*
  887. * IF we are checking for errors,
  888. * THEN look for too few occurrences of required options
  889. */
  890. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  891. if (checkConsistency( pOpts ) != 0)
  892. (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
  893. }
  894. return pOpts->curOptIdx;
  895. }
  896. /*
  897. * Local Variables:
  898. * mode: C
  899. * c-file-style: "stroustrup"
  900. * tab-width: 4
  901. * indent-tabs-mode: nil
  902. * End:
  903. * end of autoopts/autoopts.c */