merge the nameref code, using mksh standard scoping as discussed
This commit is contained in:
parent
574d6725aa
commit
9531e12b36
115
check.t
115
check.t
@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.302 2009/08/30 21:01:59 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.303 2009/09/06 17:42:11 tg Exp $
|
||||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||||
@ -4197,7 +4197,7 @@ name: xxx-param-subst-qmark-1
|
|||||||
description:
|
description:
|
||||||
Check suppresion of error message with null string. According to
|
Check suppresion of error message with null string. According to
|
||||||
POSIX, it shouldn't print the error as 'word' isn't ommitted.
|
POSIX, it shouldn't print the error as 'word' isn't ommitted.
|
||||||
ksh88, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error,
|
ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error,
|
||||||
that's why the condition is reversed.
|
that's why the condition is reversed.
|
||||||
stdin:
|
stdin:
|
||||||
unset foo
|
unset foo
|
||||||
@ -4731,6 +4731,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -4753,6 +4754,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -4799,6 +4801,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -4823,6 +4826,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -4846,6 +4850,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -4868,6 +4873,7 @@ expected-stdout:
|
|||||||
integer='typeset -i'
|
integer='typeset -i'
|
||||||
local=typeset
|
local=typeset
|
||||||
login='exec login'
|
login='exec login'
|
||||||
|
nameref='typeset -n'
|
||||||
nohup='nohup '
|
nohup='nohup '
|
||||||
r='fc -e -'
|
r='fc -e -'
|
||||||
source='PATH=$PATH:. command .'
|
source='PATH=$PATH:. command .'
|
||||||
@ -5006,6 +5012,33 @@ expected-stdout:
|
|||||||
g 0<0>1<1>2<4> = g
|
g 0<0>1<1>2<4> = g
|
||||||
h 0<0>1<1>2<4> = h
|
h 0<0>1<1>2<4> = h
|
||||||
---
|
---
|
||||||
|
name: arrays-7
|
||||||
|
description:
|
||||||
|
Check if we can get the array keys (indices) for indexed arrays,
|
||||||
|
Korn shell style, in some corner cases
|
||||||
|
stdin:
|
||||||
|
print !arz: ${!arz}
|
||||||
|
print !arz[0]: ${!arz[0]}
|
||||||
|
print !arz[1]: ${!arz[1]}
|
||||||
|
arz=foo
|
||||||
|
print !arz: ${!arz}
|
||||||
|
print !arz[0]: ${!arz[0]}
|
||||||
|
print !arz[1]: ${!arz[1]}
|
||||||
|
unset arz
|
||||||
|
print !arz: ${!arz}
|
||||||
|
print !arz[0]: ${!arz[0]}
|
||||||
|
print !arz[1]: ${!arz[1]}
|
||||||
|
expected-stdout:
|
||||||
|
!arz: 0
|
||||||
|
!arz[0]:
|
||||||
|
!arz[1]:
|
||||||
|
!arz: arz
|
||||||
|
!arz[0]: 0
|
||||||
|
!arz[1]:
|
||||||
|
!arz: 0
|
||||||
|
!arz[0]:
|
||||||
|
!arz[1]:
|
||||||
|
---
|
||||||
name: varexpand-substr-1
|
name: varexpand-substr-1
|
||||||
description:
|
description:
|
||||||
Check if bash-style substring expansion works
|
Check if bash-style substring expansion works
|
||||||
@ -6100,3 +6133,81 @@ expected-stdout:
|
|||||||
mypid=nz
|
mypid=nz
|
||||||
=15
|
=15
|
||||||
---
|
---
|
||||||
|
name: nameref-1
|
||||||
|
description:
|
||||||
|
Testsuite for nameref (bound variables)
|
||||||
|
stdin:
|
||||||
|
bar=global
|
||||||
|
typeset -n ir2=bar
|
||||||
|
typeset -n ind=ir2
|
||||||
|
print !ind: ${!ind}
|
||||||
|
print ind: $ind
|
||||||
|
print !ir2: ${!ir2}
|
||||||
|
print ir2: $ir2
|
||||||
|
typeset +n ind
|
||||||
|
print !ind: ${!ind}
|
||||||
|
print ind: $ind
|
||||||
|
typeset -n ir2=ind
|
||||||
|
print !ir2: ${!ir2}
|
||||||
|
print ir2: $ir2
|
||||||
|
set|grep ^ir2|sed 's/^/s1: /'
|
||||||
|
typeset|grep ' ir2'|sed -e 's/^/s2: /' -e 's/nameref/typeset -n/'
|
||||||
|
blub=(e1 e2 e3)
|
||||||
|
typeset -n ind=blub
|
||||||
|
typeset -n ir2=blub[2]
|
||||||
|
print !ind[1]: ${!ind[1]}
|
||||||
|
print !ir2: $!ir2
|
||||||
|
print ind[1]: ${ind[1]}
|
||||||
|
print ir2: $ir2
|
||||||
|
expected-stdout:
|
||||||
|
!ind: bar
|
||||||
|
ind: global
|
||||||
|
!ir2: bar
|
||||||
|
ir2: global
|
||||||
|
!ind: ind
|
||||||
|
ind: ir2
|
||||||
|
!ir2: ind
|
||||||
|
ir2: ir2
|
||||||
|
s1: ir2=ind
|
||||||
|
s2: typeset -n ir2
|
||||||
|
!ind[1]: 1
|
||||||
|
!ir2: ir2
|
||||||
|
ind[1]: e2
|
||||||
|
ir2: e3
|
||||||
|
---
|
||||||
|
name: nameref-2da
|
||||||
|
description:
|
||||||
|
Testsuite for nameref (bound variables)
|
||||||
|
Functions, argument given directly, after local
|
||||||
|
stdin:
|
||||||
|
function foo {
|
||||||
|
typeset bar=lokal baz=auch
|
||||||
|
typeset -n v=bar
|
||||||
|
print entering
|
||||||
|
print !v: ${!v}
|
||||||
|
print !bar: ${!bar}
|
||||||
|
print !baz: ${!baz}
|
||||||
|
print bar: $bar
|
||||||
|
print v: $v
|
||||||
|
v=123
|
||||||
|
print bar: $bar
|
||||||
|
print v: $v
|
||||||
|
print exiting
|
||||||
|
}
|
||||||
|
bar=global
|
||||||
|
print bar: $bar
|
||||||
|
foo bar
|
||||||
|
print bar: $bar
|
||||||
|
expected-stdout:
|
||||||
|
bar: global
|
||||||
|
entering
|
||||||
|
!v: bar
|
||||||
|
!bar: bar
|
||||||
|
!baz: baz
|
||||||
|
bar: lokal
|
||||||
|
v: lokal
|
||||||
|
bar: 123
|
||||||
|
v: 123
|
||||||
|
exiting
|
||||||
|
bar: global
|
||||||
|
---
|
||||||
|
22
eval.c
22
eval.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.68 2009/08/28 22:39:09 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.69 2009/09/06 17:42:12 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* string expansion
|
* string expansion
|
||||||
@ -1021,8 +1021,7 @@ varsub(Expand *xp, const char *sp, const char *word,
|
|||||||
if (!(vp->flag&ISSET))
|
if (!(vp->flag&ISSET))
|
||||||
continue;
|
continue;
|
||||||
XPput(wv, c == '!' ? shf_smprintf("%lu",
|
XPput(wv, c == '!' ? shf_smprintf("%lu",
|
||||||
vp->flag & AINDEX ?
|
arrayindex(vp)) :
|
||||||
(unsigned long)vp->ua.index : 0) :
|
|
||||||
str_val(vp));
|
str_val(vp));
|
||||||
}
|
}
|
||||||
if (XPsize(wv) == 0) {
|
if (XPsize(wv) == 0) {
|
||||||
@ -1037,14 +1036,27 @@ varsub(Expand *xp, const char *sp, const char *word,
|
|||||||
state = XARG;
|
state = XARG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*sp == '!' && sp[1])
|
|
||||||
return (-1);
|
|
||||||
/* Can't assign things like $! or $1 */
|
/* Can't assign things like $! or $1 */
|
||||||
if ((stype & 0x7f) == '=' &&
|
if ((stype & 0x7f) == '=' &&
|
||||||
ctype(*sp, C_VAR1 | C_DIGIT))
|
ctype(*sp, C_VAR1 | C_DIGIT))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
if (*sp == '!' && sp[1]) {
|
||||||
|
++sp;
|
||||||
|
xp->var = global(sp);
|
||||||
|
if (cstrchr(sp, '[')) {
|
||||||
|
if (xp->var->flag & ISSET)
|
||||||
|
xp->str = shf_smprintf("%lu",
|
||||||
|
arrayindex(xp->var));
|
||||||
|
else
|
||||||
|
xp->str = null;
|
||||||
|
} else if (xp->var->flag & ISSET)
|
||||||
|
xp->str = xp->var->name;
|
||||||
|
else
|
||||||
|
xp->str = "0"; /* ksh93 compat */
|
||||||
|
} else {
|
||||||
xp->var = global(sp);
|
xp->var = global(sp);
|
||||||
xp->str = str_val(xp->var);
|
xp->str = str_val(xp->var);
|
||||||
|
}
|
||||||
state = XSUB;
|
state = XSUB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
funcs.c
26
funcs.c
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.128 2009/08/30 21:02:00 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.129 2009/09/06 17:42:12 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -47,6 +47,8 @@ __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.128 2009/08/30 21:02:00 tg Exp $");
|
|||||||
#define c_ulimit c_label
|
#define c_ulimit c_label
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern uint8_t set_refflag;
|
||||||
|
|
||||||
/* A leading = means assignments before command are kept;
|
/* A leading = means assignments before command are kept;
|
||||||
* a leading * means a POSIX special builtin;
|
* a leading * means a POSIX special builtin;
|
||||||
* a leading + means a POSIX regular builtin
|
* a leading + means a POSIX regular builtin
|
||||||
@ -896,7 +898,7 @@ c_typeset(const char **wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* see comment below regarding possible opions */
|
/* see comment below regarding possible opions */
|
||||||
opts = istset ? "L#R#UZ#afi#lprtux" : "p";
|
opts = istset ? "L#R#UZ#afi#lnprtux" : "p";
|
||||||
|
|
||||||
fieldstr = basestr = NULL;
|
fieldstr = basestr = NULL;
|
||||||
builtin_opt.flags |= GF_PLUSOPT;
|
builtin_opt.flags |= GF_PLUSOPT;
|
||||||
@ -947,6 +949,9 @@ c_typeset(const char **wp)
|
|||||||
case 'l':
|
case 'l':
|
||||||
flag = LCASEV;
|
flag = LCASEV;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
set_refflag = (builtin_opt.info & GI_PLUS) ? 2 : 1;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* export, readonly: POSIX -p flag */
|
/* export, readonly: POSIX -p flag */
|
||||||
/* typeset: show values as well */
|
/* typeset: show values as well */
|
||||||
@ -995,13 +1000,14 @@ c_typeset(const char **wp)
|
|||||||
builtin_opt.optind++;
|
builtin_opt.optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func && ((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT))) {
|
if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) || set_refflag)) {
|
||||||
bi_errorf("only -t, -u and -x options may be used with -f");
|
bi_errorf("only -t, -u and -x options may be used with -f");
|
||||||
|
set_refflag = 0;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (wp[builtin_opt.optind]) {
|
if (wp[builtin_opt.optind]) {
|
||||||
/* Take care of exclusions.
|
/* Take care of exclusions.
|
||||||
* At this point, flags in fset are cleared in fclr and vise
|
* At this point, flags in fset are cleared in fclr and vice
|
||||||
* versa. This property should be preserved.
|
* versa. This property should be preserved.
|
||||||
*/
|
*/
|
||||||
if (fset & LCASEV) /* LCASEV has priority over UCASEV_AL */
|
if (fset & LCASEV) /* LCASEV has priority over UCASEV_AL */
|
||||||
@ -1015,8 +1021,8 @@ c_typeset(const char **wp)
|
|||||||
/* Setting these attributes clears the others, unless they
|
/* Setting these attributes clears the others, unless they
|
||||||
* are also set in this command
|
* are also set in this command
|
||||||
*/
|
*/
|
||||||
if (fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
|
if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
|
||||||
INTEGER | INT_U | INT_L))
|
INTEGER | INT_U | INT_L)) || set_refflag)
|
||||||
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
|
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
|
||||||
LCASEV | INTEGER | INT_U | INT_L);
|
LCASEV | INTEGER | INT_U | INT_L);
|
||||||
}
|
}
|
||||||
@ -1047,9 +1053,11 @@ c_typeset(const char **wp)
|
|||||||
"%s() %T\n", wp[i], f->val.t);
|
"%s() %T\n", wp[i], f->val.t);
|
||||||
} else if (!typeset(wp[i], fset, fclr, field, base)) {
|
} else if (!typeset(wp[i], fset, fclr, field, base)) {
|
||||||
bi_errorf("%s: not identifier", wp[i]);
|
bi_errorf("%s: not identifier", wp[i]);
|
||||||
|
set_refflag = 0;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
set_refflag = 0;
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1112,6 +1120,8 @@ c_typeset(const char **wp)
|
|||||||
* be suitable for re-entry...
|
* be suitable for re-entry...
|
||||||
*/
|
*/
|
||||||
shf_puts("typeset ", shl_stdout);
|
shf_puts("typeset ", shl_stdout);
|
||||||
|
if (((vp->flag&(ARRAY|ASSOC))==ASSOC))
|
||||||
|
shf_puts("-n ", shl_stdout);
|
||||||
if ((vp->flag&INTEGER))
|
if ((vp->flag&INTEGER))
|
||||||
shf_puts("-i ", shl_stdout);
|
shf_puts("-i ", shl_stdout);
|
||||||
if ((vp->flag&EXPORT))
|
if ((vp->flag&EXPORT))
|
||||||
@ -1160,9 +1170,7 @@ c_typeset(const char **wp)
|
|||||||
if ((vp->flag&ARRAY) && any_set)
|
if ((vp->flag&ARRAY) && any_set)
|
||||||
shprintf("%s[%lu]",
|
shprintf("%s[%lu]",
|
||||||
vp->name,
|
vp->name,
|
||||||
vp->flag & AINDEX ?
|
arrayindex(vp));
|
||||||
(unsigned long)vp->ua.index :
|
|
||||||
0);
|
|
||||||
else
|
else
|
||||||
shf_puts(vp->name, shl_stdout);
|
shf_puts(vp->name, shl_stdout);
|
||||||
if (thing == '-' && (vp->flag&ISSET)) {
|
if (thing == '-' && (vp->flag&ISSET)) {
|
||||||
|
3
main.c
3
main.c
@ -33,7 +33,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.143 2009/08/29 11:26:44 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.144 2009/09/06 17:42:13 tg Exp $");
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
@ -67,6 +67,7 @@ static const char *initcoms[] = {
|
|||||||
"autoload=typeset -fu",
|
"autoload=typeset -fu",
|
||||||
"functions=typeset -f",
|
"functions=typeset -f",
|
||||||
"history=fc -l",
|
"history=fc -l",
|
||||||
|
"nameref=typeset -n",
|
||||||
"nohup=nohup ",
|
"nohup=nohup ",
|
||||||
r_fc_e_,
|
r_fc_e_,
|
||||||
"source=PATH=$PATH:. command .",
|
"source=PATH=$PATH:. command .",
|
||||||
|
31
mksh.1
31
mksh.1
@ -1,4 +1,4 @@
|
|||||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.180 2009/09/05 17:12:49 tg Exp $
|
.\" $MirOS: src/bin/mksh/mksh.1,v 1.181 2009/09/06 17:42:13 tg Exp $
|
||||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
@ -48,7 +48,7 @@
|
|||||||
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
||||||
..
|
..
|
||||||
.\"-
|
.\"-
|
||||||
.Dd $Mdocdate: September 5 2009 $
|
.Dd $Mdocdate: September 6 2009 $
|
||||||
.Dt MKSH 1
|
.Dt MKSH 1
|
||||||
.Os MirBSD
|
.Os MirBSD
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -883,6 +883,7 @@ history=\*(aqfc \-l\*(aq
|
|||||||
integer=\*(aqtypeset \-i\*(aq
|
integer=\*(aqtypeset \-i\*(aq
|
||||||
local=\*(aqtypeset\*(aq
|
local=\*(aqtypeset\*(aq
|
||||||
login=\*(aqexec login\*(aq
|
login=\*(aqexec login\*(aq
|
||||||
|
nameref=\*(aqtypeset -n\*(aq
|
||||||
nohup=\*(aqnohup \*(aq
|
nohup=\*(aqnohup \*(aq
|
||||||
r=\*(aqfc \-e \-\*(aq
|
r=\*(aqfc \-e \-\*(aq
|
||||||
stop=\*(aqkill \-STOP\*(aq
|
stop=\*(aqkill \-STOP\*(aq
|
||||||
@ -1261,6 +1262,18 @@ of the string value of parameter
|
|||||||
The number of elements in the array
|
The number of elements in the array
|
||||||
.Ar name .
|
.Ar name .
|
||||||
.Pp
|
.Pp
|
||||||
|
.It Pf ${! Ns Ar name Ns }
|
||||||
|
The name of the variable referred to by
|
||||||
|
.Ar name .
|
||||||
|
This will be
|
||||||
|
.Ar name
|
||||||
|
except when
|
||||||
|
.Ar name
|
||||||
|
is a name reference (bound variable), created by the
|
||||||
|
.Ic nameref
|
||||||
|
command (which is an alias for
|
||||||
|
.Ic typeset Fl n ) .
|
||||||
|
.Pp
|
||||||
.It Pf ${! Ns Ar name Ns [*]}
|
.It Pf ${! Ns Ar name Ns [*]}
|
||||||
.It Pf ${! Ns Ar name Ns [@]}
|
.It Pf ${! Ns Ar name Ns [@]}
|
||||||
The names of indices (keys) in the array
|
The names of indices (keys) in the array
|
||||||
@ -4110,7 +4123,7 @@ A command that exits with a zero value.
|
|||||||
.Pp
|
.Pp
|
||||||
.It Xo
|
.It Xo
|
||||||
.Ic typeset
|
.Ic typeset
|
||||||
.Oo Op Ic +\-alprtUux
|
.Oo Op Ic +\-alpnrtUux
|
||||||
.Op Fl L Ns Op Ar n
|
.Op Fl L Ns Op Ar n
|
||||||
.Op Fl R Ns Op Ar n
|
.Op Fl R Ns Op Ar n
|
||||||
.Op Fl Z Ns Op Ar n
|
.Op Fl Z Ns Op Ar n
|
||||||
@ -4191,6 +4204,18 @@ All upper case characters in values are converted to lower case.
|
|||||||
when used with the
|
when used with the
|
||||||
.Fl i
|
.Fl i
|
||||||
option.)
|
option.)
|
||||||
|
.It Fl n
|
||||||
|
Create a bound variable (name reference): any access to the variable
|
||||||
|
.Ar name
|
||||||
|
will access the variable
|
||||||
|
.Ar value
|
||||||
|
in the current scope (this is different from
|
||||||
|
.At
|
||||||
|
.Nm ksh93 ! )
|
||||||
|
instead.
|
||||||
|
This can be used by functions to access variables whose names are
|
||||||
|
passed as parametres, instead of using
|
||||||
|
.Ic eval .
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Print complete
|
Print complete
|
||||||
.Ic typeset
|
.Ic typeset
|
||||||
|
6
sh.h
6
sh.h
@ -134,7 +134,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.337 2009/08/30 21:02:01 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.338 2009/09/06 17:42:14 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R39 2009/08/30"
|
#define MKSH_VERSION "R39 2009/08/30"
|
||||||
|
|
||||||
@ -906,6 +906,7 @@ struct tbl { /* table item */
|
|||||||
#define EXPRINEVAL BIT(23) /* contents currently being evaluated */
|
#define EXPRINEVAL BIT(23) /* contents currently being evaluated */
|
||||||
#define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */
|
#define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */
|
||||||
#define AINDEX BIT(25) /* array index >0 = ua.index filled in */
|
#define AINDEX BIT(25) /* array index >0 = ua.index filled in */
|
||||||
|
#define ASSOC BIT(26) /* ARRAY ? associative : reference */
|
||||||
/* flag bits used for taliases/builtins/aliases/keywords/functions */
|
/* flag bits used for taliases/builtins/aliases/keywords/functions */
|
||||||
#define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */
|
#define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */
|
||||||
#define FINUSE BIT(9) /* function being executed */
|
#define FINUSE BIT(9) /* function being executed */
|
||||||
@ -919,6 +920,9 @@ struct tbl { /* table item */
|
|||||||
#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL|\
|
#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL|\
|
||||||
LCASEV|UCASEV_AL|INT_U|INT_L)
|
LCASEV|UCASEV_AL|INT_U|INT_L)
|
||||||
|
|
||||||
|
#define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
|
||||||
|
(vp)->ua.index : 0))
|
||||||
|
|
||||||
/* command types */
|
/* command types */
|
||||||
#define CNONE 0 /* undefined */
|
#define CNONE 0 /* undefined */
|
||||||
#define CSHELL 1 /* built-in */
|
#define CSHELL 1 /* built-in */
|
||||||
|
65
var.c
65
var.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.86 2009/08/28 22:44:47 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.87 2009/09/06 17:42:15 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables
|
* Variables
|
||||||
@ -47,6 +47,8 @@ static const char *array_index_calc(const char *, bool *, uint32_t *);
|
|||||||
static int rnd_get(void);
|
static int rnd_get(void);
|
||||||
static void rnd_set(unsigned long);
|
static void rnd_set(unsigned long);
|
||||||
|
|
||||||
|
uint8_t set_refflag = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create a new block for function calls and simple commands
|
* create a new block for function calls and simple commands
|
||||||
* assume caller has allocated and set up e->loc
|
* assume caller has allocated and set up e->loc
|
||||||
@ -135,7 +137,7 @@ initvar(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Used to calculate an array index for global()/local(). Sets *arrayp to
|
/* Used to calculate an array index for global()/local(). Sets *arrayp to
|
||||||
* non-zero if this is an array, sets *valp to the array index, returns
|
* true if this is an array, sets *valp to the array index, returns
|
||||||
* the basename of the array.
|
* the basename of the array.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char *
|
||||||
@ -143,9 +145,39 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
|
|||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
int len;
|
int len;
|
||||||
|
char *ap = NULL;
|
||||||
|
|
||||||
*arrayp = false;
|
*arrayp = false;
|
||||||
|
redo_from_ref:
|
||||||
p = skip_varname(n, false);
|
p = skip_varname(n, false);
|
||||||
|
if (!set_refflag && (p != n) && ksh_isalphx(n[0])) {
|
||||||
|
struct block *l = e->loc;
|
||||||
|
struct tbl *vp;
|
||||||
|
char *vn;
|
||||||
|
uint32_t h;
|
||||||
|
|
||||||
|
strndupx(vn, n, p - n, ATEMP);
|
||||||
|
h = hash(vn);
|
||||||
|
/* check if this is a reference */
|
||||||
|
for (l = e->loc; ; l = l->next) {
|
||||||
|
if ((vp = ktsearch(&l->vars, vn, h)) != NULL)
|
||||||
|
break;
|
||||||
|
if (l->next == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
afree(vn, ATEMP);
|
||||||
|
if (vp && (vp->flag & (DEFINED|ASSOC|ARRAY)) ==
|
||||||
|
(DEFINED|ASSOC)) {
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
/* gotcha! */
|
||||||
|
cp = shf_smprintf("%s%s", str_val(vp), p);
|
||||||
|
afree(ap, ATEMP);
|
||||||
|
n = ap = cp;
|
||||||
|
goto redo_from_ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p != n && *p == '[' && (len = array_ref_len(p))) {
|
if (p != n && *p == '[' && (len = array_ref_len(p))) {
|
||||||
char *sub, *tmp;
|
char *sub, *tmp;
|
||||||
mksh_ari_t rval;
|
mksh_ari_t rval;
|
||||||
@ -646,6 +678,9 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
|||||||
if (*val == '[') {
|
if (*val == '[') {
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (set_refflag)
|
||||||
|
errorf("%s: reference variable cannot be an array",
|
||||||
|
var);
|
||||||
len = array_ref_len(val);
|
len = array_ref_len(val);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -680,6 +715,26 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
|||||||
|
|
||||||
vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) :
|
vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) :
|
||||||
global(tvar);
|
global(tvar);
|
||||||
|
if (set_refflag == 2 && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
|
||||||
|
vp->flag &= ~ASSOC;
|
||||||
|
else if (set_refflag == 1) {
|
||||||
|
if (vp->flag & ARRAY) {
|
||||||
|
struct tbl *a, *tmp;
|
||||||
|
|
||||||
|
/* Free up entire array */
|
||||||
|
for (a = vp->u.array; a; ) {
|
||||||
|
tmp = a;
|
||||||
|
a = a->u.array;
|
||||||
|
if (tmp->flag & ALLOC)
|
||||||
|
afree(tmp->val.s, tmp->areap);
|
||||||
|
afree(tmp, tmp->areap);
|
||||||
|
}
|
||||||
|
vp->u.array = NULL;
|
||||||
|
vp->flag &= ~ARRAY;
|
||||||
|
}
|
||||||
|
vp->flag |= ASSOC;
|
||||||
|
}
|
||||||
|
|
||||||
set &= ~(LOCAL|LOCAL_COPY);
|
set &= ~(LOCAL|LOCAL_COPY);
|
||||||
|
|
||||||
vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
|
vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
|
||||||
@ -803,8 +858,8 @@ unset(struct tbl *vp, int array_ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return a pointer to the first char past a legal variable name (returns the
|
/* return a pointer to the first char past a legal variable name (returns the
|
||||||
* argument if there is no legal name, returns * a pointer to the terminating
|
* argument if there is no legal name, returns a pointer to the terminating
|
||||||
* null if whole string is legal).
|
* NUL if whole string is legal).
|
||||||
*/
|
*/
|
||||||
const char *
|
const char *
|
||||||
skip_varname(const char *s, int aok)
|
skip_varname(const char *s, int aok)
|
||||||
@ -1240,7 +1295,7 @@ arraysearch(struct tbl *vp, uint32_t val)
|
|||||||
struct tbl *prev, *curr, *new;
|
struct tbl *prev, *curr, *new;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
vp->flag |= ARRAY|DEFINED;
|
vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC;
|
||||||
/* The table entry is always [0] */
|
/* The table entry is always [0] */
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
return (vp);
|
return (vp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user