move c_typeset() to var.c so we have access to either array_index_calc() or innermost_refflag for 'typeset -p x[2]'
This commit is contained in:
parent
ced705ae04
commit
ab976fd8d3
381
funcs.c
381
funcs.c
@ -38,7 +38,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.332 2017/04/02 15:00:42 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.333 2017/04/02 15:51:19 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -741,385 +741,6 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
|
|||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typeset, global(deprecated), export, and readonly */
|
|
||||||
static void c_typeset_vardump(struct tbl *, uint32_t, int, bool, bool);
|
|
||||||
static void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,
|
|
||||||
bool);
|
|
||||||
int
|
|
||||||
c_typeset(const char **wp)
|
|
||||||
{
|
|
||||||
struct tbl *vp, **p;
|
|
||||||
uint32_t fset = 0, fclr = 0, flag;
|
|
||||||
int thing = 0, field = 0, base = 0, i;
|
|
||||||
struct block *l;
|
|
||||||
const char *opts;
|
|
||||||
const char *fieldstr = NULL, *basestr = NULL;
|
|
||||||
bool localv = false, func = false, pflag = false, istset = true;
|
|
||||||
enum namerefflag new_refflag = SRF_NOP;
|
|
||||||
|
|
||||||
switch (**wp) {
|
|
||||||
|
|
||||||
/* export */
|
|
||||||
case 'e':
|
|
||||||
fset |= EXPORT;
|
|
||||||
istset = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* readonly */
|
|
||||||
case 'r':
|
|
||||||
fset |= RDONLY;
|
|
||||||
istset = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* set */
|
|
||||||
case 's':
|
|
||||||
/* called with 'typeset -' */
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* typeset */
|
|
||||||
case 't':
|
|
||||||
localv = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* see comment below regarding possible opions */
|
|
||||||
opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
|
|
||||||
|
|
||||||
builtin_opt.flags |= GF_PLUSOPT;
|
|
||||||
/*
|
|
||||||
* AT&T ksh seems to have 0-9 as options which are multiplied
|
|
||||||
* to get a number that is used with -L, -R, -Z or -i (eg, -1R2
|
|
||||||
* sets right justify in a field of 12). This allows options
|
|
||||||
* to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
|
|
||||||
* does not allow the number to be specified as a separate argument
|
|
||||||
* Here, the number must follow the RLZi option, but is optional
|
|
||||||
* (see the # kludge in ksh_getopt()).
|
|
||||||
*/
|
|
||||||
while ((i = ksh_getopt(wp, &builtin_opt, opts)) != -1) {
|
|
||||||
flag = 0;
|
|
||||||
switch (i) {
|
|
||||||
case 'L':
|
|
||||||
flag = LJUST;
|
|
||||||
fieldstr = builtin_opt.optarg;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
flag = RJUST;
|
|
||||||
fieldstr = builtin_opt.optarg;
|
|
||||||
break;
|
|
||||||
case 'U':
|
|
||||||
/*
|
|
||||||
* AT&T ksh uses u, but this conflicts with
|
|
||||||
* upper/lower case. If this option is changed,
|
|
||||||
* need to change the -U below as well
|
|
||||||
*/
|
|
||||||
flag = INT_U;
|
|
||||||
break;
|
|
||||||
case 'Z':
|
|
||||||
flag = ZEROFIL;
|
|
||||||
fieldstr = builtin_opt.optarg;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
/*
|
|
||||||
* this is supposed to set (-a) or unset (+a) the
|
|
||||||
* indexed array attribute; it does nothing on an
|
|
||||||
* existing regular string or indexed array though
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
func = true;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
localv = (builtin_opt.info & GI_PLUS) ? true : false;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
flag = INTEGER;
|
|
||||||
basestr = builtin_opt.optarg;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
flag = LCASEV;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
new_refflag = (builtin_opt.info & GI_PLUS) ?
|
|
||||||
SRF_DISABLE : SRF_ENABLE;
|
|
||||||
break;
|
|
||||||
/* export, readonly: POSIX -p flag */
|
|
||||||
case 'p':
|
|
||||||
/* typeset: show values as well */
|
|
||||||
pflag = true;
|
|
||||||
if (istset)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
flag = RDONLY;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
flag = TRACE;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
/* upper case / autoload */
|
|
||||||
flag = UCASEV_AL;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
flag = EXPORT;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
if (builtin_opt.info & GI_PLUS) {
|
|
||||||
fclr |= flag;
|
|
||||||
fset &= ~flag;
|
|
||||||
thing = '+';
|
|
||||||
} else {
|
|
||||||
fset |= flag;
|
|
||||||
fclr &= ~flag;
|
|
||||||
thing = '-';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldstr && !bi_getn(fieldstr, &field))
|
|
||||||
return (1);
|
|
||||||
if (basestr) {
|
|
||||||
if (!getn(basestr, &base)) {
|
|
||||||
bi_errorf(Tf_sD_s, "bad integer base", basestr);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
if (base < 1 || base > 36)
|
|
||||||
base = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
|
|
||||||
(wp[builtin_opt.optind][0] == '-' ||
|
|
||||||
wp[builtin_opt.optind][0] == '+') &&
|
|
||||||
wp[builtin_opt.optind][1] == '\0') {
|
|
||||||
thing = wp[builtin_opt.optind][0];
|
|
||||||
builtin_opt.optind++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
|
|
||||||
new_refflag != SRF_NOP)) {
|
|
||||||
bi_errorf("only -t, -u and -x options may be used with -f");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
if (wp[builtin_opt.optind]) {
|
|
||||||
/*
|
|
||||||
* Take care of exclusions.
|
|
||||||
* At this point, flags in fset are cleared in fclr and vice
|
|
||||||
* versa. This property should be preserved.
|
|
||||||
*/
|
|
||||||
if (fset & LCASEV)
|
|
||||||
/* LCASEV has priority over UCASEV_AL */
|
|
||||||
fset &= ~UCASEV_AL;
|
|
||||||
if (fset & LJUST)
|
|
||||||
/* LJUST has priority over RJUST */
|
|
||||||
fset &= ~RJUST;
|
|
||||||
if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) {
|
|
||||||
/* -Z implies -ZR */
|
|
||||||
fset |= RJUST;
|
|
||||||
fclr &= ~RJUST;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Setting these attributes clears the others, unless they
|
|
||||||
* are also set in this command
|
|
||||||
*/
|
|
||||||
if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
|
|
||||||
INTEGER | INT_U | INT_L)) || new_refflag != SRF_NOP)
|
|
||||||
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
|
|
||||||
LCASEV | INTEGER | INT_U | INT_L);
|
|
||||||
}
|
|
||||||
if (new_refflag != SRF_NOP) {
|
|
||||||
fclr &= ~(ARRAY | ASSOC);
|
|
||||||
fset &= ~(ARRAY | ASSOC);
|
|
||||||
fclr |= EXPORT;
|
|
||||||
fset |= ASSOC;
|
|
||||||
if (new_refflag == SRF_DISABLE)
|
|
||||||
fclr |= ASSOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set variables and attributes */
|
|
||||||
if (wp[builtin_opt.optind] &&
|
|
||||||
/* not "typeset -p varname" */
|
|
||||||
!(!func && pflag && !(fset | fclr))) {
|
|
||||||
int rv = 0;
|
|
||||||
struct tbl *f;
|
|
||||||
|
|
||||||
if (localv && !func)
|
|
||||||
fset |= LOCAL;
|
|
||||||
for (i = builtin_opt.optind; wp[i]; i++) {
|
|
||||||
if (func) {
|
|
||||||
f = findfunc(wp[i], hash(wp[i]),
|
|
||||||
tobool(fset & UCASEV_AL));
|
|
||||||
if (!f) {
|
|
||||||
/* AT&T ksh does ++rv: bogus */
|
|
||||||
rv = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fset | fclr) {
|
|
||||||
f->flag |= fset;
|
|
||||||
f->flag &= ~fclr;
|
|
||||||
} else {
|
|
||||||
fpFUNCTf(shl_stdout, 0,
|
|
||||||
tobool(f->flag & FKSH),
|
|
||||||
wp[i], f->val.t);
|
|
||||||
shf_putc('\n', shl_stdout);
|
|
||||||
}
|
|
||||||
} else if (!typeset(wp[i], fset, fclr, field, base)) {
|
|
||||||
bi_errorf(Tf_sD_s, wp[i], Tnot_ident);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* list variables and attributes */
|
|
||||||
|
|
||||||
/* no difference at this point.. */
|
|
||||||
flag = fset | fclr;
|
|
||||||
if (func) {
|
|
||||||
for (l = e->loc; l; l = l->next) {
|
|
||||||
for (p = ktsort(&l->funs); (vp = *p++); ) {
|
|
||||||
if (flag && (vp->flag & flag) == 0)
|
|
||||||
continue;
|
|
||||||
if (thing == '-')
|
|
||||||
fpFUNCTf(shl_stdout, 0,
|
|
||||||
tobool(vp->flag & FKSH),
|
|
||||||
vp->name, vp->val.t);
|
|
||||||
else
|
|
||||||
shf_puts(vp->name, shl_stdout);
|
|
||||||
shf_putc('\n', shl_stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (wp[builtin_opt.optind]) {
|
|
||||||
for (i = builtin_opt.optind; wp[i]; i++) {
|
|
||||||
varsearch(e->loc, &vp, wp[i], hash(wp[i]));
|
|
||||||
c_typeset_vardump(vp, flag, thing, pflag, istset);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
c_typeset_vardump_recursive(e->loc, flag, thing, pflag, istset);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
c_typeset_vardump_recursive(struct block *l, uint32_t flag, int thing,
|
|
||||||
bool pflag, bool istset)
|
|
||||||
{
|
|
||||||
struct tbl **blockvars, *vp;
|
|
||||||
|
|
||||||
if (l->next)
|
|
||||||
c_typeset_vardump_recursive(l->next, flag, thing, pflag, istset);
|
|
||||||
blockvars = ktsort(&l->vars);
|
|
||||||
while ((vp = *blockvars++))
|
|
||||||
c_typeset_vardump(vp, flag, thing, pflag, istset);
|
|
||||||
/*XXX doesn’t this leak? */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
c_typeset_vardump(struct tbl *vp, uint32_t flag, int thing, bool pflag,
|
|
||||||
bool istset)
|
|
||||||
{
|
|
||||||
struct tbl *tvp;
|
|
||||||
int any_set = 0;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
if (!vp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if the parameter is set (for arrays, if any
|
|
||||||
* element is set).
|
|
||||||
*/
|
|
||||||
for (tvp = vp; tvp; tvp = tvp->u.array)
|
|
||||||
if (tvp->flag & ISSET) {
|
|
||||||
any_set = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check attributes - note that all array elements
|
|
||||||
* have (should have?) the same attributes, so checking
|
|
||||||
* the first is sufficient.
|
|
||||||
*
|
|
||||||
* Report an unset param only if the user has
|
|
||||||
* explicitly given it some attribute (like export);
|
|
||||||
* otherwise, after "echo $FOO", we would report FOO...
|
|
||||||
*/
|
|
||||||
if (!any_set && !(vp->flag & USERATTRIB))
|
|
||||||
return;
|
|
||||||
if (flag && (vp->flag & flag) == 0)
|
|
||||||
return;
|
|
||||||
if (!(vp->flag & ARRAY))
|
|
||||||
/* optimise later conditionals */
|
|
||||||
any_set = 0;
|
|
||||||
do {
|
|
||||||
/*
|
|
||||||
* Ignore array elements that aren't set unless there
|
|
||||||
* are no set elements, in which case the first is
|
|
||||||
* reported on
|
|
||||||
*/
|
|
||||||
if (any_set && !(vp->flag & ISSET))
|
|
||||||
continue;
|
|
||||||
/* no arguments */
|
|
||||||
if (!thing && !flag) {
|
|
||||||
if (any_set == 1) {
|
|
||||||
shprintf(Tf_s_s_sN, Tset, "-A", vp->name);
|
|
||||||
any_set = 2;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* AT&T ksh prints things like export, integer,
|
|
||||||
* leftadj, zerofill, etc., but POSIX says must
|
|
||||||
* be suitable for re-entry...
|
|
||||||
*/
|
|
||||||
shprintf(Tf_s_s, Ttypeset, "");
|
|
||||||
if (((vp->flag & (ARRAY | ASSOC)) == ASSOC))
|
|
||||||
shprintf(Tf__c_, 'n');
|
|
||||||
if ((vp->flag & INTEGER))
|
|
||||||
shprintf(Tf__c_, 'i');
|
|
||||||
if ((vp->flag & EXPORT))
|
|
||||||
shprintf(Tf__c_, 'x');
|
|
||||||
if ((vp->flag & RDONLY))
|
|
||||||
shprintf(Tf__c_, 'r');
|
|
||||||
if ((vp->flag & TRACE))
|
|
||||||
shprintf(Tf__c_, 't');
|
|
||||||
if ((vp->flag & LJUST))
|
|
||||||
shprintf("-L%d ", vp->u2.field);
|
|
||||||
if ((vp->flag & RJUST))
|
|
||||||
shprintf("-R%d ", vp->u2.field);
|
|
||||||
if ((vp->flag & ZEROFIL))
|
|
||||||
shprintf(Tf__c_, 'Z');
|
|
||||||
if ((vp->flag & LCASEV))
|
|
||||||
shprintf(Tf__c_, 'l');
|
|
||||||
if ((vp->flag & UCASEV_AL))
|
|
||||||
shprintf(Tf__c_, 'u');
|
|
||||||
if ((vp->flag & INT_U))
|
|
||||||
shprintf(Tf__c_, 'U');
|
|
||||||
} else if (pflag) {
|
|
||||||
shprintf(Tf_s_s, istset ? Ttypeset :
|
|
||||||
(flag & EXPORT) ? Texport : Treadonly, "");
|
|
||||||
}
|
|
||||||
if (any_set)
|
|
||||||
shprintf("%s[%lu]", vp->name, arrayindex(vp));
|
|
||||||
else
|
|
||||||
shf_puts(vp->name, shl_stdout);
|
|
||||||
if ((!thing && !flag && pflag) ||
|
|
||||||
(thing == '-' && (vp->flag & ISSET))) {
|
|
||||||
s = str_val(vp);
|
|
||||||
shf_putc('=', shl_stdout);
|
|
||||||
/* AT&T ksh can't have justified integers... */
|
|
||||||
if ((vp->flag & (INTEGER | LJUST | RJUST)) == INTEGER)
|
|
||||||
shf_puts(s, shl_stdout);
|
|
||||||
else
|
|
||||||
print_value_quoted(shl_stdout, s);
|
|
||||||
}
|
|
||||||
shf_putc('\n', shl_stdout);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only report first 'element' of an array with
|
|
||||||
* no set elements.
|
|
||||||
*/
|
|
||||||
if (!any_set)
|
|
||||||
return;
|
|
||||||
} while ((vp = vp->u.array));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
c_alias(const char **wp)
|
c_alias(const char **wp)
|
||||||
{
|
{
|
||||||
|
383
var.c
383
var.c
@ -28,7 +28,7 @@
|
|||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.210 2017/03/26 00:10:26 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.211 2017/04/02 15:51:20 tg Exp $");
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Variables
|
* Variables
|
||||||
@ -45,6 +45,9 @@ static uint32_t lcg_state = 5381, qh_state = 4711;
|
|||||||
/* may only be set by typeset() just before call to array_index_calc() */
|
/* may only be set by typeset() just before call to array_index_calc() */
|
||||||
static enum namerefflag innermost_refflag = SRF_NOP;
|
static enum namerefflag innermost_refflag = SRF_NOP;
|
||||||
|
|
||||||
|
static void c_typeset_vardump(struct tbl *, uint32_t, int, bool, bool);
|
||||||
|
static void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,
|
||||||
|
bool);
|
||||||
static char *formatstr(struct tbl *, const char *);
|
static char *formatstr(struct tbl *, const char *);
|
||||||
static void exportprep(struct tbl *, const char *);
|
static void exportprep(struct tbl *, const char *);
|
||||||
static int special(const char *);
|
static int special(const char *);
|
||||||
@ -1771,3 +1774,381 @@ record_match(const char *istr)
|
|||||||
vp->flag = DEFINED | RDONLY;
|
vp->flag = DEFINED | RDONLY;
|
||||||
setstr(vp, istr, 0x4);
|
setstr(vp, istr, 0x4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* typeset, global(deprecated), export, and readonly */
|
||||||
|
int
|
||||||
|
c_typeset(const char **wp)
|
||||||
|
{
|
||||||
|
struct tbl *vp, **p;
|
||||||
|
uint32_t fset = 0, fclr = 0, flag;
|
||||||
|
int thing = 0, field = 0, base = 0, i;
|
||||||
|
struct block *l;
|
||||||
|
const char *opts;
|
||||||
|
const char *fieldstr = NULL, *basestr = NULL;
|
||||||
|
bool localv = false, func = false, pflag = false, istset = true;
|
||||||
|
enum namerefflag new_refflag = SRF_NOP;
|
||||||
|
|
||||||
|
switch (**wp) {
|
||||||
|
|
||||||
|
/* export */
|
||||||
|
case 'e':
|
||||||
|
fset |= EXPORT;
|
||||||
|
istset = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* readonly */
|
||||||
|
case 'r':
|
||||||
|
fset |= RDONLY;
|
||||||
|
istset = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* set */
|
||||||
|
case 's':
|
||||||
|
/* called with 'typeset -' */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* typeset */
|
||||||
|
case 't':
|
||||||
|
localv = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* see comment below regarding possible opions */
|
||||||
|
opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
|
||||||
|
|
||||||
|
builtin_opt.flags |= GF_PLUSOPT;
|
||||||
|
/*
|
||||||
|
* AT&T ksh seems to have 0-9 as options which are multiplied
|
||||||
|
* to get a number that is used with -L, -R, -Z or -i (eg, -1R2
|
||||||
|
* sets right justify in a field of 12). This allows options
|
||||||
|
* to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
|
||||||
|
* does not allow the number to be specified as a separate argument
|
||||||
|
* Here, the number must follow the RLZi option, but is optional
|
||||||
|
* (see the # kludge in ksh_getopt()).
|
||||||
|
*/
|
||||||
|
while ((i = ksh_getopt(wp, &builtin_opt, opts)) != -1) {
|
||||||
|
flag = 0;
|
||||||
|
switch (i) {
|
||||||
|
case 'L':
|
||||||
|
flag = LJUST;
|
||||||
|
fieldstr = builtin_opt.optarg;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
flag = RJUST;
|
||||||
|
fieldstr = builtin_opt.optarg;
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
/*
|
||||||
|
* AT&T ksh uses u, but this conflicts with
|
||||||
|
* upper/lower case. If this option is changed,
|
||||||
|
* need to change the -U below as well
|
||||||
|
*/
|
||||||
|
flag = INT_U;
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
flag = ZEROFIL;
|
||||||
|
fieldstr = builtin_opt.optarg;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
/*
|
||||||
|
* this is supposed to set (-a) or unset (+a) the
|
||||||
|
* indexed array attribute; it does nothing on an
|
||||||
|
* existing regular string or indexed array though
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
func = true;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
localv = (builtin_opt.info & GI_PLUS) ? true : false;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
flag = INTEGER;
|
||||||
|
basestr = builtin_opt.optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
flag = LCASEV;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
new_refflag = (builtin_opt.info & GI_PLUS) ?
|
||||||
|
SRF_DISABLE : SRF_ENABLE;
|
||||||
|
break;
|
||||||
|
/* export, readonly: POSIX -p flag */
|
||||||
|
case 'p':
|
||||||
|
/* typeset: show values as well */
|
||||||
|
pflag = true;
|
||||||
|
if (istset)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
flag = RDONLY;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
flag = TRACE;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
/* upper case / autoload */
|
||||||
|
flag = UCASEV_AL;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
flag = EXPORT;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
if (builtin_opt.info & GI_PLUS) {
|
||||||
|
fclr |= flag;
|
||||||
|
fset &= ~flag;
|
||||||
|
thing = '+';
|
||||||
|
} else {
|
||||||
|
fset |= flag;
|
||||||
|
fclr &= ~flag;
|
||||||
|
thing = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldstr && !getn(fieldstr, &field)) {
|
||||||
|
bi_errorf(Tf_sD_s, "bad number", fieldstr);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
if (basestr) {
|
||||||
|
if (!getn(basestr, &base)) {
|
||||||
|
bi_errorf(Tf_sD_s, "bad integer base", basestr);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
if (base < 1 || base > 36)
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
|
||||||
|
(wp[builtin_opt.optind][0] == '-' ||
|
||||||
|
wp[builtin_opt.optind][0] == '+') &&
|
||||||
|
wp[builtin_opt.optind][1] == '\0') {
|
||||||
|
thing = wp[builtin_opt.optind][0];
|
||||||
|
builtin_opt.optind++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
|
||||||
|
new_refflag != SRF_NOP)) {
|
||||||
|
bi_errorf("only -t, -u and -x options may be used with -f");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
if (wp[builtin_opt.optind]) {
|
||||||
|
/*
|
||||||
|
* Take care of exclusions.
|
||||||
|
* At this point, flags in fset are cleared in fclr and vice
|
||||||
|
* versa. This property should be preserved.
|
||||||
|
*/
|
||||||
|
if (fset & LCASEV)
|
||||||
|
/* LCASEV has priority over UCASEV_AL */
|
||||||
|
fset &= ~UCASEV_AL;
|
||||||
|
if (fset & LJUST)
|
||||||
|
/* LJUST has priority over RJUST */
|
||||||
|
fset &= ~RJUST;
|
||||||
|
if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) {
|
||||||
|
/* -Z implies -ZR */
|
||||||
|
fset |= RJUST;
|
||||||
|
fclr &= ~RJUST;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Setting these attributes clears the others, unless they
|
||||||
|
* are also set in this command
|
||||||
|
*/
|
||||||
|
if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
|
||||||
|
INTEGER | INT_U | INT_L)) || new_refflag != SRF_NOP)
|
||||||
|
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
|
||||||
|
LCASEV | INTEGER | INT_U | INT_L);
|
||||||
|
}
|
||||||
|
if (new_refflag != SRF_NOP) {
|
||||||
|
fclr &= ~(ARRAY | ASSOC);
|
||||||
|
fset &= ~(ARRAY | ASSOC);
|
||||||
|
fclr |= EXPORT;
|
||||||
|
fset |= ASSOC;
|
||||||
|
if (new_refflag == SRF_DISABLE)
|
||||||
|
fclr |= ASSOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set variables and attributes */
|
||||||
|
if (wp[builtin_opt.optind] &&
|
||||||
|
/* not "typeset -p varname" */
|
||||||
|
!(!func && pflag && !(fset | fclr))) {
|
||||||
|
int rv = 0;
|
||||||
|
struct tbl *f;
|
||||||
|
|
||||||
|
if (localv && !func)
|
||||||
|
fset |= LOCAL;
|
||||||
|
for (i = builtin_opt.optind; wp[i]; i++) {
|
||||||
|
if (func) {
|
||||||
|
f = findfunc(wp[i], hash(wp[i]),
|
||||||
|
tobool(fset & UCASEV_AL));
|
||||||
|
if (!f) {
|
||||||
|
/* AT&T ksh does ++rv: bogus */
|
||||||
|
rv = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fset | fclr) {
|
||||||
|
f->flag |= fset;
|
||||||
|
f->flag &= ~fclr;
|
||||||
|
} else {
|
||||||
|
fpFUNCTf(shl_stdout, 0,
|
||||||
|
tobool(f->flag & FKSH),
|
||||||
|
wp[i], f->val.t);
|
||||||
|
shf_putc('\n', shl_stdout);
|
||||||
|
}
|
||||||
|
} else if (!typeset(wp[i], fset, fclr, field, base)) {
|
||||||
|
bi_errorf(Tf_sD_s, wp[i], Tnot_ident);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list variables and attributes */
|
||||||
|
|
||||||
|
/* no difference at this point.. */
|
||||||
|
flag = fset | fclr;
|
||||||
|
if (func) {
|
||||||
|
for (l = e->loc; l; l = l->next) {
|
||||||
|
for (p = ktsort(&l->funs); (vp = *p++); ) {
|
||||||
|
if (flag && (vp->flag & flag) == 0)
|
||||||
|
continue;
|
||||||
|
if (thing == '-')
|
||||||
|
fpFUNCTf(shl_stdout, 0,
|
||||||
|
tobool(vp->flag & FKSH),
|
||||||
|
vp->name, vp->val.t);
|
||||||
|
else
|
||||||
|
shf_puts(vp->name, shl_stdout);
|
||||||
|
shf_putc('\n', shl_stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (wp[builtin_opt.optind]) {
|
||||||
|
for (i = builtin_opt.optind; wp[i]; i++) {
|
||||||
|
varsearch(e->loc, &vp, wp[i], hash(wp[i]));
|
||||||
|
c_typeset_vardump(vp, flag, thing, pflag, istset);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
c_typeset_vardump_recursive(e->loc, flag, thing, pflag, istset);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
c_typeset_vardump_recursive(struct block *l, uint32_t flag, int thing,
|
||||||
|
bool pflag, bool istset)
|
||||||
|
{
|
||||||
|
struct tbl **blockvars, *vp;
|
||||||
|
|
||||||
|
if (l->next)
|
||||||
|
c_typeset_vardump_recursive(l->next, flag, thing, pflag, istset);
|
||||||
|
blockvars = ktsort(&l->vars);
|
||||||
|
while ((vp = *blockvars++))
|
||||||
|
c_typeset_vardump(vp, flag, thing, pflag, istset);
|
||||||
|
/*XXX doesn’t this leak? */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
c_typeset_vardump(struct tbl *vp, uint32_t flag, int thing, bool pflag,
|
||||||
|
bool istset)
|
||||||
|
{
|
||||||
|
struct tbl *tvp;
|
||||||
|
int any_set = 0;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if (!vp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if the parameter is set (for arrays, if any
|
||||||
|
* element is set).
|
||||||
|
*/
|
||||||
|
for (tvp = vp; tvp; tvp = tvp->u.array)
|
||||||
|
if (tvp->flag & ISSET) {
|
||||||
|
any_set = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check attributes - note that all array elements
|
||||||
|
* have (should have?) the same attributes, so checking
|
||||||
|
* the first is sufficient.
|
||||||
|
*
|
||||||
|
* Report an unset param only if the user has
|
||||||
|
* explicitly given it some attribute (like export);
|
||||||
|
* otherwise, after "echo $FOO", we would report FOO...
|
||||||
|
*/
|
||||||
|
if (!any_set && !(vp->flag & USERATTRIB))
|
||||||
|
return;
|
||||||
|
if (flag && (vp->flag & flag) == 0)
|
||||||
|
return;
|
||||||
|
if (!(vp->flag & ARRAY))
|
||||||
|
/* optimise later conditionals */
|
||||||
|
any_set = 0;
|
||||||
|
do {
|
||||||
|
/*
|
||||||
|
* Ignore array elements that aren't set unless there
|
||||||
|
* are no set elements, in which case the first is
|
||||||
|
* reported on
|
||||||
|
*/
|
||||||
|
if (any_set && !(vp->flag & ISSET))
|
||||||
|
continue;
|
||||||
|
/* no arguments */
|
||||||
|
if (!thing && !flag) {
|
||||||
|
if (any_set == 1) {
|
||||||
|
shprintf(Tf_s_s_sN, Tset, "-A", vp->name);
|
||||||
|
any_set = 2;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* AT&T ksh prints things like export, integer,
|
||||||
|
* leftadj, zerofill, etc., but POSIX says must
|
||||||
|
* be suitable for re-entry...
|
||||||
|
*/
|
||||||
|
shprintf(Tf_s_s, Ttypeset, "");
|
||||||
|
if (((vp->flag & (ARRAY | ASSOC)) == ASSOC))
|
||||||
|
shprintf(Tf__c_, 'n');
|
||||||
|
if ((vp->flag & INTEGER))
|
||||||
|
shprintf(Tf__c_, 'i');
|
||||||
|
if ((vp->flag & EXPORT))
|
||||||
|
shprintf(Tf__c_, 'x');
|
||||||
|
if ((vp->flag & RDONLY))
|
||||||
|
shprintf(Tf__c_, 'r');
|
||||||
|
if ((vp->flag & TRACE))
|
||||||
|
shprintf(Tf__c_, 't');
|
||||||
|
if ((vp->flag & LJUST))
|
||||||
|
shprintf("-L%d ", vp->u2.field);
|
||||||
|
if ((vp->flag & RJUST))
|
||||||
|
shprintf("-R%d ", vp->u2.field);
|
||||||
|
if ((vp->flag & ZEROFIL))
|
||||||
|
shprintf(Tf__c_, 'Z');
|
||||||
|
if ((vp->flag & LCASEV))
|
||||||
|
shprintf(Tf__c_, 'l');
|
||||||
|
if ((vp->flag & UCASEV_AL))
|
||||||
|
shprintf(Tf__c_, 'u');
|
||||||
|
if ((vp->flag & INT_U))
|
||||||
|
shprintf(Tf__c_, 'U');
|
||||||
|
} else if (pflag) {
|
||||||
|
shprintf(Tf_s_s, istset ? Ttypeset :
|
||||||
|
(flag & EXPORT) ? Texport : Treadonly, "");
|
||||||
|
}
|
||||||
|
if (any_set)
|
||||||
|
shprintf("%s[%lu]", vp->name, arrayindex(vp));
|
||||||
|
else
|
||||||
|
shf_puts(vp->name, shl_stdout);
|
||||||
|
if ((!thing && !flag && pflag) ||
|
||||||
|
(thing == '-' && (vp->flag & ISSET))) {
|
||||||
|
s = str_val(vp);
|
||||||
|
shf_putc('=', shl_stdout);
|
||||||
|
/* AT&T ksh can't have justified integers... */
|
||||||
|
if ((vp->flag & (INTEGER | LJUST | RJUST)) == INTEGER)
|
||||||
|
shf_puts(s, shl_stdout);
|
||||||
|
else
|
||||||
|
print_value_quoted(shl_stdout, s);
|
||||||
|
}
|
||||||
|
shf_putc('\n', shl_stdout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only report first 'element' of an array with
|
||||||
|
* no set elements.
|
||||||
|
*/
|
||||||
|
if (!any_set)
|
||||||
|
return;
|
||||||
|
} while ((vp = vp->u.array));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user