make this pass varexpand-substr-1 and ‘c’ of varexpand-substr-2
by actually using the lexer and parser for that
This commit is contained in:
parent
c9db9eb092
commit
26a6e5acc9
106
eval.c
106
eval.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.30 2007/07/01 15:39:22 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.31 2007/07/06 01:53:35 tg Exp $");
|
||||
|
||||
#ifdef MKSH_SMALL
|
||||
#define MKSH_NOPWNAM
|
||||
|
@ -311,9 +311,48 @@ expand(const char *cp, /* input word */
|
|||
if (stype)
|
||||
sp += slen;
|
||||
switch (stype & 0x7f) {
|
||||
case '0':
|
||||
/* XXX begin arithmetic eval. */
|
||||
break;
|
||||
case '0': {
|
||||
char *beg, *mid, *end, *stg;
|
||||
long from = 0, num = -1, flen;
|
||||
|
||||
/* ! DOBLANK,DOBRACE_,DOTILDE */
|
||||
f = DOPAT | (f&DONTRUNCOMMAND) |
|
||||
DOTEMP_;
|
||||
quote = 0;
|
||||
beg = wdcopy(sp, ATEMP);
|
||||
mid = beg + (wdscan(sp, ADELIM) - sp);
|
||||
mid[-2] = EOS;
|
||||
if (mid[-1] == /*{*/'}') {
|
||||
sp += mid - beg - 1;
|
||||
end = NULL;
|
||||
} else {
|
||||
end = mid +
|
||||
(wdscan(mid, ADELIM) - mid);
|
||||
end[-2] = EOS;
|
||||
sp += end - beg - 1;
|
||||
}
|
||||
evaluate(stg = wdstrip(beg), &from,
|
||||
KSH_UNWIND_ERROR, true);
|
||||
afree(stg, ATEMP);
|
||||
if (end) {
|
||||
evaluate(stg = wdstrip(mid),
|
||||
&num, KSH_UNWIND_ERROR, true);
|
||||
afree(stg, ATEMP);
|
||||
}
|
||||
afree(beg, ATEMP);
|
||||
beg = str_val(st->var);
|
||||
flen = strlen(beg);
|
||||
if (from < 0) {
|
||||
if (-from < flen)
|
||||
beg += flen + from;
|
||||
} else
|
||||
beg += from < flen ? from : flen;
|
||||
flen = strlen(beg);
|
||||
if (num < 0 || num > flen)
|
||||
num = flen;
|
||||
x.str = str_nsave(beg, num, ATEMP);
|
||||
goto do_CSUBST;
|
||||
}
|
||||
case '#':
|
||||
case '%':
|
||||
/* ! DOBLANK,DOBRACE_,DOTILDE */
|
||||
|
@ -365,6 +404,7 @@ expand(const char *cp, /* input word */
|
|||
continue;
|
||||
}
|
||||
case CSUBST: /* only get here if expanding word */
|
||||
do_CSUBST:
|
||||
sp++; /* ({) skip the } or x */
|
||||
tilde_ok = 0; /* in case of ${unset:-} */
|
||||
*dp = '\0';
|
||||
|
@ -427,38 +467,12 @@ expand(const char *cp, /* input word */
|
|||
(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;
|
||||
}
|
||||
dp = Xrestpos(ds, dp, st->base);
|
||||
type = XSUB;
|
||||
if (f&DOBLANK)
|
||||
doblank++;
|
||||
st = st->prev;
|
||||
continue;
|
||||
}
|
||||
st = st->prev;
|
||||
type = XBASE;
|
||||
|
@ -778,25 +792,9 @@ varsub(Expand *xp, const char *sp, const char *word,
|
|||
stype = 0x80;
|
||||
c = word[slen + 0] == CHAR ? word[slen + 1] : 0;
|
||||
}
|
||||
if (stype == 0x80 && (ksh_isdigit(c) || c == ':')) {
|
||||
const char *tp = word + slen + 2;
|
||||
bool had_colon = false;
|
||||
|
||||
if (stype == 0x80 && (ksh_isdigit(c) || c == '('/*)*/ ||
|
||||
(!c && word[slen] && word[slen] != CHAR))) {
|
||||
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;
|
||||
|
|
37
lex.c
37
lex.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.38 2007/07/05 23:48:53 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.39 2007/07/06 01:53:36 tg Exp $");
|
||||
|
||||
/* Structure to keep track of the lexing state and the various pieces of info
|
||||
* needed for each particular state. */
|
||||
|
@ -42,6 +42,13 @@ struct lex_state {
|
|||
#define ls_sletarray ls_info.u_sletarray
|
||||
} u_sletarray;
|
||||
|
||||
/* ADELIM */
|
||||
struct sadelim_info {
|
||||
unsigned char delimiter;
|
||||
unsigned char num;
|
||||
#define ls_sadelim ls_info.u_sadelim
|
||||
} u_sadelim;
|
||||
|
||||
Lex_state *base; /* used to point to next state block */
|
||||
} ls_info;
|
||||
};
|
||||
|
@ -155,6 +162,15 @@ yylex(int cf)
|
|||
((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
|
||||
Xcheck(ws, wp);
|
||||
switch (state) {
|
||||
case SADELIM:
|
||||
if (c == /*{*/ '}' || c == statep->ls_sadelim.delimiter) {
|
||||
*wp++ = ADELIM;
|
||||
*wp++ = c;
|
||||
if (c == /*{*/ '}' || --statep->ls_sadelim.num == 0)
|
||||
POP_STATE();
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case SBASE:
|
||||
if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
|
||||
*wp = EOS; /* temporary */
|
||||
|
@ -270,6 +286,25 @@ yylex(int cf)
|
|||
if (c == ':') {
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
c = getsc();
|
||||
if (c == ':') {
|
||||
*wp++ = CHAR;
|
||||
*wp++ = '0';
|
||||
*wp++ = ADELIM;
|
||||
*wp++ = ':';
|
||||
PUSH_STATE(SADELIM);
|
||||
statep->ls_sadelim.delimiter = ':';
|
||||
statep->ls_sadelim.num = 1;
|
||||
break;
|
||||
} else if (ksh_isdigit(c) ||
|
||||
c == '('/*)*/ ||
|
||||
c == '$' /* XXX what else? */) {
|
||||
/* substring subst. */
|
||||
ungetsc(c);
|
||||
PUSH_STATE(SADELIM);
|
||||
statep->ls_sadelim.delimiter = ':';
|
||||
statep->ls_sadelim.num = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If this is a trim operation,
|
||||
* treat (,|,) specially in STBRACE.
|
||||
|
|
4
sh.h
4
sh.h
|
@ -8,7 +8,7 @@
|
|||
/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
|
||||
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
|
||||
|
||||
#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.154 2007/07/01 21:47:08 tg Exp $"
|
||||
#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.155 2007/07/06 01:53:36 tg Exp $"
|
||||
#define MKSH_VERSION "R29 2007/07/01"
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
|
@ -904,6 +904,7 @@ struct op {
|
|||
#define OPAT 9 /* open pattern: *(, @(, etc. */
|
||||
#define SPAT 10 /* separate pattern: | */
|
||||
#define CPAT 11 /* close pattern: ) */
|
||||
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
|
||||
|
||||
/*
|
||||
* IO redirection
|
||||
|
@ -1116,6 +1117,7 @@ struct source {
|
|||
#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
|
||||
#define STBRACE 12 /* parsing ${..[#%]..} */
|
||||
#define SLETARRAY 13 /* inside =( ), just copy */
|
||||
#define SADELIM 14 /* like SBASE, looking for delimiter */
|
||||
|
||||
typedef union {
|
||||
int i;
|
||||
|
|
8
tree.c
8
tree.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.10 2007/05/13 17:51:24 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.11 2007/07/06 01:53:36 tg Exp $");
|
||||
|
||||
#define INDENT 4
|
||||
|
||||
|
@ -268,6 +268,7 @@ tputS(char *wp, struct shf *shf)
|
|||
switch ((c = *wp++)) {
|
||||
case EOS:
|
||||
return;
|
||||
case ADELIM:
|
||||
case CHAR:
|
||||
tputC(*wp++, shf);
|
||||
break;
|
||||
|
@ -484,6 +485,10 @@ wdscan(const char *wp, int c)
|
|||
switch (*wp++) {
|
||||
case EOS:
|
||||
return (wp);
|
||||
case ADELIM:
|
||||
if (c == ADELIM)
|
||||
return (wp + 1);
|
||||
/* FALLTHROUGH */
|
||||
case CHAR:
|
||||
case QCHAR:
|
||||
wp++;
|
||||
|
@ -546,6 +551,7 @@ wdstrip(const char *wp)
|
|||
switch ((c = *wp++)) {
|
||||
case EOS:
|
||||
return shf_sclose(&shf); /* null terminates */
|
||||
case ADELIM:
|
||||
case CHAR:
|
||||
case QCHAR:
|
||||
shf_putchar(*wp++, &shf);
|
||||
|
|
Loading…
Reference in New Issue