/*=export_func optionStackArg * private: * * what: put option args on a stack * arg: + tOptions* + opts + program options descriptor + * arg: + tOptDesc* + od + the descriptor for this arg + * * doc: * Keep an entry-ordered list of option arguments. =*/ void optionStackArg(tOptions * opts, tOptDesc * od) { char * pz; if (INQUERY_CALL(opts, od)) return; if ((od->fOptState & OPTST_RESET) != 0) { tArgList * arg_list = (void*)od->optCookie; int ix; if (arg_list == NULL) return; ix = arg_list->useCt; while (--ix >= 0) AGFREE(arg_list->apzArgs[ix]); AGFREE(arg_list); } else { if (od->optArg.argString == NULL) return; AGDUPSTR(pz, od->optArg.argString, "stack arg"); addArgListEntry(&(od->optCookie), (void*)pz); } }
/*=export_func optionBooleanVal * private: * * what: Decipher a boolean value * arg: + tOptions * + opts + program options descriptor + * arg: + tOptDesc * + od + the descriptor for this arg + * * doc: * Decipher a true or false value for a boolean valued option argument. * The value is true, unless it starts with 'n' or 'f' or "#f" or * it is an empty string or it is a number that evaluates to zero. =*/ void optionBooleanVal(tOptions * opts, tOptDesc * od) { char * pz; bool res = true; if (INQUERY_CALL(opts, od)) return; if (od->optArg.argString == NULL) { od->optArg.argBool = false; return; } switch (*(od->optArg.argString)) { case '0': { long val = strtol(od->optArg.argString, &pz, 0); if ((val != 0) || (*pz != NUL)) break; /* FALLTHROUGH */ } case 'N': case 'n': case 'F': case 'f': case NUL: res = false; break; case '#': if (od->optArg.argString[1] != 'f') break; res = false; } if (od->fOptState & OPTST_ALLOC_ARG) { AGFREE(od->optArg.argString); od->fOptState &= ~OPTST_ALLOC_ARG; } od->optArg.argBool = res; }
/*=export_func optionTimeVal * private: * * what: process an option with a time duration. * arg: + tOptions * + opts + program options descriptor + * arg: + tOptDesc * + od + the descriptor for this arg + * * doc: * Decipher a time duration value. =*/ void optionTimeVal(tOptions * opts, tOptDesc * od) { time_t val; if (INQUERY_CALL(opts, od)) return; val = parse_duration(od->optArg.argString); if (val == BAD_TIME) { fprintf(stderr, zNotDuration, opts->pzProgName, od->optArg.argString); if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) (*(opts->pUsageProc))(opts, EXIT_FAILURE); } if (od->fOptState & OPTST_ALLOC_ARG) { AGFREE(od->optArg.argString); od->fOptState &= ~OPTST_ALLOC_ARG; } od->optArg.argInt = (long)val; }
/*=export_func optionUnstackArg * private: * * what: Remove option args from a stack * arg: + tOptions* + opts + program options descriptor + * arg: + tOptDesc* + od + the descriptor for this arg + * * doc: * Invoked for options that are equivalenced to stacked options. =*/ void optionUnstackArg(tOptions * opts, tOptDesc * od) { tArgList * arg_list; if (INQUERY_CALL(opts, od)) return; arg_list = (tArgList*)od->optCookie; /* * IF we don't have any stacked options, * THEN indicate that we don't have any of these options */ if (arg_list == NULL) { od->fOptState &= OPTST_PERSISTENT_MASK; if ((od->fOptState & OPTST_INITENABLED) == 0) od->fOptState |= OPTST_DISABLED; return; } #ifdef WITH_LIBREGEX { regex_t re; int i, ct, dIdx; if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0) return; /* * search the list for the entry(s) to remove. Entries that * are removed are *not* copied into the result. The source * index is incremented every time. The destination only when * we are keeping a define. */ for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { char const * pzSrc = arg_list->apzArgs[ i ]; char * pzEq = strchr(pzSrc, '='); int res; if (pzEq != NULL) *pzEq = NUL; res = regexec(&re, pzSrc, (size_t)0, NULL, 0); switch (res) { case 0: /* * Remove this entry by reducing the in-use count * and *not* putting the string pointer back into * the list. */ AGFREE(pzSrc); arg_list->useCt--; break; default: case REG_NOMATCH: if (pzEq != NULL) *pzEq = '='; /* * IF we have dropped an entry * THEN we have to move the current one. */ if (dIdx != i) arg_list->apzArgs[ dIdx ] = pzSrc; dIdx++; } } regfree(&re); } #else /* not WITH_LIBREGEX */ { int i, ct, dIdx; /* * search the list for the entry(s) to remove. Entries that * are removed are *not* copied into the result. The source * index is incremented every time. The destination only when * we are keeping a define. */ for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { const char * pzSrc = arg_list->apzArgs[ i ]; char * pzEq = strchr(pzSrc, '='); if (pzEq != NULL) *pzEq = NUL; if (strcmp(pzSrc, od->optArg.argString) == 0) { /* * Remove this entry by reducing the in-use count * and *not* putting the string pointer back into * the list. */ AGFREE(pzSrc); arg_list->useCt--; } else { if (pzEq != NULL) *pzEq = '='; /* * IF we have dropped an entry * THEN we have to move the current one. */ if (dIdx != i) arg_list->apzArgs[ dIdx ] = pzSrc; dIdx++; } } } #endif /* WITH_LIBREGEX */ /* * IF we have unstacked everything, * THEN indicate that we don't have any of these options */ if (arg_list->useCt == 0) { od->fOptState &= OPTST_PERSISTENT_MASK; if ((od->fOptState & OPTST_INITENABLED) == 0) od->fOptState |= OPTST_DISABLED; AGFREE((void *)arg_list); od->optCookie = NULL; } }
/*=export_func optionNumericVal * private: * * what: process an option with a numeric value. * arg: + tOptions * + opts + program options descriptor + * arg: + tOptDesc * + od + the descriptor for this arg + * * doc: * Decipher a numeric value. =*/ void optionNumericVal(tOptions * opts, tOptDesc * od) { char * pz; long val; /* * Guard against all the different ways this procedure might get invoked * when there is no string argument provided. */ if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL)) return; /* * Numeric options may have a range associated with it. * If it does, the usage procedure requests that it be * emitted by passing a NULL od pointer. Also bail out * if there is no option argument or if we are being reset. */ if ( (od == NULL) || (od->optArg.argString == NULL) || ((od->fOptState & OPTST_RESET) != 0) || (opts <= OPTPROC_EMIT_LIMIT)) return; errno = 0; val = strtol(od->optArg.argString, &pz, 0); if ((pz == od->optArg.argString) || (errno != 0)) goto bad_number; if ((od->fOptState & OPTST_SCALED_NUM) != 0) switch (*(pz++)) { case NUL: pz--; break; case 't': val *= 1000; case 'g': val *= 1000; case 'm': val *= 1000; case 'k': val *= 1000; break; case 'T': val *= 1024; case 'G': val *= 1024; case 'M': val *= 1024; case 'K': val *= 1024; break; default: goto bad_number; } if (*pz != NUL) goto bad_number; if (od->fOptState & OPTST_ALLOC_ARG) { AGFREE(od->optArg.argString); od->fOptState &= ~OPTST_ALLOC_ARG; } od->optArg.argInt = val; return; bad_number: fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString ); if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) (*(opts->pUsageProc))(opts, EXIT_FAILURE); errno = EINVAL; od->optArg.argInt = ~0; }
/*=export_func optionTimeDate * private: * * what: process an option with a time and date. * arg: + tOptions * + opts + program options descriptor + * arg: + tOptDesc * + od + the descriptor for this arg + * * doc: * Decipher a time and date value. =*/ void optionTimeDate(tOptions * opts, tOptDesc * od) { #if defined(HAVE_GETDATE_R) && defined(HAVE_PUTENV) if (INQUERY_CALL(opts, od)) return; if ((! HAS_pzPkgDataDir(opts)) || (opts->pzPkgDataDir == NULL)) goto default_action; /* * Export the DATEMSK environment variable. getdate_r() uses it to * find the file with the strptime formats. If we cannot find the file * we need ($PKGDATADIR/datemsk), then fall back to just a time duration. */ { static char * envptr = NULL; if (envptr == NULL) { static char const fmt[] = "DATEMSK=%s/datemsk"; size_t sz = sizeof(fmt) + strlen(opts->pzPkgDataDir); envptr = AGALOC(sz, fmt); if (snprintf(envptr, sz, fmt, opts->pzPkgDataDir) >= (int)sz) option_exits(EXIT_FAILURE); putenv(envptr); } if (access(envptr+8, R_OK) != 0) goto default_action; } /* * Convert the date to a time since the epoch and stash it in a long int. */ { struct tm stm; time_t tm; if (getdate_r(od->optArg.argString, &stm) != 0) { fprintf(stderr, zNotDate, opts->pzProgName, od->optArg.argString); if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) (*(opts->pUsageProc))(opts, EXIT_FAILURE); return; } tm = mktime(&stm); if (od->fOptState & OPTST_ALLOC_ARG) { AGFREE(od->optArg.argString); od->fOptState &= ~OPTST_ALLOC_ARG; } od->optArg.argInt = tm; } return; default_action: #endif optionTimeVal(opts, od); if (od->optArg.argInt != BAD_TIME) od->optArg.argInt += (long)time(NULL); }