/* * shortOptionFind * * Find the short option descriptor for the current option */ LOCAL tSuccess shortOptionFind(tOptions* pOpts, uint_t optValue, tOptState* pOptState) { tOptDesc* pRes = pOpts->pOptDesc; int ct = pOpts->optCt; /* * Search the option list */ do { if (optValue != pRes->optValue) continue; if (SKIP_OPT(pRes)) { if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) && (pRes->pz_Name != NULL)) { fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name); if (pRes->pzText != NULL) fprintf(stderr, " -- %s", pRes->pzText); fputc('\n', stderr); (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); /* NOTREACHED */ } goto short_opt_error; } pOptState->pOD = pRes; pOptState->optType = TOPT_SHORT; return SUCCESS; } while (pRes++, --ct > 0); /* * IF the character value is a digit * AND there is a special number option ("-n") * THEN the result is the "option" itself and the * option is the specially marked "number" option. */ if ( IS_DEC_DIGIT_CHAR(optValue) && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) { pOptState->pOD = \ pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option; (pOpts->pzCurOpt)--; pOptState->optType = TOPT_SHORT; return SUCCESS; } short_opt_error: /* * IF we are to stop on errors (the default, actually) * THEN call the usage procedure. */ if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue); (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); } return FAILURE; }
/** * Emit GNU-standard long option handling code. * * @param[in] opts the program options */ static void emit_long(tOptions * opts) { tOptDesc * od = opts->pOptDesc; int ct = opts->optCt; fputs(zOptionCase, stdout); /* * do each option, ... */ do { /* * Documentation & compiled-out options */ if (SKIP_OPT(od)) continue; emit_match_expr(od->pz_Name, od, opts); emit_action(opts, od); /* * Now, do the same thing for the disablement version of the option. */ if (od->pz_DisableName != NULL) { emit_match_expr(od->pz_DisableName, od, opts); emit_inaction(opts, od); } } while (od++, --ct > 0); printf(UNK_OPT_FMT, OPTION_STR, opts->pzPROGNAME); }
static void emit_wrapup(tOptions * opts) { tOptDesc * od = opts->pOptDesc; int opt_ct = opts->presetOptCt; char const * fmt; printf(FINISH_LOOP, opts->pzPROGNAME); for (;opt_ct > 0; od++, --opt_ct) { /* * Options that are either usage documentation or are compiled out * are not to be processed. */ if (SKIP_OPT(od) || (od->pz_NAME == NULL)) continue; /* * do not presence check if there is no minimum/must-set */ if ((od->optMinCt == 0) && ((od->fOptState & OPTST_MUST_SET) == 0)) continue; if (od->optMaxCt > 1) fmt = CHK_MIN_COUNT; else fmt = CHK_ONE_REQUIRED; { int min = (od->optMinCt == 0) ? 1 : od->optMinCt; printf(fmt, opts->pzPROGNAME, od->pz_NAME, min); } } fputs(END_MARK, stdout); }
/* * Emit GNU-standard long option handling code */ static void emitLong( tOptions* pOpts ) { tOptDesc* pOD = pOpts->pOptDesc; int ct = pOpts->optCt; fputs( zOptionCase, stdout ); /* * do each option, ... */ do { /* * Documentation & compiled-out options */ if (SKIP_OPT(pOD)) continue; emitMatchExpr( pOD->pz_Name, pOD, pOpts ); printOptionAction( pOpts, pOD ); /* * Now, do the same thing for the disablement version of the option. */ if (pOD->pz_DisableName != NULL) { emitMatchExpr( pOD->pz_DisableName, pOD, pOpts ); printOptionInaction( pOpts, pOD ); } } while (pOD++, --ct > 0); printf( zOptionUnknown, "option", pOpts->pzPROGNAME ); }
/** * Set the option to the indicated option number. * * @param opts option data * @param arg option argument (if glued to name) * @param idx option index * @param disable mark disabled option * @param st state about current option */ static tSuccess opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st) { tOptDesc * pOD = opts->pOptDesc + idx; if (SKIP_OPT(pOD)) { if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) return FAILURE; fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name); if (pOD->pzText != NULL) fprintf(stderr, SET_OFF_FMT, pOD->pzText); fputc(NL, stderr); (*opts->pUsageProc)(opts, EXIT_FAILURE); /* NOTREACHED */ _exit(EXIT_FAILURE); /* to be certain */ } /* * IF we found a disablement name, * THEN set the bit in the callers' flag word */ if (disable) st->flags |= OPTST_DISABLED; st->pOD = pOD; st->pzOptArg = arg; st->optType = TOPT_LONG; return SUCCESS; }
/** * recognize flag options. These go at the end. * At the end, emit code to handle options we don't recognize. * * @param[in] opts the program options */ static void emit_flag(tOptions * opts) { tOptDesc * od = opts->pOptDesc; int opt_ct = opts->optCt; fputs(zOptionCase, stdout); for (;opt_ct > 0; od++, --opt_ct) { if (SKIP_OPT(od) || ! IS_GRAPHIC_CHAR(od->optValue)) continue; printf(zOptionFlag, od->optValue); emit_action(opts, od); } printf(UNK_OPT_FMT, FLAG_STR, opts->pzPROGNAME); }
static void emitFlag( tOptions* pOpts ) { tOptDesc* pOptDesc = pOpts->pOptDesc; int optionCt = pOpts->optCt; fputs( zOptionCase, stdout ); for (;optionCt > 0; pOptDesc++, --optionCt) { if (SKIP_OPT(pOptDesc)) continue; if (IS_GRAPHIC_CHAR(pOptDesc->optValue)) { printf( zOptionFlag, pOptDesc->optValue ); printOptionAction( pOpts, pOptDesc ); } } printf( zOptionUnknown, "flag", pOpts->pzPROGNAME ); }
static void emit_flag(tOptions * pOpts) { tOptDesc* pOptDesc = pOpts->pOptDesc; int optionCt = pOpts->optCt; fputs(zOptionCase, stdout); for (;optionCt > 0; pOptDesc++, --optionCt) { if (SKIP_OPT(pOptDesc)) continue; if (IS_GRAPHIC_CHAR(pOptDesc->optValue)) { printf(zOptionFlag, pOptDesc->optValue); emit_action(pOpts, pOptDesc); } } printf(UNK_OPT_FMT, FLAG_STR, pOpts->pzPROGNAME); }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * HUNT FOR OPTIONS IN THE ARGUMENT LIST * * The next four procedures are "private" to nextOption(). * nextOption() uses findOptDesc() to find the next descriptor and it, in * turn, uses longOptionFind() and shortOptionFind() to actually do the hunt. * * longOptionFind * * Find the long option descriptor for the current option */ LOCAL tSuccess longOptionFind(tOptions* pOpts, char* pzOptName, tOptState* pOptState) { ag_bool disable = AG_FALSE; char* pzEq = strchr(pzOptName, '='); tOptDesc* pOD = pOpts->pOptDesc; int idx = 0; int idxLim = pOpts->optCt; int matchCt = 0; int matchIdx = 0; int nameLen; char opt_name_buf[128]; /* * IF the value is attached to the name, * copy it off so we can NUL terminate. */ if (pzEq != NULL) { nameLen = (int)(pzEq - pzOptName); if (nameLen >= sizeof(opt_name_buf)) return FAILURE; memcpy(opt_name_buf, pzOptName, nameLen); opt_name_buf[nameLen] = NUL; pzOptName = opt_name_buf; pzEq++; } else nameLen = strlen(pzOptName); do { /* * If option disabled or a doc option, skip to next */ if (pOD->pz_Name == NULL) continue; if ( SKIP_OPT(pOD) && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) continue; if (strneqvcmp(pzOptName, pOD->pz_Name, nameLen) == 0) { /* * IF we have a complete match * THEN it takes priority over any already located partial */ if (pOD->pz_Name[ nameLen ] == NUL) { matchCt = 1; matchIdx = idx; break; } } /* * IF there is a disable name * *AND* no argument value has been supplied * (disabled options may have no argument) * *AND* the option name matches the disable name * THEN ... */ else if ( (pOD->pz_DisableName != NULL) && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0) ) { disable = AG_TRUE; /* * IF we have a complete match * THEN it takes priority over any already located partial */ if (pOD->pz_DisableName[ nameLen ] == NUL) { matchCt = 1; matchIdx = idx; break; } } else continue; /* * We found a partial match, either regular or disabling. * Remember the index for later. */ matchIdx = idx; if (++matchCt > 1) break; } while (pOD++, (++idx < idxLim)); /* * Make sure we either found an exact match or found only one partial */ if (matchCt == 1) { pOD = pOpts->pOptDesc + matchIdx; if (SKIP_OPT(pOD)) { fprintf(stderr, zDisabledErr, pOpts->pzProgName, pOD->pz_Name); if (pOD->pzText != NULL) fprintf(stderr, " -- %s", pOD->pzText); fputc('\n', stderr); (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); /* NOTREACHED */ } /* * IF we found a disablement name, * THEN set the bit in the callers' flag word */ if (disable) pOptState->flags |= OPTST_DISABLED; pOptState->pOD = pOD; pOptState->pzOptArg = pzEq; pOptState->optType = TOPT_LONG; return SUCCESS; } /* * IF there is no equal sign * *AND* we are using named arguments * *AND* there is a default named option, * THEN return that option. */ if ( (pzEq == NULL) && NAMED_OPTS(pOpts) && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) { pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt; pOptState->pzOptArg = pzOptName; pOptState->optType = TOPT_DEFAULT; return SUCCESS; } /* * IF we are to stop on errors (the default, actually) * THEN call the usage procedure. */ if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { fprintf(stderr, (matchCt == 0) ? zIllOptStr : zAmbigOptStr, pOpts->pzProgPath, pzOptName); (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); } return FAILURE; }
/** * Emit the match text for a long option. The passed in \a name may be * either the enablement name or the disablement name. * * @param[in] name The current name to check. * @param[in] cod current option descriptor * @param[in] opts the program options */ static void emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts) { char name_bf[32]; unsigned int min_match_ct = 2; unsigned int max_match_ct = strlen(name) - 1; if (max_match_ct >= sizeof(name_bf) - 1) goto leave; { tOptDesc * od = opts->pOptDesc; int ct = opts->optCt; for (; ct-- > 0; od++) { unsigned int match_ct = 0; /* * Omit the current option, Doc opts and compiled out opts. */ if ((od == cod) || SKIP_OPT(od)) continue; /* * Check each character of the name case insensitively. * They must not be the same. They cannot be, because it would * not compile correctly if they were. */ while (UPPER(od->pz_Name[match_ct]) == UPPER(name[match_ct])) match_ct++; if (match_ct > min_match_ct) min_match_ct = match_ct; /* * Check the disablement name, too. */ if (od->pz_DisableName == NULL) continue; match_ct = 0; while ( toupper((unsigned char)od->pz_DisableName[match_ct]) == toupper((unsigned char)name[match_ct])) match_ct++; if (match_ct > min_match_ct) min_match_ct = match_ct; } } /* * Don't bother emitting partial matches if there is only one possible * partial match. */ if (min_match_ct < max_match_ct) { char * pz = name_bf + min_match_ct; int nm_ix = min_match_ct; memcpy(name_bf, name, min_match_ct); for (;;) { *pz = NUL; printf(zOptionPartName, name_bf); *pz++ = name[nm_ix++]; if (name[nm_ix] == NUL) { *pz = NUL; break; } } } leave: printf(zOptionFullName, name); }
static void emit_setup(tOptions * opts) { tOptDesc * od = opts->pOptDesc; int opt_ct = opts->presetOptCt; char const * fmt; char const * def_val; for (;opt_ct > 0; od++, --opt_ct) { char int_val_buf[32]; /* * Options that are either usage documentation or are compiled out * are not to be processed. */ if (SKIP_OPT(od) || (od->pz_NAME == NULL)) continue; if (od->optMaxCt > 1) fmt = MULTI_DEF_FMT; else fmt = SGL_DEF_FMT; /* * IF this is an enumeration/bitmask option, then convert the value * to a string before printing the default value. */ switch (OPTST_GET_ARGTYPE(od->fOptState)) { case OPARG_TYPE_ENUMERATION: (*(od->pOptProc))(OPTPROC_EMIT_SHELL, od ); def_val = od->optArg.argString; break; /* * Numeric and membership bit options are just printed as a number. */ case OPARG_TYPE_NUMERIC: snprintf(int_val_buf, sizeof(int_val_buf), "%d", (int)od->optArg.argInt); def_val = int_val_buf; break; case OPARG_TYPE_MEMBERSHIP: snprintf(int_val_buf, sizeof(int_val_buf), "%lu", (unsigned long)od->optArg.argIntptr); def_val = int_val_buf; break; case OPARG_TYPE_BOOLEAN: def_val = (od->optArg.argBool) ? TRUE_STR : FALSE_STR; break; default: if (od->optArg.argString == NULL) { if (fmt == SGL_DEF_FMT) fmt = SGL_NO_DEF_FMT; def_val = NULL; } else def_val = od->optArg.argString; } printf(fmt, opts->pzPROGNAME, od->pz_NAME, def_val); } }
/*=export_func optionPutShell * what: write a portable shell script to parse options * private: * arg: tOptions*, pOpts, the program options descriptor * doc: This routine will emit portable shell script text for parsing * the options described in the option definitions. =*/ void optionPutShell(tOptions* pOpts) { int optIx = 0; tSCC zOptCtFmt[] = "OPTION_CT=%d\nexport OPTION_CT\n"; tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n"; tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n"; tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n"; printf(zOptCtFmt, pOpts->curOptIdx-1); do { tOptDesc* pOD = pOpts->pOptDesc + optIx; if (SKIP_OPT(pOD)) continue; /* * Equivalence classes are hard to deal with. Where the * option data wind up kind of squishes around. For the purposes * of emitting shell state, they are not recommended, but we'll * do something. I guess we'll emit the equivalenced-to option * at the point in time when the base option is found. */ if (pOD->optEquivIndex != NO_EQUIVALENT) continue; /* equivalence to a different option */ /* * Equivalenced to a different option. Process the current option * as the equivalenced-to option. Keep the persistent state bits, * but copy over the set-state bits. */ if (pOD->optActualIndex != optIx) { tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex; p->optArg = pOD->optArg; p->fOptState &= OPTST_PERSISTENT_MASK; p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK; printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME); pOD = p; } /* * If the argument type is a set membership bitmask, then we always * emit the thing. We do this because it will always have some sort * of bitmask value and we need to emit the bit values. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { print_membership(pOpts, pOD); continue; } /* * IF the option was either specified or it wakes up enabled, * then we will emit information. Otherwise, skip it. * The idea is that if someone defines an option to initialize * enabled, we should tell our shell script that it is enabled. */ if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) { continue; } /* * Handle stacked arguments */ if ( (pOD->fOptState & OPTST_STACKED) && (pOD->optCookie != NULL) ) { print_stacked_arg(pOpts, pOD); continue; } /* * If the argument has been disabled, * Then set its value to the disablement string */ if ((pOD->fOptState & OPTST_DISABLED) != 0) { printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME, (pOD->pz_DisablePfx != NULL) ? pOD->pz_DisablePfx : "false"); continue; } /* * If the argument type is numeric, the last arg pointer * is really the VALUE of the string that was pointed to. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) { printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, (int)pOD->optArg.argInt); continue; } /* * If the argument type is an enumeration, then it is much * like a text value, except we call the callback function * to emit the value corresponding to the "optArg" number. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) { print_enumeration(pOpts, pOD); continue; } /* * If the argument type is numeric, the last arg pointer * is really the VALUE of the string that was pointed to. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) { printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME, (pOD->optArg.argBool == 0) ? "false" : "true"); continue; } /* * IF the option has an empty value, * THEN we set the argument to the occurrence count. */ if ( (pOD->optArg.argString == NULL) || (pOD->optArg.argString[0] == NUL) ) { printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, pOD->optOccCt); continue; } /* * This option has a text value */ printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME); print_quot_str(pOD->optArg.argString); printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME); } while (++optIx < pOpts->presetOptCt ); if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0) && (pOpts->curOptIdx < pOpts->origArgCt)) print_reordering(pOpts); fflush(stdout); }
/* * Emit the match text for a long option */ static void emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts ) { tOptDesc* pOD = pOpts->pOptDesc; int oCt = pOpts->optCt; int min = 1; char zName[ 256 ]; char* pz = zName; for (;;) { int matchCt = 0; /* * Omit the current option, Documentation opts and compiled out opts. */ if ((pOD == pCurOpt) || SKIP_OPT(pOD)){ if (--oCt <= 0) break; pOD++; continue; } /* * Check each character of the name case insensitively. * They must not be the same. They cannot be, because it would * not compile correctly if they were. */ while ( toupper( pOD->pz_Name[matchCt] ) == toupper( pzMatchName[matchCt] )) matchCt++; if (matchCt > min) min = matchCt; /* * Check the disablement name, too. */ if (pOD->pz_DisableName != NULL) { matchCt = 0; while ( toupper( pOD->pz_DisableName[matchCt] ) == toupper( pzMatchName[matchCt] )) matchCt++; if (matchCt > min) min = matchCt; } if (--oCt <= 0) break; pOD++; } /* * IF the 'min' is all or one short of the name length, * THEN the entire string must be matched. */ if ( (pzMatchName[min ] == NUL) || (pzMatchName[min+1] == NUL) ) printf( zOptionFullName, pzMatchName ); else { int matchCt = 0; for (; matchCt <= min; matchCt++) *pz++ = pzMatchName[matchCt]; for (;;) { *pz = NUL; printf( zOptionPartName, zName ); *pz++ = pzMatchName[matchCt++]; if (pzMatchName[matchCt] == NUL) { *pz = NUL; printf( zOptionFullName, zName ); break; } } } }
static void emitSetup( tOptions* pOpts ) { tOptDesc* pOptDesc = pOpts->pOptDesc; int optionCt = pOpts->presetOptCt; char const* pzFmt; char const* pzDefault; for (;optionCt > 0; pOptDesc++, --optionCt) { char zVal[16]; /* * Options that are either usage documentation or are compiled out * are not to be processed. */ if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL)) continue; if (pOptDesc->optMaxCt > 1) pzFmt = zMultiDef; else pzFmt = zSingleDef; /* * IF this is an enumeration/bitmask option, then convert the value * to a string before printing the default value. */ switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) { case OPARG_TYPE_ENUMERATION: (*(pOptDesc->pOptProc))(OPTPROC_EMIT_SHELL, pOptDesc ); pzDefault = pOptDesc->optArg.argString; break; /* * Numeric and membership bit options are just printed as a number. */ case OPARG_TYPE_NUMERIC: snprintf( zVal, sizeof( zVal ), "%d", (int)pOptDesc->optArg.argInt ); pzDefault = zVal; break; case OPARG_TYPE_MEMBERSHIP: snprintf( zVal, sizeof( zVal ), "%lu", (unsigned long)pOptDesc->optArg.argIntptr ); pzDefault = zVal; break; case OPARG_TYPE_BOOLEAN: pzDefault = (pOptDesc->optArg.argBool) ? "true" : "false"; break; default: if (pOptDesc->optArg.argString == NULL) { if (pzFmt == zSingleDef) pzFmt = zSingleNoDef; pzDefault = NULL; } else pzDefault = pOptDesc->optArg.argString; } printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault ); } }
/*=export_func optionPutShell * what: write a portable shell script to parse options * private: * arg: tOptions*, pOpts, the program options descriptor * doc: This routine will emit portable shell script text for parsing * the options described in the option definitions. =*/ void optionPutShell( tOptions* pOpts ) { int optIx = 0; tSCC zOptCtFmt[] = "OPTION_CT=%d\nexport OPTION_CT\n"; tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n"; tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n"; tSCC zOptValFmt[] = "%s_%s="; tSCC zOptEnd[] = "\nexport %s_%s\n"; tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n"; tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n"; printf( zOptCtFmt, pOpts->curOptIdx-1 ); do { tOptDesc* pOD = pOpts->pOptDesc + optIx; if (SKIP_OPT(pOD)) continue; /* * Equivalence classes are hard to deal with. Where the * option data wind up kind of squishes around. For the purposes * of emitting shell state, they are not recommended, but we'll * do something. I guess we'll emit the equivalenced-to option * at the point in time when the base option is found. */ if (pOD->optEquivIndex != NO_EQUIVALENT) continue; /* equivalence to a different option */ /* * Equivalenced to a different option. Process the current option * as the equivalenced-to option. Keep the persistent state bits, * but copy over the set-state bits. */ if (pOD->optActualIndex != optIx) { tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex; p->optArg = pOD->optArg; p->fOptState &= OPTST_PERSISTENT_MASK; p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK; printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME ); pOD = p; } /* * If the argument type is a set membership bitmask, then we always * emit the thing. We do this because it will always have some sort * of bitmask value and we need to emit the bit values. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { char const * pz; uintptr_t val = 1; printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, (int)(uintptr_t)(pOD->optCookie) ); pOD->optCookie = (void*)(uintptr_t)~0UL; (*(pOD->pOptProc))( (tOptions*)2UL, pOD ); /* * We are building the typeset list. The list returned starts with * 'none + ' for use by option saving stuff. We must ignore that. */ pz = pOD->optArg.argString + 7; while (*pz != NUL) { printf( "typeset -x -i %s_", pOD->pz_NAME ); pz += strspn( pz, " +\t\n\f" ); for (;;) { int ch = *(pz++); if (islower( ch )) fputc( toupper( ch ), stdout ); else if (isalnum( ch )) fputc( ch, stdout ); else if (isspace( ch ) || (ch == '+')) goto name_done; else if (ch == NUL) { pz--; goto name_done; } else fputc( '_', stdout ); } name_done:; printf( "=%1$lu # 0x%1$lX\n", (unsigned long)val ); val <<= 1; } AGFREE(pOD->optArg.argString); pOD->optArg.argString = NULL; pOD->fOptState &= ~OPTST_ALLOC_ARG; continue; } /* * IF the option was either specified or it wakes up enabled, * then we will emit information. Otherwise, skip it. * The idea is that if someone defines an option to initialize * enabled, we should tell our shell script that it is enabled. */ if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD )) continue; /* * Handle stacked arguments */ if ( (pOD->fOptState & OPTST_STACKED) && (pOD->optCookie != NULL) ) { tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n"; tArgList* pAL = (tArgList*)pOD->optCookie; tCC** ppz = pAL->apzArgs; int ct = pAL->useCt; printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct ); while (--ct >= 0) { tSCC numarg_z[] = "%s_%s_%d="; tSCC end_z[] = "\nexport %s_%s_%d\n"; printf( numarg_z, pOpts->pzPROGNAME, pOD->pz_NAME, pAL->useCt - ct ); putQuotedStr( *(ppz++) ); printf( end_z, pOpts->pzPROGNAME, pOD->pz_NAME, pAL->useCt - ct ); } } /* * If the argument has been disabled, * Then set its value to the disablement string */ else if ((pOD->fOptState & OPTST_DISABLED) != 0) printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME, (pOD->pz_DisablePfx != NULL) ? pOD->pz_DisablePfx : "false" ); /* * If the argument type is numeric, the last arg pointer * is really the VALUE of the string that was pointed to. */ else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, (int)pOD->optArg.argInt ); /* * If the argument type is an enumeration, then it is much * like a text value, except we call the callback function * to emit the value corresponding to the "optArg" number. */ else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) { printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME ); fputc( '\'', stdout ); (*(pOD->pOptProc))( (tOptions*)1UL, pOD ); fputc( '\'', stdout ); printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME ); } /* * If the argument type is numeric, the last arg pointer * is really the VALUE of the string that was pointed to. */ else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME, (pOD->optArg.argBool == 0) ? "false" : "true" ); /* * IF the option has an empty value, * THEN we set the argument to the occurrence count. */ else if ( (pOD->optArg.argString == NULL) || (pOD->optArg.argString[0] == NUL) ) printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, pOD->optOccCt ); /* * This option has a text value */ else { printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME ); putQuotedStr( pOD->optArg.argString ); printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME ); } } while (++optIx < pOpts->presetOptCt ); if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0) && (pOpts->curOptIdx < pOpts->origArgCt)) { fputs( "set --", stdout ); for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) { char* pzArg = pOpts->origArgVect[ optIx ]; if (strchr( pzArg, '\'' ) == NULL) printf( " '%s'", pzArg ); else { fputs( " '", stdout ); for (;;) { char ch = *(pzArg++); switch (ch) { case '\'': fputs( "'\\''", stdout ); break; case NUL: goto arg_done; default: fputc( ch, stdout ); break; } } arg_done:; fputc( '\'', stdout ); } } fputs( "\nOPTION_CT=0\n", stdout ); } }
/** * Determine the number of options that match the name * * @param pOpts option data * @param opt_name name of option to look for * @param nm_len length of provided name * @param index pointer to int for option index * @param disable pointer to bool to mark disabled option * @return count of options that match */ static int opt_match_ct(tOptions * opts, char const * name, int nm_len, int * ixp, bool * disable) { int matchCt = 0; int idx = 0; int idxLim = opts->optCt; tOptDesc * pOD = opts->pOptDesc; do { /* * If option disabled or a doc option, skip to next */ if (pOD->pz_Name == NULL) continue; if ( SKIP_OPT(pOD) && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) continue; if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) { /* * IF we have a complete match * THEN it takes priority over any already located partial */ if (pOD->pz_Name[ nm_len ] == NUL) { *ixp = idx; return 1; } } /* * IF there is a disable name * *AND* the option name matches the disable name * THEN ... */ else if ( (pOD->pz_DisableName != NULL) && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) ) { *disable = true; /* * IF we have a complete match * THEN it takes priority over any already located partial */ if (pOD->pz_DisableName[ nm_len ] == NUL) { *ixp = idx; return 1; } } else continue; /* does not match any option */ /* * We found a full or partial match, either regular or disabling. * Remember the index for later. */ *ixp = idx; ++matchCt; } while (pOD++, (++idx < idxLim)); return matchCt; }