Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / sntp / libopts / autoopts.c
blob7dcd437578d966144837798cbdcdc3155137df9c
1 /* $NetBSD$ */
4 /*
5 * Id: 56abb301f50605ec5bae137ded730e330d8d7735
6 * Time-stamp: "2009-11-01 10:50:34 bkorb"
8 * This file contains all of the routines that must be linked into
9 * an executable to use the generated option processing. The optional
10 * routines are in separately compiled modules so that they will not
11 * necessarily be linked in.
13 * This file is part of AutoOpts, a companion to AutoGen.
14 * AutoOpts is free software.
15 * AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
17 * AutoOpts is available under any one of two licenses. The license
18 * in use must be one of these two and the choice is under the control
19 * of the user of the license.
21 * The GNU Lesser General Public License, version 3 or later
22 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
24 * The Modified Berkeley Software Distribution License
25 * See the file "COPYING.mbsd"
27 * These files have the following md5sums:
29 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
30 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
31 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
34 static char const zNil[] = "";
36 /* = = = START-STATIC-FORWARD = = = */
37 /* static forward declarations maintained by mk-fwd */
38 static tSuccess
39 findOptDesc( tOptions* pOpts, tOptState* pOptState );
41 static tSuccess
42 next_opt_arg_must(tOptions* pOpts, tOptState* pOptState);
44 static tSuccess
45 next_opt_arg_may(tOptions* pOpts, tOptState* pOptState);
47 static tSuccess
48 next_opt_arg_none(tOptions* pOpts, tOptState* pOptState);
50 static tSuccess
51 nextOption(tOptions* pOpts, tOptState* pOptState);
53 static tSuccess
54 doPresets( tOptions* pOpts );
56 static int
57 checkConsistency( tOptions* pOpts );
58 /* = = = END-STATIC-FORWARD = = = */
60 LOCAL void *
61 ao_malloc( size_t sz )
63 void * res = malloc(sz);
64 if (res == NULL) {
65 fprintf( stderr, "malloc of %d bytes failed\n", (int)sz );
66 exit( EXIT_FAILURE );
68 return res;
70 #undef malloc
71 #define malloc(_s) ao_malloc(_s)
73 LOCAL void *
74 ao_realloc( void *p, size_t sz )
76 void * res = realloc(p, sz);
77 if (res == NULL) {
78 fprintf( stderr, "realloc of %d bytes at 0x%p failed\n", (int)sz, p );
79 exit( EXIT_FAILURE );
81 return res;
83 #undef realloc
84 #define realloc(_p,_s) ao_realloc(_p,_s)
87 LOCAL void
88 ao_free( void *p )
90 if (p != NULL)
91 free(p);
93 #undef free
94 #define free(_p) ao_free(_p)
97 LOCAL char *
98 ao_strdup( char const *str )
100 char * res = strdup(str);
101 if (res == NULL) {
102 fprintf(stderr, "strdup of %d byte string failed\n", (int)strlen(str));
103 exit( EXIT_FAILURE );
105 return res;
107 #undef strdup
108 #define strdup(_p) ao_strdup(_p)
110 #ifndef HAVE_PATHFIND
111 # include "compat/pathfind.c"
112 #endif
114 #ifndef HAVE_SNPRINTF
115 # include "compat/snprintf.c"
116 #endif
118 #ifndef HAVE_STRDUP
119 # include "compat/strdup.c"
120 #endif
122 #ifndef HAVE_STRCHR
123 # include "compat/strchr.c"
124 #endif
127 * handleOption
129 * This routine handles equivalencing, sets the option state flags and
130 * invokes the handler procedure, if any.
132 LOCAL tSuccess
133 handleOption( tOptions* pOpts, tOptState* pOptState )
136 * Save a copy of the option procedure pointer.
137 * If this is an equivalence class option, we still want this proc.
139 tOptDesc* pOD = pOptState->pOD;
140 tOptProc* pOP = pOD->pOptProc;
141 if (pOD->fOptState & OPTST_ALLOC_ARG)
142 AGFREE(pOD->optArg.argString);
144 pOD->optArg.argString = pOptState->pzOptArg;
147 * IF we are presetting options, then we will ignore any un-presettable
148 * options. They are the ones either marked as such.
150 if ( ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
151 && ((pOD->fOptState & OPTST_NO_INIT) != 0)
153 return PROBLEM;
156 * IF this is an equivalence class option,
157 * THEN
158 * Save the option value that got us to this option
159 * entry. (It may not be pOD->optChar[0], if this is an
160 * equivalence entry.)
161 * set the pointer to the equivalence class base
163 if (pOD->optEquivIndex != NO_EQUIVALENT) {
164 tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
167 * IF the current option state has not been defined (set on the
168 * command line), THEN we will allow continued resetting of
169 * the value. Once "defined", then it must not change.
171 if ((pOD->fOptState & OPTST_DEFINED) != 0) {
173 * The equivalenced-to option has been found on the command
174 * line before. Make sure new occurrences are the same type.
176 * IF this option has been previously equivalenced and
177 * it was not the same equivalenced-to option,
178 * THEN we have a usage problem.
180 if (p->optActualIndex != pOD->optIndex) {
181 fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
182 (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
183 return FAILURE;
185 } else {
187 * Set the equivalenced-to actual option index to no-equivalent
188 * so that we set all the entries below. This option may either
189 * never have been selected before, or else it was selected by
190 * some sort of "presetting" mechanism.
192 p->optActualIndex = NO_EQUIVALENT;
195 if (p->optActualIndex != pOD->optIndex) {
197 * First time through, copy over the state
198 * and add in the equivalence flag
200 p->optActualValue = pOD->optValue;
201 p->optActualIndex = pOD->optIndex;
202 pOptState->flags |= OPTST_EQUIVALENCE;
206 * Copy the most recent option argument. set membership state
207 * is kept in ``p->optCookie''. Do not overwrite.
209 p->optArg.argString = pOD->optArg.argString;
210 pOD = p;
212 } else {
213 pOD->optActualValue = pOD->optValue;
214 pOD->optActualIndex = pOD->optIndex;
217 pOD->fOptState &= OPTST_PERSISTENT_MASK;
218 pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT_MASK);
221 * Keep track of count only for DEFINED (command line) options.
222 * IF we have too many, build up an error message and bail.
224 if ( (pOD->fOptState & OPTST_DEFINED)
225 && (++pOD->optOccCt > pOD->optMaxCt) ) {
227 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
228 char const * pzEqv =
229 (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
231 fputs( zErrOnly, stderr );
233 if (pOD->optMaxCt > 1)
234 fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv);
235 else
236 fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv);
239 return FAILURE;
243 * If provided a procedure to call, call it
245 if (pOP != NULL)
246 (*pOP)( pOpts, pOD );
248 return SUCCESS;
252 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
254 * HUNT FOR OPTIONS IN THE ARGUMENT LIST
256 * The next four procedures are "private" to nextOption().
257 * nextOption() uses findOptDesc() to find the next descriptor and it, in
258 * turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
260 * longOptionFind
262 * Find the long option descriptor for the current option
264 LOCAL tSuccess
265 longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
267 ag_bool disable = AG_FALSE;
268 char* pzEq = strchr( pzOptName, '=' );
269 tOptDesc* pOD = pOpts->pOptDesc;
270 int idx = 0;
271 int idxLim = pOpts->optCt;
272 int matchCt = 0;
273 int matchIdx = 0;
274 int nameLen;
275 char opt_name_buf[128];
278 * IF the value is attached to the name,
279 * copy it off so we can NUL terminate.
281 if (pzEq != NULL) {
282 nameLen = (int)(pzEq - pzOptName);
283 if (nameLen >= sizeof(opt_name_buf))
284 return FAILURE;
285 memcpy(opt_name_buf, pzOptName, nameLen);
286 opt_name_buf[nameLen] = NUL;
287 pzOptName = opt_name_buf;
288 pzEq++;
290 } else nameLen = strlen( pzOptName );
292 do {
293 if (SKIP_OPT(pOD)) {
294 if ( (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))
295 || (pOD->pz_Name == NULL))
296 continue;
298 else assert(pOD->pz_Name != NULL);
300 if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
302 * IF we have a complete match
303 * THEN it takes priority over any already located partial
305 if (pOD->pz_Name[ nameLen ] == NUL) {
306 matchCt = 1;
307 matchIdx = idx;
308 break;
313 * IF there is a disable name
314 * *AND* no argument value has been supplied
315 * (disabled options may have no argument)
316 * *AND* the option name matches the disable name
317 * THEN ...
319 else if ( (pOD->pz_DisableName != NULL)
320 && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
322 disable = AG_TRUE;
325 * IF we have a complete match
326 * THEN it takes priority over any already located partial
328 if (pOD->pz_DisableName[ nameLen ] == NUL) {
329 matchCt = 1;
330 matchIdx = idx;
331 break;
335 else
336 continue;
339 * We found a partial match, either regular or disabling.
340 * Remember the index for later.
342 matchIdx = idx;
344 if (++matchCt > 1)
345 break;
347 } while (pOD++, (++idx < idxLim));
350 * Make sure we either found an exact match or found only one partial
352 if (matchCt == 1) {
353 pOD = pOpts->pOptDesc + matchIdx;
355 if (SKIP_OPT(pOD)) {
356 fprintf(stderr, zDisabledErr, pOpts->pzProgName, pOD->pz_Name);
357 if (pOD->pzText != NULL)
358 fprintf(stderr, " -- %s", pOD->pzText);
359 fputc('\n', stderr);
360 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
361 /* NOTREACHED */
365 * IF we found a disablement name,
366 * THEN set the bit in the callers' flag word
368 if (disable)
369 pOptState->flags |= OPTST_DISABLED;
371 pOptState->pOD = pOD;
372 pOptState->pzOptArg = pzEq;
373 pOptState->optType = TOPT_LONG;
374 return SUCCESS;
378 * IF there is no equal sign
379 * *AND* we are using named arguments
380 * *AND* there is a default named option,
381 * THEN return that option.
383 if ( (pzEq == NULL)
384 && NAMED_OPTS(pOpts)
385 && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
386 pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
388 pOptState->pzOptArg = pzOptName;
389 pOptState->optType = TOPT_DEFAULT;
390 return SUCCESS;
394 * IF we are to stop on errors (the default, actually)
395 * THEN call the usage procedure.
397 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
398 fprintf(stderr, (matchCt == 0) ? zIllOptStr : zAmbigOptStr,
399 pOpts->pzProgPath, pzOptName);
400 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
403 return FAILURE;
408 * shortOptionFind
410 * Find the short option descriptor for the current option
412 LOCAL tSuccess
413 shortOptionFind( tOptions* pOpts, uint_t optValue, tOptState* pOptState )
415 tOptDesc* pRes = pOpts->pOptDesc;
416 int ct = pOpts->optCt;
419 * Search the option list
421 do {
422 if (optValue != pRes->optValue)
423 continue;
425 if (SKIP_OPT(pRes)) {
426 if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
427 && (pRes->pz_Name != NULL)) {
428 fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name);
429 if (pRes->pzText != NULL)
430 fprintf(stderr, " -- %s", pRes->pzText);
431 fputc('\n', stderr);
432 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
433 /* NOTREACHED */
435 goto short_opt_error;
438 pOptState->pOD = pRes;
439 pOptState->optType = TOPT_SHORT;
440 return SUCCESS;
442 } while (pRes++, --ct > 0);
445 * IF the character value is a digit
446 * AND there is a special number option ("-n")
447 * THEN the result is the "option" itself and the
448 * option is the specially marked "number" option.
450 if ( IS_DEC_DIGIT_CHAR(optValue)
451 && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
452 pOptState->pOD = \
453 pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
454 (pOpts->pzCurOpt)--;
455 pOptState->optType = TOPT_SHORT;
456 return SUCCESS;
459 short_opt_error:
462 * IF we are to stop on errors (the default, actually)
463 * THEN call the usage procedure.
465 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
466 fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
467 (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
470 return FAILURE;
475 * findOptDesc
477 * Find the option descriptor for the current option
479 static tSuccess
480 findOptDesc( tOptions* pOpts, tOptState* pOptState )
483 * IF we are continuing a short option list (e.g. -xyz...)
484 * THEN continue a single flag option.
485 * OTHERWISE see if there is room to advance and then do so.
487 if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
488 return shortOptionFind( pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState );
490 if (pOpts->curOptIdx >= pOpts->origArgCt)
491 return PROBLEM; /* NORMAL COMPLETION */
493 pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
496 * IF all arguments must be named options, ...
498 if (NAMED_OPTS(pOpts)) {
499 char * pz = pOpts->pzCurOpt;
500 int def;
501 tSuccess res;
502 tAoUS * def_opt;
504 pOpts->curOptIdx++;
506 if (*pz != '-')
507 return longOptionFind(pOpts, pz, pOptState);
510 * The name is prefixed with one or more hyphens. Strip them off
511 * and disable the "default_opt" setting. Use heavy recasting to
512 * strip off the "const" quality of the "default_opt" field.
514 while (*(++pz) == '-') ;
515 def_opt = (void *)&(pOpts->specOptIdx.default_opt);
516 def = *def_opt;
517 *def_opt = NO_EQUIVALENT;
518 res = longOptionFind(pOpts, pz, pOptState);
519 *def_opt = def;
520 return res;
524 * Note the kind of flag/option marker
526 if (*((pOpts->pzCurOpt)++) != '-')
527 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
530 * Special hack for a hyphen by itself
532 if (*(pOpts->pzCurOpt) == NUL)
533 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
536 * The current argument is to be processed as an option argument
538 pOpts->curOptIdx++;
541 * We have an option marker.
542 * Test the next character for long option indication
544 if (pOpts->pzCurOpt[0] == '-') {
545 if (*++(pOpts->pzCurOpt) == NUL)
547 * NORMAL COMPLETION - NOT this arg, but rest are operands
549 return PROBLEM;
552 * We do not allow the hyphen to be used as a flag value.
553 * Therefore, if long options are not to be accepted, we punt.
555 if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
556 fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
557 zIllegal, pOpts->pzCurOpt-2 );
558 return FAILURE;
561 return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
565 * If short options are not allowed, then do long
566 * option processing. Otherwise the character must be a
567 * short (i.e. single character) option.
569 if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
570 return shortOptionFind( pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState );
572 return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
576 static tSuccess
577 next_opt_arg_must(tOptions* pOpts, tOptState* pOptState)
580 * An option argument is required. Long options can either have
581 * a separate command line argument, or an argument attached by
582 * the '=' character. Figure out which.
584 switch (pOptState->optType) {
585 case TOPT_SHORT:
587 * See if an arg string follows the flag character
589 if (*++(pOpts->pzCurOpt) == NUL)
590 pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
591 pOptState->pzOptArg = pOpts->pzCurOpt;
592 break;
594 case TOPT_LONG:
596 * See if an arg string has already been assigned (glued on
597 * with an `=' character)
599 if (pOptState->pzOptArg == NULL)
600 pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
601 break;
603 default:
604 #ifdef DEBUG
605 fputs( "AutoOpts lib error: option type not selected\n",
606 stderr );
607 exit( EXIT_FAILURE );
608 #endif
610 case TOPT_DEFAULT:
612 * The option was selected by default. The current token is
613 * the option argument.
615 break;
619 * Make sure we did not overflow the argument list.
621 if (pOpts->curOptIdx > pOpts->origArgCt) {
622 fprintf( stderr, zMisArg, pOpts->pzProgPath,
623 pOptState->pOD->pz_Name );
624 return FAILURE;
627 pOpts->pzCurOpt = NULL; /* next time advance to next arg */
628 return SUCCESS;
632 static tSuccess
633 next_opt_arg_may(tOptions* pOpts, tOptState* pOptState)
636 * An option argument is optional.
638 switch (pOptState->optType) {
639 case TOPT_SHORT:
640 if (*++pOpts->pzCurOpt != NUL)
641 pOptState->pzOptArg = pOpts->pzCurOpt;
642 else {
643 char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
646 * BECAUSE it is optional, we must make sure
647 * we did not find another flag and that there
648 * is such an argument.
650 if ((pzLA == NULL) || (*pzLA == '-'))
651 pOptState->pzOptArg = NULL;
652 else {
653 pOpts->curOptIdx++; /* argument found */
654 pOptState->pzOptArg = pzLA;
657 break;
659 case TOPT_LONG:
661 * Look for an argument if we don't already have one (glued on
662 * with a `=' character) *AND* we are not in named argument mode
664 if ( (pOptState->pzOptArg == NULL)
665 && (! NAMED_OPTS(pOpts))) {
666 char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
669 * BECAUSE it is optional, we must make sure
670 * we did not find another flag and that there
671 * is such an argument.
673 if ((pzLA == NULL) || (*pzLA == '-'))
674 pOptState->pzOptArg = NULL;
675 else {
676 pOpts->curOptIdx++; /* argument found */
677 pOptState->pzOptArg = pzLA;
680 break;
682 default:
683 case TOPT_DEFAULT:
684 fputs(zAO_Woops, stderr );
685 exit( EX_SOFTWARE );
689 * After an option with an optional argument, we will
690 * *always* start with the next option because if there
691 * were any characters following the option name/flag,
692 * they would be interpreted as the argument.
694 pOpts->pzCurOpt = NULL;
695 return SUCCESS;
699 static tSuccess
700 next_opt_arg_none(tOptions* pOpts, tOptState* pOptState)
703 * No option argument. Make sure next time around we find
704 * the correct option flag character for short options
706 if (pOptState->optType == TOPT_SHORT)
707 (pOpts->pzCurOpt)++;
710 * It is a long option. Make sure there was no ``=xxx'' argument
712 else if (pOptState->pzOptArg != NULL) {
713 fprintf(stderr, zNoArg, pOpts->pzProgPath, pOptState->pOD->pz_Name);
714 return FAILURE;
718 * It is a long option. Advance to next command line argument.
720 else
721 pOpts->pzCurOpt = NULL;
722 return SUCCESS;
726 * nextOption
728 * Find the option descriptor and option argument (if any) for the
729 * next command line argument. DO NOT modify the descriptor. Put
730 * all the state in the state argument so that the option can be skipped
731 * without consequence (side effect).
733 static tSuccess
734 nextOption(tOptions* pOpts, tOptState* pOptState)
737 tSuccess res;
738 res = findOptDesc( pOpts, pOptState );
739 if (! SUCCESSFUL( res ))
740 return res;
743 if ( ((pOptState->flags & OPTST_DEFINED) != 0)
744 && ((pOptState->pOD->fOptState & OPTST_NO_COMMAND) != 0)) {
745 fprintf(stderr, zNotCmdOpt, pOptState->pOD->pz_Name);
746 return FAILURE;
749 pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT_MASK);
752 * Figure out what to do about option arguments. An argument may be
753 * required, not associated with the option, or be optional. We detect the
754 * latter by examining for an option marker on the next possible argument.
755 * Disabled mode option selection also disables option arguments.
758 enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
759 tSuccess res;
761 if ((pOptState->flags & OPTST_DISABLED) != 0)
762 arg_type = ARG_NONE;
764 else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE)
765 arg_type = ARG_NONE;
767 else if (pOptState->flags & OPTST_ARG_OPTIONAL)
768 arg_type = ARG_MAY;
770 else
771 arg_type = ARG_MUST;
773 switch (arg_type) {
774 case ARG_MUST: res = next_opt_arg_must(pOpts, pOptState); break;
775 case ARG_MAY: res = next_opt_arg_may( pOpts, pOptState); break;
776 case ARG_NONE: res = next_opt_arg_none(pOpts, pOptState); break;
779 return res;
784 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
786 * DO PRESETS
788 * The next several routines do the immediate action pass on the command
789 * line options, then the environment variables, then the config files in
790 * reverse order. Once done with that, the order is reversed and all
791 * the config files and environment variables are processed again, this
792 * time only processing the non-immediate action options. doPresets()
793 * will then return for optionProcess() to do the final pass on the command
794 * line arguments.
798 * doImmediateOpts - scan the command line for immediate action options
800 LOCAL tSuccess
801 doImmediateOpts( tOptions* pOpts )
803 pOpts->curOptIdx = 1; /* start by skipping program name */
804 pOpts->pzCurOpt = NULL;
807 * Examine all the options from the start. We process any options that
808 * are marked for immediate processing.
810 for (;;) {
811 tOptState optState = OPTSTATE_INITIALIZER(PRESET);
813 switch (nextOption( pOpts, &optState )) {
814 case FAILURE: goto optionsDone;
815 case PROBLEM: return SUCCESS; /* no more args */
816 case SUCCESS: break;
820 * IF this *is* an immediate-attribute option, then do it.
822 if (! DO_IMMEDIATELY(optState.flags))
823 continue;
825 if (! SUCCESSFUL( handleOption( pOpts, &optState )))
826 break;
827 } optionsDone:;
829 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
830 (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
831 return FAILURE;
835 LOCAL tSuccess
836 doRegularOpts( tOptions* pOpts )
839 * Now, process all the options from our current position onward.
840 * (This allows interspersed options and arguments for the few
841 * non-standard programs that require it.)
843 for (;;) {
844 tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
846 switch (nextOption( pOpts, &optState )) {
847 case FAILURE: goto optionsDone;
848 case PROBLEM: return SUCCESS; /* no more args */
849 case SUCCESS: break;
853 * IF this is not being processed normally (i.e. is immediate action)
854 * THEN skip it (unless we are supposed to do it a second time).
856 if (! DO_NORMALLY(optState.flags)) {
857 if (! DO_SECOND_TIME(optState.flags))
858 continue;
859 optState.pOD->optOccCt--; /* don't count last time */
862 if (! SUCCESSFUL( handleOption( pOpts, &optState )))
863 break;
864 } optionsDone:;
865 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
866 (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
867 return FAILURE;
872 * doPresets - check for preset values from a config file or the envrionment
874 static tSuccess
875 doPresets( tOptions* pOpts )
877 tOptDesc * pOD = NULL;
879 if (! SUCCESSFUL( doImmediateOpts( pOpts )))
880 return FAILURE;
883 * IF this option set has a --save-opts option, then it also
884 * has a --load-opts option. See if a command line option has disabled
885 * option presetting.
887 if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
888 && (pOpts->specOptIdx.save_opts != 0)) {
889 pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
890 if (DISABLED_OPT(pOD))
891 return SUCCESS;
895 * Until we return from this procedure, disable non-presettable opts
897 pOpts->fOptSet |= OPTPROC_PRESETTING;
899 * IF there are no config files,
900 * THEN do any environment presets and leave.
902 if (pOpts->papzHomeList == NULL) {
903 doEnvPresets( pOpts, ENV_ALL );
905 else {
906 doEnvPresets( pOpts, ENV_IMM );
909 * Check to see if environment variables have disabled presetting.
911 if ((pOD != NULL) && ! DISABLED_OPT(pOD))
912 internalFileLoad( pOpts );
915 * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment
916 * variable options. Only the loading of .rc files.
918 doEnvPresets( pOpts, ENV_NON_IMM );
920 pOpts->fOptSet &= ~OPTPROC_PRESETTING;
922 return SUCCESS;
926 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
928 * VERIFY OPTION CONSISTENCY
930 * Make sure that the argument list passes our consistency tests.
932 static int
933 checkConsistency( tOptions* pOpts )
935 int errCt = 0;
936 tOptDesc* pOD = pOpts->pOptDesc;
937 int oCt = pOpts->presetOptCt;
940 * FOR each of "oCt" options, ...
942 for (;;) {
943 const int* pMust = pOD->pOptMust;
944 const int* pCant = pOD->pOptCant;
947 * IF the current option was provided on the command line
948 * THEN ensure that any "MUST" requirements are not
949 * "DEFAULT" (unspecified) *AND* ensure that any
950 * "CANT" options have not been SET or DEFINED.
952 if (SELECTED_OPT(pOD)) {
953 if (pMust != NULL) for (;;) {
954 tOptDesc* p = pOpts->pOptDesc + *(pMust++);
955 if (UNUSED_OPT(p)) {
956 const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
957 errCt++;
958 fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
961 if (*pMust == NO_EQUIVALENT)
962 break;
965 if (pCant != NULL) for (;;) {
966 tOptDesc* p = pOpts->pOptDesc + *(pCant++);
967 if (SELECTED_OPT(p)) {
968 const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
969 errCt++;
970 fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
973 if (*pCant == NO_EQUIVALENT)
974 break;
979 * IF this option is not equivalenced to another,
980 * OR it is equivalenced to itself (is the equiv. root)
981 * THEN we need to make sure it occurs often enough.
983 if ( (pOD->optEquivIndex == NO_EQUIVALENT)
984 || (pOD->optEquivIndex == pOD->optIndex) ) do {
986 * IF the occurrence counts have been satisfied,
987 * THEN there is no problem.
989 if (pOD->optOccCt >= pOD->optMinCt)
990 break;
993 * IF MUST_SET means SET and PRESET are okay,
994 * so min occurrence count doesn't count
996 if ( (pOD->fOptState & OPTST_MUST_SET)
997 && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
998 break;
1000 errCt++;
1001 if (pOD->optMinCt > 1)
1002 fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
1003 else fprintf( stderr, zNeedOne, pOD->pz_Name );
1004 } while (0);
1006 if (--oCt <= 0)
1007 break;
1008 pOD++;
1012 * IF we are stopping on errors, check to see if any remaining
1013 * arguments are required to be there or prohibited from being there.
1015 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
1018 * Check for prohibition
1020 if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
1021 if (pOpts->origArgCt > pOpts->curOptIdx) {
1022 fprintf( stderr, zNoArgs, pOpts->pzProgName );
1023 ++errCt;
1028 * ELSE not prohibited, check for being required
1030 else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
1031 if (pOpts->origArgCt <= pOpts->curOptIdx) {
1032 fprintf( stderr, zArgsMust, pOpts->pzProgName );
1033 ++errCt;
1038 return errCt;
1042 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1044 * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
1046 /*=--subblock=arg=arg_type,arg_name,arg_desc =*/
1047 /*=*
1048 * library: opts
1049 * header: your-opts.h
1051 * lib_description:
1053 * These are the routines that libopts users may call directly from their
1054 * code. There are several other routines that can be called by code
1055 * generated by the libopts option templates, but they are not to be
1056 * called from any other user code. The @file{options.h} header is
1057 * fairly clear about this, too.
1060 /*=export_func optionProcess
1062 * what: this is the main option processing routine
1064 * arg: + tOptions* + pOpts + program options descriptor +
1065 * arg: + int + argc + program arg count +
1066 * arg: + char** + argv + program arg vector +
1068 * ret_type: int
1069 * ret_desc: the count of the arguments processed
1071 * doc:
1073 * This is the main entry point for processing options. It is intended
1074 * that this procedure be called once at the beginning of the execution of
1075 * a program. Depending on options selected earlier, it is sometimes
1076 * necessary to stop and restart option processing, or to select completely
1077 * different sets of options. This can be done easily, but you generally
1078 * do not want to do this.
1080 * The number of arguments processed always includes the program name.
1081 * If one of the arguments is "--", then it is counted and the processing
1082 * stops. If an error was encountered and errors are to be tolerated, then
1083 * the returned value is the index of the argument causing the error.
1084 * A hyphen by itself ("-") will also cause processing to stop and will
1085 * @emph{not} be counted among the processed arguments. A hyphen by itself
1086 * is treated as an operand. Encountering an operand stops option
1087 * processing.
1089 * err: Errors will cause diagnostics to be printed. @code{exit(3)} may
1090 * or may not be called. It depends upon whether or not the options
1091 * were generated with the "allow-errors" attribute, or if the
1092 * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
1095 optionProcess(
1096 tOptions* pOpts,
1097 int argCt,
1098 char** argVect )
1100 if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
1101 exit( EX_SOFTWARE );
1104 * Establish the real program name, the program full path,
1105 * and do all the presetting the first time thru only.
1107 if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
1108 pOpts->origArgCt = argCt;
1109 pOpts->origArgVect = argVect;
1110 pOpts->fOptSet |= OPTPROC_INITDONE;
1112 if (! SUCCESSFUL( doPresets( pOpts )))
1113 return 0;
1116 * IF option name conversion was suppressed but it is not suppressed
1117 * for the command line, then it's time to translate option names.
1118 * Usage text will not get retranslated.
1120 if ( ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0)
1121 && (pOpts->pTransProc != NULL)
1122 && ((pOpts->fOptSet & OPTPROC_NO_XLAT_MASK)
1123 == OPTPROC_NXLAT_OPT_CFG) ) {
1125 pOpts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG;
1126 (*pOpts->pTransProc)();
1129 if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
1130 optionSort( pOpts );
1132 pOpts->curOptIdx = 1;
1133 pOpts->pzCurOpt = NULL;
1137 * IF we are (re)starting,
1138 * THEN reset option location
1140 else if (pOpts->curOptIdx <= 0) {
1141 pOpts->curOptIdx = 1;
1142 pOpts->pzCurOpt = NULL;
1145 if (! SUCCESSFUL( doRegularOpts( pOpts )))
1146 return pOpts->origArgCt;
1149 * IF there were no errors
1150 * AND we have RC/INI files
1151 * AND there is a request to save the files
1152 * THEN do that now before testing for conflicts.
1153 * (conflicts are ignored in preset options)
1155 if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
1156 && (pOpts->specOptIdx.save_opts != 0)) {
1157 tOptDesc* pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
1159 if (SELECTED_OPT( pOD )) {
1160 optionSaveFile( pOpts );
1161 exit( EXIT_SUCCESS );
1166 * IF we are checking for errors,
1167 * THEN look for too few occurrences of required options
1169 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
1170 if (checkConsistency( pOpts ) != 0)
1171 (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
1174 return pOpts->curOptIdx;
1178 * Local Variables:
1179 * mode: C
1180 * c-file-style: "stroustrup"
1181 * indent-tabs-mode: nil
1182 * End:
1183 * end of autoopts/autoopts.c */