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
|
||||
|
||||
__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
|
||||
/*
|
||||
@ -741,385 +741,6 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
|
||||
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
|
||||
c_alias(const char **wp)
|
||||
{
|
||||
|
383
var.c
383
var.c
@ -28,7 +28,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#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
|
||||
@ -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() */
|
||||
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 void exportprep(struct tbl *, const char *);
|
||||
static int special(const char *);
|
||||
@ -1771,3 +1774,381 @@ record_match(const char *istr)
|
||||
vp->flag = DEFINED | RDONLY;
|
||||
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…
Reference in New Issue
Block a user