this is bash compatibility week, and by suggestion of actual users,

namely Dr. Robert “Pfeffer” Arnold (in this case, in FreeWRT), make
a half-completed attempt at implementing ${foo:2:3} substring evals
(of course, negatives can't work right now and that the numbers are
in face expressions is something I only read later too – this is to
be revisited later, but it's already late)

don't depend on this behaviour yet though

if someone wants to add more regression tests, feel free to…
This commit is contained in:
tg
2007-06-27 23:12:59 +00:00
parent 0675b8f25b
commit ca17798533
4 changed files with 135 additions and 9 deletions

61
eval.c
View File

@ -2,7 +2,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.28 2007/06/06 23:28:14 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.29 2007/06/27 23:12:58 tg Exp $");
#ifdef MKSH_SMALL
#define MKSH_NOPWNAM
@ -311,6 +311,9 @@ expand(const char *cp, /* input word */
if (stype)
sp += slen;
switch (stype & 0x7f) {
case '0':
/* XXX begin arithmetic eval. */
break;
case '#':
case '%':
/* ! DOBLANK,DOBRACE_,DOTILDE */
@ -423,6 +426,39 @@ expand(const char *cp, /* input word */
"parameter null or not set" :
(debunk(s, s, strlen(s) + 1), s));
}
case '0':
{
char i, *s = Xrestpos(ds, dp, st->base);
int from = 0, num = 0;
/* bool fromend = false; */
/* XXX use evaluate() from expr.c
XXX or directly parse as 2 exprs */
/* if (*s == '-') {
fromend = true;
++s;
} */
while ((i = *s++) && i != ':')
from = from * 10 + i - '0';
if (i == ':') while ((i = *s++))
num = num * 10 + i - '0';
else
num = -1;
/* if (fromend) {
int flen = strlen(x.str);
if (from < flen)
x.str += flen - from;
} else */
x.str += from;
from = strlen(x.str);
if (num < 0 || num > from)
num = from;
dp = Xstring(ds, dp);
XcheckN(ds, dp, num);
memcpy(dp, x.str, num);
dp += num;
}
}
st = st->prev;
type = XBASE;
@ -742,7 +778,26 @@ varsub(Expand *xp, const char *sp, const char *word,
stype = 0x80;
c = word[slen + 0] == CHAR ? word[slen + 1] : 0;
}
if (ctype(c, C_SUBOP1)) {
if (stype == 0x80 && (ksh_isdigit(c) || c == ':')) {
const char *tp = word + slen + 2;
bool had_colon = false;
stype |= '0';
/* syntax check: minus, digits, one colon, digits */
/* if (*tp == CHAR && tp[1] == '-')
tp += 2; */
while (*tp != EOS && *tp != CSUBST) {
if (*tp != CHAR)
return (-1);
if (!ksh_isdigit(tp[1])) {
if (!had_colon && tp[1] == ':')
had_colon = true;
else
return (-1);
}
tp += 2;
}
} else if (ctype(c, C_SUBOP1)) {
slen += 2;
stype |= c;
} else if (ctype(c, C_SUBOP2)) { /* Note: ksh88 allows :%, :%%, etc */
@ -820,7 +875,7 @@ varsub(Expand *xp, const char *sp, const char *word,
c = stype&0x7f;
/* test the compiler's code generator */
if (ctype(c, C_SUBOP2) ||
if (ctype(c, C_SUBOP2) || stype == (0x80 | '0') ||
(((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */
c == '=' || c == '-' || c == '?' : c == '+'))
state = XBASE; /* expand word instead of variable value */