File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / sntp / libopts / putshell.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 putshell.c
    4:  *
    5:  * Time-stamp:      "2010-09-05 06:10:56 bkorb"
    6:  *
    7:  *  This module will interpret the options set in the tOptions
    8:  *  structure and print them to standard out in a fashion that
    9:  *  will allow them to be interpreted by the Bourne or Korn shells.
   10:  *
   11:  *  This file is part of AutoOpts, a companion to AutoGen.
   12:  *  AutoOpts is free software.
   13:  *  AutoOpts is Copyright (c) 1992-2011 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:  *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
   28:  *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
   29:  *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
   30:  */
   31: static char const zOptValFmt[] = "%s_%s=";
   32: static char const zOptEnd[]    = "\nexport %s_%s\n";
   33: static char const zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
   34: 
   35: /* = = = START-STATIC-FORWARD = = = */
   36: static void
   37: print_quot_str(tCC* pzStr);
   38: 
   39: static void
   40: print_enumeration(tOptions * pOpts, tOptDesc * pOD);
   41: 
   42: static void
   43: print_membership(tOptions * pOpts, tOptDesc * pOD);
   44: 
   45: static void
   46: print_stacked_arg(tOptions * pOpts, tOptDesc * pOD);
   47: 
   48: static void
   49: print_reordering(tOptions * pOpts);
   50: /* = = = END-STATIC-FORWARD = = = */
   51: 
   52: /*
   53:  *  Make sure embedded single quotes come out okay.  The initial quote has
   54:  *  been emitted and the closing quote will be upon return.
   55:  */
   56: static void
   57: print_quot_str(tCC* pzStr)
   58: {
   59:     /*
   60:      *  Handle empty strings to make the rest of the logic simpler.
   61:      */
   62:     if ((pzStr == NULL) || (*pzStr == NUL)) {
   63:         fputs("''", stdout);
   64:         return;
   65:     }
   66: 
   67:     /*
   68:      *  Emit any single quotes/apostrophes at the start of the string and
   69:      *  bail if that is all we need to do.
   70:      */
   71:     while (*pzStr == '\'') {
   72:         fputs("\\'", stdout);
   73:         pzStr++;
   74:     }
   75:     if (*pzStr == NUL)
   76:         return;
   77: 
   78:     /*
   79:      *  Start the single quote string
   80:      */
   81:     fputc('\'', stdout);
   82:     for (;;) {
   83:         tCC* pz = strchr(pzStr, '\'');
   84:         if (pz == NULL)
   85:             break;
   86: 
   87:         /*
   88:          *  Emit the string up to the single quote (apostrophe) we just found.
   89:          */
   90:         (void)fwrite(pzStr, (size_t)(pz - pzStr), (size_t)1, stdout);
   91:         fputc('\'', stdout);
   92:         pzStr = pz;
   93: 
   94:         /*
   95:          *  Emit an escaped apostrophe for every one we find.
   96:          *  If that ends the string, do not re-open the single quotes.
   97:          */
   98:         while (*++pzStr == '\'')   fputs("\\'", stdout);
   99:         if (*pzStr == NUL)
  100:             return;
  101: 
  102:         fputc('\'', stdout);
  103:     }
  104: 
  105:     /*
  106:      *  If we broke out of the loop, we must still emit the remaining text
  107:      *  and then close the single quote string.
  108:      */
  109:     fputs(pzStr, stdout);
  110:     fputc('\'', stdout);
  111: }
  112: 
  113: static void
  114: print_enumeration(tOptions * pOpts, tOptDesc * pOD)
  115: {
  116:     uintptr_t e_val = pOD->optArg.argEnum;
  117:     printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME);
  118: 
  119:     /*
  120:      *  Convert value to string, print that and restore numeric value.
  121:      */
  122:     (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD);
  123:     printf("'%s'", pOD->optArg.argString);
  124:     if (pOD->fOptState & OPTST_ALLOC_ARG)
  125:         AGFREE(pOD->optArg.argString);
  126:     pOD->optArg.argEnum = e_val;
  127: 
  128:     printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME);
  129: }
  130: 
  131: static void
  132: print_membership(tOptions * pOpts, tOptDesc * pOD)
  133: {
  134:     char const * pz;
  135:     uintptr_t val = 1;
  136:     printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
  137:            (int)(uintptr_t)(pOD->optCookie));
  138:     pOD->optCookie = (void*)(uintptr_t)~0UL;
  139:     (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD);
  140: 
  141:     /*
  142:      *  We are building the typeset list.  The list returned starts with
  143:      *  'none + ' for use by option saving stuff.  We must ignore that.
  144:      */
  145:     pz = pOD->optArg.argString + 7;
  146:     while (*pz != NUL) {
  147:         printf("typeset -x -i %s_", pOD->pz_NAME);
  148:         while (IS_PLUS_N_SPACE_CHAR(*pz))  pz++;
  149: 
  150:         for (;;) {
  151:             int ch = *(pz++);
  152:             if (IS_LOWER_CASE_CHAR(ch))   fputc(toupper(ch), stdout);
  153:             else if (IS_UPPER_CASE_CHAR(ch))   fputc(ch, stdout);
  154:             else if (IS_PLUS_N_SPACE_CHAR(ch)) goto name_done;
  155:             else if (ch == NUL)        { pz--; goto name_done; }
  156:             else fputc('_', stdout);
  157:         } name_done:;
  158:         printf("=%1$lu # 0x%1$lX\n", (unsigned long)val);
  159:         val <<= 1;
  160:     }
  161: 
  162:     AGFREE(pOD->optArg.argString);
  163:     pOD->optArg.argString = NULL;
  164:     pOD->fOptState &= ~OPTST_ALLOC_ARG;
  165: }
  166: 
  167: static void
  168: print_stacked_arg(tOptions * pOpts, tOptDesc * pOD)
  169: {
  170:     tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";
  171: 
  172:     tArgList*    pAL = (tArgList*)pOD->optCookie;
  173:     tCC**        ppz = pAL->apzArgs;
  174:     int          ct  = pAL->useCt;
  175: 
  176:     printf(zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct);
  177: 
  178:     while (--ct >= 0) {
  179:         tSCC numarg_z[] = "%s_%s_%d=";
  180:         tSCC end_z[]    = "\nexport %s_%s_%d\n";
  181: 
  182:         printf(numarg_z, pOpts->pzPROGNAME, pOD->pz_NAME,
  183:                pAL->useCt - ct);
  184:         print_quot_str(*(ppz++));
  185:         printf(end_z, pOpts->pzPROGNAME, pOD->pz_NAME,
  186:                pAL->useCt - ct);
  187:     }
  188: }
  189: 
  190: static void
  191: print_reordering(tOptions * pOpts)
  192: {
  193:     int  optIx;
  194: 
  195:     fputs("set --", stdout);
  196: 
  197:     for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
  198: 
  199:         char* pzArg = pOpts->origArgVect[ optIx ];
  200: 
  201:         if (strchr(pzArg, '\'') == NULL)
  202:             printf(" '%s'", pzArg);
  203: 
  204:         else {
  205:             fputs(" '", stdout);
  206:             for (;;) {
  207:                 char ch = *(pzArg++);
  208:                 switch (ch) {
  209:                 case '\'':  fputs("'\\''", stdout); break;
  210:                 case NUL:   goto arg_done;
  211:                 default:    fputc(ch, stdout); break;
  212:                 }
  213:             } arg_done:;
  214:             fputc('\'', stdout);
  215:         }
  216:     }
  217:     fputs("\nOPTION_CT=0\n", stdout);
  218: }
  219: 
  220: /*=export_func  optionPutShell
  221:  * what:  write a portable shell script to parse options
  222:  * private:
  223:  * arg:   tOptions*, pOpts, the program options descriptor
  224:  * doc:   This routine will emit portable shell script text for parsing
  225:  *        the options described in the option definitions.
  226: =*/
  227: void
  228: optionPutShell(tOptions* pOpts)
  229: {
  230:     int  optIx = 0;
  231:     tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
  232:     tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
  233:     tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
  234:     tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";
  235: 
  236:     printf(zOptCtFmt, pOpts->curOptIdx-1);
  237: 
  238:     do  {
  239:         tOptDesc* pOD = pOpts->pOptDesc + optIx;
  240: 
  241:         if (SKIP_OPT(pOD))
  242:             continue;
  243: 
  244:         /*
  245:          *  Equivalence classes are hard to deal with.  Where the
  246:          *  option data wind up kind of squishes around.  For the purposes
  247:          *  of emitting shell state, they are not recommended, but we'll
  248:          *  do something.  I guess we'll emit the equivalenced-to option
  249:          *  at the point in time when the base option is found.
  250:          */
  251:         if (pOD->optEquivIndex != NO_EQUIVALENT)
  252:             continue; /* equivalence to a different option */
  253: 
  254:         /*
  255:          *  Equivalenced to a different option.  Process the current option
  256:          *  as the equivalenced-to option.  Keep the persistent state bits,
  257:          *  but copy over the set-state bits.
  258:          */
  259:         if (pOD->optActualIndex != optIx) {
  260:             tOptDesc* p   = pOpts->pOptDesc + pOD->optActualIndex;
  261:             p->optArg     = pOD->optArg;
  262:             p->fOptState &= OPTST_PERSISTENT_MASK;
  263:             p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK;
  264:             printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME);
  265:             pOD = p;
  266:         }
  267: 
  268:         /*
  269:          *  If the argument type is a set membership bitmask, then we always
  270:          *  emit the thing.  We do this because it will always have some sort
  271:          *  of bitmask value and we need to emit the bit values.
  272:          */
  273:         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
  274:             print_membership(pOpts, pOD);
  275:             continue;
  276:         }
  277: 
  278:         /*
  279:          *  IF the option was either specified or it wakes up enabled,
  280:          *  then we will emit information.  Otherwise, skip it.
  281:          *  The idea is that if someone defines an option to initialize
  282:          *  enabled, we should tell our shell script that it is enabled.
  283:          */
  284:         if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) {
  285:             continue;
  286:         }
  287: 
  288:         /*
  289:          *  Handle stacked arguments
  290:          */
  291:         if (  (pOD->fOptState & OPTST_STACKED)
  292:            && (pOD->optCookie != NULL) )  {
  293:             print_stacked_arg(pOpts, pOD);
  294:             continue;
  295:         }
  296: 
  297:         /*
  298:          *  If the argument has been disabled,
  299:          *  Then set its value to the disablement string
  300:          */
  301:         if ((pOD->fOptState & OPTST_DISABLED) != 0) {
  302:             printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
  303:                    (pOD->pz_DisablePfx != NULL)
  304:                    ? pOD->pz_DisablePfx : "false");
  305:             continue;
  306:         }
  307: 
  308:         /*
  309:          *  If the argument type is numeric, the last arg pointer
  310:          *  is really the VALUE of the string that was pointed to.
  311:          */
  312:         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) {
  313:             printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
  314:                    (int)pOD->optArg.argInt);
  315:             continue;
  316:         }
  317: 
  318:         /*
  319:          *  If the argument type is an enumeration, then it is much
  320:          *  like a text value, except we call the callback function
  321:          *  to emit the value corresponding to the "optArg" number.
  322:          */
  323:         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
  324:             print_enumeration(pOpts, pOD);
  325:             continue;
  326:         }
  327: 
  328:         /*
  329:          *  If the argument type is numeric, the last arg pointer
  330:          *  is really the VALUE of the string that was pointed to.
  331:          */
  332:         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) {
  333:             printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
  334:                    (pOD->optArg.argBool == 0) ? "false" : "true");
  335:             continue;
  336:         }
  337: 
  338:         /*
  339:          *  IF the option has an empty value,
  340:          *  THEN we set the argument to the occurrence count.
  341:          */
  342:         if (  (pOD->optArg.argString == NULL)
  343:            || (pOD->optArg.argString[0] == NUL) ) {
  344: 
  345:             printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
  346:                    pOD->optOccCt);
  347:             continue;
  348:         }
  349: 
  350:         /*
  351:          *  This option has a text value
  352:          */
  353:         printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME);
  354:         print_quot_str(pOD->optArg.argString);
  355:         printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME);
  356: 
  357:     } while (++optIx < pOpts->presetOptCt );
  358: 
  359:     if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
  360:        && (pOpts->curOptIdx < pOpts->origArgCt))
  361:         print_reordering(pOpts);
  362: 
  363:     fflush(stdout);
  364: }
  365: 
  366: /*
  367:  * Local Variables:
  368:  * mode: C
  369:  * c-file-style: "stroustrup"
  370:  * indent-tabs-mode: nil
  371:  * End:
  372:  * end of autoopts/putshell.c */

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