File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / sntp / libopts / autoopts.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 7 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>