From 07a3b9192001369c7bf74cd4f096dc49703b24e9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 21 Oct 2018 21:36:51 -0500 Subject: Add % to lib/args.c (long time in milliseconds), add xmillitime(), redo xparsetime() not to need floating point, adjust callers. --- lib/args.c | 21 +++++++++++---------- lib/lib.h | 1 + lib/xwrap.c | 47 ++++++++++++++++++++++++++++------------------- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/args.c b/lib/args.c index 5267ebe2..1927a930 100644 --- a/lib/args.c +++ b/lib/args.c @@ -53,17 +53,18 @@ // // Suffixes specify that this option takes an argument (stored in GLOBALS): // Note that pointer and long are always the same size, even on 64 bit. -// : plus a string argument, keep most recent if more than one -// * plus a string argument, appended to a list -// # plus a signed long argument +// : string argument, keep most recent if more than one +// * string argument, appended to a struct arg_list linked list. +// # signed long argument // HIGH - die if greater than HIGH // =DEFAULT - value if not specified -// - plus a signed long argument defaulting to negative (say + for positive) -// . plus a double precision floating point argument (with CFG_TOYBOX_FLOAT) +// - signed long argument defaulting to negative (say + for positive) +// . double precision floating point argument (with CFG_TOYBOX_FLOAT) // Chop this option out with USE_TOYBOX_FLOAT() in option string // Same HIGH=DEFAULT as # -// @ plus an occurrence counter (which is a long) +// @ occurrence counter (which is a long) +// % time offset in milliseconds with optional s/m/h/d suffix // (longopt) // | this is required. If more than one marked, only one required. // ; long option's argument is optional (can only be supplied with --opt=) @@ -215,7 +216,7 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt) help_exit("-%c < %lf", opt->c, (double)opt->val[0].f); if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f) help_exit("-%c > %lf", opt->c, (double)opt->val[1].f); - } + } else if (type=='%') *(opt->arg) = xparsemillitime(arg); if (!gof->nodash_now) gof->arg = ""; } @@ -291,20 +292,20 @@ void parse_optflaglist(struct getoptflagstate *gof) // If this is the start of a new option that wasn't a longopt, - } else if (strchr(":*#@.-", *options)) { + } else if (strchr(":*#@.-%", *options)) { if (CFG_TOYBOX_DEBUG && new->type) error_exit("multiple types %c:%c%c", new->c, new->type, *options); new->type = *options; } else if (-1 != (idx = stridx("|^ ;", *options))) new->flags |= 1<=", *options))) { - if (new->type == '#') { + if (new->type == '#' || new->type == '%') { long l = strtol(++options, &temp, 10); if (temp != options) new->val[idx].l = l; } else if (CFG_TOYBOX_FLOAT && new->type == '.') { FLOAT f = strtod(++options, &temp); if (temp != options) new->val[idx].f = f; - } else error_exit("<>= only after .#"); + } else error_exit("<>= only after .#%%"); options = --temp; // At this point, we've hit the end of the previous option. The diff --git a/lib/lib.h b/lib/lib.h index 98c042c7..e630bbc9 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -172,6 +172,7 @@ void xsetuser(struct passwd *pwd); char *xreadlink(char *name); double xstrtod(char *s); long xparsetime(char *arg, long units, long *fraction); +long long xparsemillitime(char *arg); void xpidfile(char *name); void xregcomp(regex_t *preg, char *rexec, int cflags); char *xtzset(char *new); diff --git a/lib/xwrap.c b/lib/xwrap.c index 2c3b6041..fba262b9 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -789,36 +789,45 @@ double xstrtod(char *s) } // parse fractional seconds with optional s/m/h/d suffix -long xparsetime(char *arg, long units, long *fraction) +long xparsetime(char *arg, long zeroes, long *fraction) { - double d; - long l; + long l, fr; char *end; - if (*arg != '.' && !isdigit(*arg)) error_exit("bad %s", arg); - if (CFG_TOYBOX_FLOAT) d = strtod(arg, &end); - else l = strtoul(arg, &end, 10); - - if (end == arg) error_exit("Not a number '%s'", arg); - arg = end; + if (*arg != '.' && !isdigit(*arg)) error_exit("Not a number '%s'", arg); + l = strtoul(arg, &end, 10); + fr = 0; + if (*end == '.') { + end++; + while (zeroes--) { + fr *= 10; + if (isdigit(*end)) fr += *end++-'0'; + } + } + if (fraction) *fraction = fr; // Parse suffix - if (*arg) { - int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); + if (*end) { + int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *end); - if (i == -1 || *(arg+1)) error_exit("Unknown suffix '%s'", arg); - if (CFG_TOYBOX_FLOAT) d *= ismhd[i]; - else l *= ismhd[i]; + if (i == -1 || *(end+1)) error_exit("Unknown suffix '%s'", end); + l *= ismhd[i]; } - if (CFG_TOYBOX_FLOAT) { - l = (long)d; - if (fraction) *fraction = units*(d-l); - } else if (fraction) *fraction = 0; - return l; } +long long xparsemillitime(char *arg) +{ + long l, ll; + + l = xparsetime(arg, 3, &ll); + + return (l*1000LL)+ll; +} + + + // Compile a regular expression into a regex_t void xregcomp(regex_t *preg, char *regex, int cflags) { -- cgit v1.2.3