diff options
Diffstat (limited to 'Src/builtin.c')
-rw-r--r-- | Src/builtin.c | 171 |
1 files changed, 113 insertions, 58 deletions
diff --git a/Src/builtin.c b/Src/builtin.c index 3a471760a..a3e7149d9 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -71,7 +71,7 @@ static struct builtin builtins[] = */ BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "nlre:IRWAdDfEimpPa", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), - BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%Hghlprtux", "E"), + BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlprtux", "E"), BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmtuUz", NULL), BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"), BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL), @@ -82,7 +82,7 @@ static struct builtin builtins[] = #endif BUILTIN("history", 0, bin_fc, 0, -1, BIN_FC, "nrdDfEimpPa", "l"), - BUILTIN("integer", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "Hghi:%lprtux", "i"), + BUILTIN("integer", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "HL:%R:%Z:%ghi:%lprtux", "i"), BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL), BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), @@ -1719,13 +1719,73 @@ enum { NS_SECONDS }; +static const struct gsu_scalar tiedarr_gsu = +{ tiedarrgetfn, tiedarrsetfn, tiedarrunsetfn }; + +/* Install a base if we are turning on a numeric option with an argument */ + +static int +typeset_setbase(const char *name, Param pm, Options ops, int on, int always) +{ + char *arg = NULL; + + if ((on & PM_INTEGER) && OPT_HASARG(ops,'i')) + arg = OPT_ARG(ops,'i'); + else if ((on & PM_EFLOAT) && OPT_HASARG(ops,'E')) + arg = OPT_ARG(ops,'E'); + else if ((on & PM_FFLOAT) && OPT_HASARG(ops,'F')) + arg = OPT_ARG(ops,'F'); + + if (arg) { + char *eptr; + pm->base = (int)zstrtol(arg, &eptr, 10); + if (*eptr) { + if (on & PM_INTEGER) + zwarnnam(name, "bad base value: %s", arg, 0); + else + zwarnnam(name, "bad precision value: %s", arg, 0); + return 1; + } + } else if (always) + pm->base = 0; + + return 0; +} + +/* Install a width if we are turning on a padding option with an argument */ + +static int +typeset_setwidth(const char * name, Param pm, Options ops, int on, int always) +{ + char *arg = NULL; + + if ((on & PM_LEFT) && OPT_HASARG(ops,'L')) + arg = OPT_ARG(ops,'L'); + else if ((on & PM_RIGHT_B) && OPT_HASARG(ops,'R')) + arg = OPT_ARG(ops,'R'); + else if ((on & PM_RIGHT_Z) && OPT_HASARG(ops,'Z')) + arg = OPT_ARG(ops,'Z'); + + if (arg) { + char *eptr; + pm->width = (int)zstrtol(arg, &eptr, 10); + if (*eptr) { + zwarnnam(name, "bad width value: %s", arg, 0); + return 1; + } + } else if (always) + pm->width = 0; + + return 0; +} + /* function to set a single parameter */ /**/ static Param typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), int on, int off, int roff, char *value, Param altpm, - Options ops, int auxlen, int joinchar) + Options ops, int joinchar) { int usepm, tc, keeplocal = 0, newspecial = NS_NONE, readonly; char *subscript; @@ -1862,25 +1922,28 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), Param apm; char **x; if (PM_TYPE(pm->flags) == PM_ARRAY) { - x = (*pm->gets.afn)(pm); + x = (*pm->gsu.a->getfn)(pm); uniqarray(x); if (pm->ename && x) arrfixenv(pm->ename, x); } else if (PM_TYPE(pm->flags) == PM_SCALAR && pm->ename && (apm = (Param) paramtab->getnode(paramtab, pm->ename))) { - x = (*apm->gets.afn)(apm); + x = (*apm->gsu.a->getfn)(apm); uniqarray(x); if (x) arrfixenv(pm->nam, x); } } pm->flags = (pm->flags | (on & ~PM_READONLY)) & ~(off | PM_UNSET); - /* This auxlen/pm->ct stuff is a nasty hack. */ - if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER | - PM_EFLOAT | PM_FFLOAT)) && - auxlen) - pm->ct = auxlen; + if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 0)) + return NULL; + } + if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 0)) + return NULL; + } if (!(pm->flags & (PM_ARRAY|PM_HASHED))) { if (pm->flags & PM_EXPORTED) { if (!(pm->flags & PM_UNSET) && !pm->env && !value) @@ -1960,7 +2023,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), } tpm->old = pm->old; tpm->level = pm->level; - tpm->ct = pm->ct; + tpm->base = pm->base; + tpm->width = pm->width; if (pm->env) delenv(pm); tpm->env = NULL; @@ -1981,11 +2045,14 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), * Final tweak: if we've turned on one of the flags with * numbers, we should use the appropriate integer. */ - if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z|PM_INTEGER| - PM_EFLOAT|PM_FFLOAT)) - pm->ct = auxlen; - else - pm->ct = 0; + if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 1)) + return NULL; + } + if (on & (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 1)) + return NULL; + } } else if ((subscript = strchr(pname, '['))) { if (on & PM_READONLY) { zerrnam(cname, @@ -2027,7 +2094,14 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), */ pm = createparam(pname, on & ~PM_READONLY); DPUTS(!pm, "BUG: parameter not created"); - pm->ct = auxlen; + if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 0)) + return NULL; + } + if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 0)) + return NULL; + } } else { if (isident(pname)) zerrnam(cname, "not valid in this context: %s", pname, 0); @@ -2049,9 +2123,7 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), tdp->joinchar = joinchar; tdp->arrptr = &altpm->u.arr; - pm->sets.cfn = tiedarrsetfn; - pm->gets.cfn = tiedarrgetfn; - pm->unsetfn = tiedarrunsetfn; + pm->gsu.s = &tiedarr_gsu; pm->u.data = tdp; } @@ -2075,20 +2147,20 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), */ switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - pm->sets.cfn(pm, ztrdup("")); + pm->gsu.s->setfn(pm, ztrdup("")); break; case PM_INTEGER: - pm->sets.ifn(pm, 0); + pm->gsu.i->setfn(pm, 0); break; case PM_EFLOAT: case PM_FFLOAT: - pm->sets.ffn(pm, 0.0); + pm->gsu.f->setfn(pm, 0.0); break; case PM_ARRAY: - pm->sets.afn(pm, mkarray(NULL)); + pm->gsu.a->setfn(pm, mkarray(NULL)); break; case PM_HASHED: - pm->sets.hfn(pm, newparamtable(17, pm->nam)); + pm->gsu.h->setfn(pm, newparamtable(17, pm->nam)); break; } } @@ -2118,7 +2190,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) char *optstr = TYPESET_OPTSTR; int on = 0, off = 0, roff, bit = PM_ARRAY; int i; - int returnval = 0, printflags = 0, auxlen = 0; + int returnval = 0, printflags = 0; /* hash -f is really the builtin `functions' */ if (OPT_ISSET(ops,'f')) @@ -2134,43 +2206,27 @@ bin_typeset(char *name, char **argv, Options ops, int func) on |= bit; else if (OPT_PLUS(ops,optval)) off |= bit; - /* - * There is only a single field in struct param for widths, - * precisions and bases. Until this gets fixed, we can therefore - * bundle all optional arguments up into a single word. You - * may think this is very nasty, but then you should have seen the - * code before option arguments were handled properly. - */ - if (OPT_HASARG(ops,optval)) { - char *eptr, *arg = OPT_ARG(ops,optval); - auxlen = (int)zstrtol(arg, &eptr, 10); - if (*eptr) { - zwarnnam(name, "bad integer value: %s", arg, 0); - return 1; - } - } } roff = off; /* Sanity checks on the options. Remove conflicting options. */ if (on & PM_FFLOAT) { - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_INTEGER | PM_EFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_EFLOAT; /* Allow `float -F' to work even though float sets -E by default */ on &= ~PM_EFLOAT; } if (on & PM_EFLOAT) - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_INTEGER | PM_FFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_FFLOAT; if (on & PM_INTEGER) - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_EFLOAT | PM_FFLOAT; - if (on & PM_LEFT) - off |= PM_RIGHT_B | PM_INTEGER | PM_EFLOAT | PM_FFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_EFLOAT | PM_FFLOAT; + /* + * Allowing -Z with -L is a feature: left justify, suppressing + * leading zeroes. + */ + if (on & (PM_LEFT|PM_RIGHT_Z)) + off |= PM_RIGHT_B; if (on & PM_RIGHT_B) - off |= PM_LEFT | PM_INTEGER | PM_EFLOAT | PM_FFLOAT; - if (on & PM_RIGHT_Z) - off |= PM_INTEGER | PM_EFLOAT | PM_FFLOAT; + off |= PM_LEFT | PM_RIGHT_Z; if (on & PM_UPPER) off |= PM_LOWER; if (on & PM_LOWER) @@ -2279,8 +2335,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) (Param)paramtab->getnode(paramtab, asg->name), func, (on | PM_ARRAY) & ~PM_EXPORTED, - off, roff, asg->value, NULL, ops, auxlen, - 0))) { + off, roff, asg->value, NULL, ops, 0))) { unqueue_signals(); return 1; } @@ -2292,7 +2347,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) (Param)paramtab->getnode(paramtab, asg0.name), func, on, off, roff, asg0.value, apm, - ops, auxlen, joinchar))) { + ops, joinchar))) { if (oldval) zsfree(oldval); unsetparam_pm(apm, 1, 1); @@ -2367,7 +2422,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) { pm = (Param) getdata(pmnode); if (!typeset_single(name, pm->nam, pm, func, on, off, roff, - asg->value, NULL, ops, auxlen, 0)) + asg->value, NULL, ops, 0)) returnval = 1; } } @@ -2382,7 +2437,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) gethashnode2(paramtab, asg->name) : paramtab->getnode(paramtab, asg->name)), func, on, off, roff, asg->value, NULL, - ops, auxlen, 0)) + ops, 0)) returnval = 1; } unqueue_signals(); @@ -2681,7 +2736,7 @@ bin_unset(char *name, char **argv, Options ops, int func) } else if (ss) { if (PM_TYPE(pm->flags) == PM_HASHED) { HashTable tht = paramtab; - if ((paramtab = pm->gets.hfn(pm))) { + if ((paramtab = pm->gsu.h->getfn(pm))) { *--sse = 0; unsetparam(ss+1); *sse = ']'; |