1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-05-20 23:41:27 +02:00

51483: Enable assignment and expansion of parameters with ksh-like namespace prefixes.

This commit is contained in:
Bart Schaefer 2023-03-05 14:03:42 -08:00
parent 806d096b0e
commit a9ba166216
9 changed files with 45 additions and 19 deletions

View file

@ -1,5 +1,10 @@
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
2023-02-28 Mikael Magnusson <mikachu@gmail.com>

View file

@ -1230,14 +1230,14 @@ check_param(char *s, int set, int test)
else if (idigit(*e))
while (idigit(*e))
e++;
else if ((ie = itype_end(e, IIDENT, 0)) != e) {
else if ((ie = itype_end(e, INAMESPC, 0)) != e) {
do {
e = ie;
if (comppatmatch && *comppatmatch &&
(*e == Star || *e == Quest))
ie = e + 1;
else
ie = itype_end(e, IIDENT, 0);
ie = itype_end(e, INAMESPC, 0);
} while (ie != e);
}

View file

@ -576,7 +576,7 @@ parambeg(char *s)
while (idigit(*e))
e++;
else
e = itype_end(e, IIDENT, 0);
e = itype_end(e, INAMESPC, 0);
/* Now make sure that the cursor is inside the name. */
if (offs <= e - s && offs >= b - s && n <= 0) {
@ -765,7 +765,7 @@ docomplete(int lst)
else if (idigit(*q))
do q++; while (idigit(*q));
else
q = itype_end(q, IIDENT, 0);
q = itype_end(q, INAMESPC, 0);
sav = *q;
*q = '\0';
if (zlemetacs - wb == q - s &&
@ -1497,7 +1497,7 @@ get_comp_string(void)
if (varq)
tt = clwords[clwpos];
s = itype_end(tt, IIDENT, 0);
s = itype_end(tt, INAMESPC, 0);
sav = *s;
*s = '\0';
zsfree(varname);

View file

@ -1230,7 +1230,7 @@ gettokstr(int c, int sub)
else {
int sav = *lexbuf.ptr;
*lexbuf.ptr = '\0';
t = itype_end(t, IIDENT, 0);
t = itype_end(t, INAMESPC, 0);
if (t < lexbuf.ptr) {
skipparens(Inbrack, Outbrack, &t);
} else {

View file

@ -1223,7 +1223,7 @@ isident(char *s)
break;
} else {
/* 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 *
@ -2086,6 +2086,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
char *s, *t, *ie;
char sav, c;
int ppar = 0;
int itype = (flags & SCANPM_NONAMESPC) ? IIDENT : INAMESPC;
s = t = *pptr;
@ -2095,7 +2096,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
else
ppar = *s++ - '0';
}
else if ((ie = itype_end(s, IIDENT, 0)) != s)
else if ((ie = itype_end(s, itype, 0)) != s)
s = ie;
else if (c == Quest)
*s++ = '?';
@ -2183,7 +2184,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
return v;
}
} 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;
}
if (!bracks && *s)
@ -6196,7 +6197,7 @@ setscope(Param pm)
if (pm->node.flags & PM_NAMEREF) {
Param basepm;
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 */
if (t && *t == '[')
@ -6277,7 +6278,7 @@ upscope(Param pm, int reflevel)
mod_export int
valid_refname(char *val)
{
char *t = itype_end(val, IIDENT, 0);
char *t = itype_end(val, INAMESPC, 0);
if (*t != 0) {
if (*t == '[') {

View file

@ -1870,7 +1870,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
* these later on, too.
*/
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) &&
c != '!' && c != '$' && c != String && c != Qstring &&
c != '?' && c != Quest &&
@ -2332,7 +2332,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
}
} else if ((c == '#' || c == Pound) &&
(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 == '?' || cc == Quest
|| 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
* by (P) (second part of test).
*/
if (itype_end(s+1, IIDENT, 0) != s+1 || (aspar && isstring(s[1]) &&
(s[2] == Inbrace || s[2] == Inpar)))
if (itype_end(s+1, INAMESPC, 0) != s+1 ||
(aspar && isstring(s[1]) &&
(s[2] == Inbrace || s[2] == Inpar)))
chkset = 1, s++;
else if (!inbrace) {
/* 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;
if (chkset)
scanflags |= SCANPM_CHECKING;
if (!inbrace)
scanflags |= SCANPM_NONAMESPC;
/*
* Second argument: decide whether to use the subexpression or
* 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;
++s;
}
if (*itype_end(s, IIDENT, 0)) {
if (*itype_end(s, INAMESPC, 0)) {
untokenize(s);
zerr("not an identifier: %s", s);
return NULL;
@ -3271,7 +3274,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
int intersect = (*s == '*' || *s == Star);
char **compare, **ap, **apsrc;
++s;
if (*itype_end(s, IIDENT, 0)) {
if (*itype_end(s, INAMESPC, 0)) {
untokenize(s);
zerr("not an identifier: %s", s);
return NULL;

View file

@ -3123,7 +3123,7 @@ spckword(char **s, int hist, int cmd, int ask)
if (**s == String && !*t) {
guess = *s + 1;
if (itype_end(guess, IIDENT, 1) == guess)
if (itype_end(guess, INAMESPC, 1) == guess)
return;
ic = String;
d = 100;
@ -4310,13 +4310,27 @@ wcsitype(wchar_t c, int itype)
* If "once" is set, just test the first character, i.e. (outptr !=
* 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 *
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
if (isset(MULTIBYTE) &&
(itype != IIDENT || !isset(POSIXIDENTIFIERS))) {

View file

@ -1963,6 +1963,8 @@ struct tieddata {
*/
#define SCANPM_CHECKING (1<<10) /* Check if set, no need to create */
#define SCANPM_NOEXEC (1<<11) /* No command substitutions, etc. */
#define SCANPM_NONAMESPC (1<<12) /* namespace syntax not allowed */
/* "$foo[@]"-style substitution
* Only sign bit is significant
*/

View file

@ -43,6 +43,7 @@
#define IWSEP (1 << 13)
#define INULL (1 << 14)
#define IPATTERN (1 << 15)
#define INAMESPC (1 << 16)
#define zistype(X,Y) (typtab[(unsigned char) (X)] & Y)
#define idigit(X) zistype(X,IDIGIT)
#define ialnum(X) zistype(X,IALNUM)