autoopts.c 32 KB

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