1
0

autoopts.c 33 KB

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