mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-08 18:18:02 +02:00
51483: Enable assignment and expansion of parameters with ksh-like namespace prefixes.
This commit is contained in:
parent
806d096b0e
commit
a9ba166216
9 changed files with 45 additions and 19 deletions
|
@ -1,5 +1,10 @@
|
||||||
2023-03-05 Bart Schaefer <schaefer@zsh.org>
|
2023-03-05 Bart Schaefer <schaefer@zsh.org>
|
||||||
|
|
||||||
|
* 51483: Src/Zle/compcore.c, Src/Zle/zle_tricky.c, Src/lex.c,
|
||||||
|
Src/params.c, Src/subst.c, Src/utils.c, Src/zsh.h, Src/ztype.h:
|
||||||
|
Enable assignment and expansion of parameters with ksh-like
|
||||||
|
namespace prefixes.
|
||||||
|
|
||||||
* unposted: Src/Modules/param_private.c: coverity memory leak
|
* unposted: Src/Modules/param_private.c: coverity memory leak
|
||||||
|
|
||||||
2023-02-28 Mikael Magnusson <mikachu@gmail.com>
|
2023-02-28 Mikael Magnusson <mikachu@gmail.com>
|
||||||
|
|
|
@ -1230,14 +1230,14 @@ check_param(char *s, int set, int test)
|
||||||
else if (idigit(*e))
|
else if (idigit(*e))
|
||||||
while (idigit(*e))
|
while (idigit(*e))
|
||||||
e++;
|
e++;
|
||||||
else if ((ie = itype_end(e, IIDENT, 0)) != e) {
|
else if ((ie = itype_end(e, INAMESPC, 0)) != e) {
|
||||||
do {
|
do {
|
||||||
e = ie;
|
e = ie;
|
||||||
if (comppatmatch && *comppatmatch &&
|
if (comppatmatch && *comppatmatch &&
|
||||||
(*e == Star || *e == Quest))
|
(*e == Star || *e == Quest))
|
||||||
ie = e + 1;
|
ie = e + 1;
|
||||||
else
|
else
|
||||||
ie = itype_end(e, IIDENT, 0);
|
ie = itype_end(e, INAMESPC, 0);
|
||||||
} while (ie != e);
|
} while (ie != e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -576,7 +576,7 @@ parambeg(char *s)
|
||||||
while (idigit(*e))
|
while (idigit(*e))
|
||||||
e++;
|
e++;
|
||||||
else
|
else
|
||||||
e = itype_end(e, IIDENT, 0);
|
e = itype_end(e, INAMESPC, 0);
|
||||||
|
|
||||||
/* Now make sure that the cursor is inside the name. */
|
/* Now make sure that the cursor is inside the name. */
|
||||||
if (offs <= e - s && offs >= b - s && n <= 0) {
|
if (offs <= e - s && offs >= b - s && n <= 0) {
|
||||||
|
@ -765,7 +765,7 @@ docomplete(int lst)
|
||||||
else if (idigit(*q))
|
else if (idigit(*q))
|
||||||
do q++; while (idigit(*q));
|
do q++; while (idigit(*q));
|
||||||
else
|
else
|
||||||
q = itype_end(q, IIDENT, 0);
|
q = itype_end(q, INAMESPC, 0);
|
||||||
sav = *q;
|
sav = *q;
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
if (zlemetacs - wb == q - s &&
|
if (zlemetacs - wb == q - s &&
|
||||||
|
@ -1497,7 +1497,7 @@ get_comp_string(void)
|
||||||
if (varq)
|
if (varq)
|
||||||
tt = clwords[clwpos];
|
tt = clwords[clwpos];
|
||||||
|
|
||||||
s = itype_end(tt, IIDENT, 0);
|
s = itype_end(tt, INAMESPC, 0);
|
||||||
sav = *s;
|
sav = *s;
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
zsfree(varname);
|
zsfree(varname);
|
||||||
|
|
|
@ -1230,7 +1230,7 @@ gettokstr(int c, int sub)
|
||||||
else {
|
else {
|
||||||
int sav = *lexbuf.ptr;
|
int sav = *lexbuf.ptr;
|
||||||
*lexbuf.ptr = '\0';
|
*lexbuf.ptr = '\0';
|
||||||
t = itype_end(t, IIDENT, 0);
|
t = itype_end(t, INAMESPC, 0);
|
||||||
if (t < lexbuf.ptr) {
|
if (t < lexbuf.ptr) {
|
||||||
skipparens(Inbrack, Outbrack, &t);
|
skipparens(Inbrack, Outbrack, &t);
|
||||||
} else {
|
} else {
|
||||||
|
|
11
Src/params.c
11
Src/params.c
|
@ -1223,7 +1223,7 @@ isident(char *s)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* Find the first character in `s' not in the iident type table */
|
/* Find the first character in `s' not in the iident type table */
|
||||||
ss = itype_end(s, IIDENT, 0);
|
ss = itype_end(s, INAMESPC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the next character is not [, then it is *
|
/* If the next character is not [, then it is *
|
||||||
|
@ -2086,6 +2086,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
|
||||||
char *s, *t, *ie;
|
char *s, *t, *ie;
|
||||||
char sav, c;
|
char sav, c;
|
||||||
int ppar = 0;
|
int ppar = 0;
|
||||||
|
int itype = (flags & SCANPM_NONAMESPC) ? IIDENT : INAMESPC;
|
||||||
|
|
||||||
s = t = *pptr;
|
s = t = *pptr;
|
||||||
|
|
||||||
|
@ -2095,7 +2096,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
|
||||||
else
|
else
|
||||||
ppar = *s++ - '0';
|
ppar = *s++ - '0';
|
||||||
}
|
}
|
||||||
else if ((ie = itype_end(s, IIDENT, 0)) != s)
|
else if ((ie = itype_end(s, itype, 0)) != s)
|
||||||
s = ie;
|
s = ie;
|
||||||
else if (c == Quest)
|
else if (c == Quest)
|
||||||
*s++ = '?';
|
*s++ = '?';
|
||||||
|
@ -2183,7 +2184,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
} else if (!(flags & SCANPM_ASSIGNING) && v->isarr &&
|
} else if (!(flags & SCANPM_ASSIGNING) && v->isarr &&
|
||||||
itype_end(t, IIDENT, 1) != t && isset(KSHARRAYS))
|
itype_end(t, INAMESPC, 1) != t && isset(KSHARRAYS))
|
||||||
v->end = 1, v->isarr = 0;
|
v->end = 1, v->isarr = 0;
|
||||||
}
|
}
|
||||||
if (!bracks && *s)
|
if (!bracks && *s)
|
||||||
|
@ -6196,7 +6197,7 @@ setscope(Param pm)
|
||||||
if (pm->node.flags & PM_NAMEREF) {
|
if (pm->node.flags & PM_NAMEREF) {
|
||||||
Param basepm;
|
Param basepm;
|
||||||
struct asgment stop;
|
struct asgment stop;
|
||||||
char *t = pm->u.str ? itype_end(pm->u.str, IIDENT, 0) : NULL;
|
char *t = pm->u.str ? itype_end(pm->u.str, INAMESPC, 0) : NULL;
|
||||||
|
|
||||||
/* Temporarily change nameref to array parameter itself */
|
/* Temporarily change nameref to array parameter itself */
|
||||||
if (t && *t == '[')
|
if (t && *t == '[')
|
||||||
|
@ -6277,7 +6278,7 @@ upscope(Param pm, int reflevel)
|
||||||
mod_export int
|
mod_export int
|
||||||
valid_refname(char *val)
|
valid_refname(char *val)
|
||||||
{
|
{
|
||||||
char *t = itype_end(val, IIDENT, 0);
|
char *t = itype_end(val, INAMESPC, 0);
|
||||||
|
|
||||||
if (*t != 0) {
|
if (*t != 0) {
|
||||||
if (*t == '[') {
|
if (*t == '[') {
|
||||||
|
|
15
Src/subst.c
15
Src/subst.c
|
@ -1870,7 +1870,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
* these later on, too.
|
* these later on, too.
|
||||||
*/
|
*/
|
||||||
c = *s;
|
c = *s;
|
||||||
if (itype_end(s, IIDENT, 1) == s && *s != '#' && c != Pound &&
|
if (itype_end(s, INAMESPC, 1) == s && *s != '#' && c != Pound &&
|
||||||
!IS_DASH(c) &&
|
!IS_DASH(c) &&
|
||||||
c != '!' && c != '$' && c != String && c != Qstring &&
|
c != '!' && c != '$' && c != String && c != Qstring &&
|
||||||
c != '?' && c != Quest &&
|
c != '?' && c != Quest &&
|
||||||
|
@ -2332,7 +2332,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
}
|
}
|
||||||
} else if ((c == '#' || c == Pound) &&
|
} else if ((c == '#' || c == Pound) &&
|
||||||
(inbrace || !isset(POSIXIDENTIFIERS)) &&
|
(inbrace || !isset(POSIXIDENTIFIERS)) &&
|
||||||
(itype_end(s+1, IIDENT, 0) != s + 1
|
(itype_end(s+1, INAMESPC, 0) != s + 1
|
||||||
|| (cc = s[1]) == '*' || cc == Star || cc == '@'
|
|| (cc = s[1]) == '*' || cc == Star || cc == '@'
|
||||||
|| cc == '?' || cc == Quest
|
|| cc == '?' || cc == Quest
|
||||||
|| cc == '$' || cc == String || cc == Qstring
|
|| cc == '$' || cc == String || cc == Qstring
|
||||||
|
@ -2369,8 +2369,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
* Try to handle this when parameter is named
|
* Try to handle this when parameter is named
|
||||||
* by (P) (second part of test).
|
* by (P) (second part of test).
|
||||||
*/
|
*/
|
||||||
if (itype_end(s+1, IIDENT, 0) != s+1 || (aspar && isstring(s[1]) &&
|
if (itype_end(s+1, INAMESPC, 0) != s+1 ||
|
||||||
(s[2] == Inbrace || s[2] == Inpar)))
|
(aspar && isstring(s[1]) &&
|
||||||
|
(s[2] == Inbrace || s[2] == Inpar)))
|
||||||
chkset = 1, s++;
|
chkset = 1, s++;
|
||||||
else if (!inbrace) {
|
else if (!inbrace) {
|
||||||
/* Special case for `$+' on its own --- leave unmodified */
|
/* Special case for `$+' on its own --- leave unmodified */
|
||||||
|
@ -2531,6 +2532,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
scanflags |= SCANPM_DQUOTED;
|
scanflags |= SCANPM_DQUOTED;
|
||||||
if (chkset)
|
if (chkset)
|
||||||
scanflags |= SCANPM_CHECKING;
|
scanflags |= SCANPM_CHECKING;
|
||||||
|
if (!inbrace)
|
||||||
|
scanflags |= SCANPM_NONAMESPC;
|
||||||
/*
|
/*
|
||||||
* Second argument: decide whether to use the subexpression or
|
* Second argument: decide whether to use the subexpression or
|
||||||
* the string next on the line as the parameter name.
|
* the string next on the line as the parameter name.
|
||||||
|
@ -3211,7 +3214,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
shortest = 0;
|
shortest = 0;
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
if (*itype_end(s, IIDENT, 0)) {
|
if (*itype_end(s, INAMESPC, 0)) {
|
||||||
untokenize(s);
|
untokenize(s);
|
||||||
zerr("not an identifier: %s", s);
|
zerr("not an identifier: %s", s);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3271,7 +3274,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
||||||
int intersect = (*s == '*' || *s == Star);
|
int intersect = (*s == '*' || *s == Star);
|
||||||
char **compare, **ap, **apsrc;
|
char **compare, **ap, **apsrc;
|
||||||
++s;
|
++s;
|
||||||
if (*itype_end(s, IIDENT, 0)) {
|
if (*itype_end(s, INAMESPC, 0)) {
|
||||||
untokenize(s);
|
untokenize(s);
|
||||||
zerr("not an identifier: %s", s);
|
zerr("not an identifier: %s", s);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
18
Src/utils.c
18
Src/utils.c
|
@ -3123,7 +3123,7 @@ spckword(char **s, int hist, int cmd, int ask)
|
||||||
|
|
||||||
if (**s == String && !*t) {
|
if (**s == String && !*t) {
|
||||||
guess = *s + 1;
|
guess = *s + 1;
|
||||||
if (itype_end(guess, IIDENT, 1) == guess)
|
if (itype_end(guess, INAMESPC, 1) == guess)
|
||||||
return;
|
return;
|
||||||
ic = String;
|
ic = String;
|
||||||
d = 100;
|
d = 100;
|
||||||
|
@ -4310,13 +4310,27 @@ wcsitype(wchar_t c, int itype)
|
||||||
* If "once" is set, just test the first character, i.e. (outptr !=
|
* If "once" is set, just test the first character, i.e. (outptr !=
|
||||||
* inptr) tests whether the first character is valid in an identifier.
|
* inptr) tests whether the first character is valid in an identifier.
|
||||||
*
|
*
|
||||||
* Currently this is only called with itype IIDENT, IUSER or ISEP.
|
* Currently called only with itype INAMESPC, IIDENT, IUSER or ISEP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
mod_export char *
|
mod_export char *
|
||||||
itype_end(const char *ptr, int itype, int once)
|
itype_end(const char *ptr, int itype, int once)
|
||||||
{
|
{
|
||||||
|
if (itype == INAMESPC) {
|
||||||
|
itype = IIDENT;
|
||||||
|
if (once == 0 && !isset(POSIXIDENTIFIERS)) {
|
||||||
|
/* Special case for names containing ".", ksh93 namespaces */
|
||||||
|
char *t = itype_end(ptr + (*ptr == '.'), itype, 0);
|
||||||
|
if (t > ptr+1) {
|
||||||
|
if (*t == '.')
|
||||||
|
return itype_end(t+1, itype, 0);
|
||||||
|
else
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
#ifdef MULTIBYTE_SUPPORT
|
||||||
if (isset(MULTIBYTE) &&
|
if (isset(MULTIBYTE) &&
|
||||||
(itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
|
(itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
|
||||||
|
|
|
@ -1963,6 +1963,8 @@ struct tieddata {
|
||||||
*/
|
*/
|
||||||
#define SCANPM_CHECKING (1<<10) /* Check if set, no need to create */
|
#define SCANPM_CHECKING (1<<10) /* Check if set, no need to create */
|
||||||
#define SCANPM_NOEXEC (1<<11) /* No command substitutions, etc. */
|
#define SCANPM_NOEXEC (1<<11) /* No command substitutions, etc. */
|
||||||
|
#define SCANPM_NONAMESPC (1<<12) /* namespace syntax not allowed */
|
||||||
|
|
||||||
/* "$foo[@]"-style substitution
|
/* "$foo[@]"-style substitution
|
||||||
* Only sign bit is significant
|
* Only sign bit is significant
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#define IWSEP (1 << 13)
|
#define IWSEP (1 << 13)
|
||||||
#define INULL (1 << 14)
|
#define INULL (1 << 14)
|
||||||
#define IPATTERN (1 << 15)
|
#define IPATTERN (1 << 15)
|
||||||
|
#define INAMESPC (1 << 16)
|
||||||
#define zistype(X,Y) (typtab[(unsigned char) (X)] & Y)
|
#define zistype(X,Y) (typtab[(unsigned char) (X)] & Y)
|
||||||
#define idigit(X) zistype(X,IDIGIT)
|
#define idigit(X) zistype(X,IDIGIT)
|
||||||
#define ialnum(X) zistype(X,IALNUM)
|
#define ialnum(X) zistype(X,IALNUM)
|
||||||
|
|
Loading…
Reference in a new issue