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"
|
#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
|
#ifdef MKSH_SMALL
|
||||||
#define MKSH_NOPWNAM
|
#define MKSH_NOPWNAM
|
||||||
@ -311,9 +311,48 @@ expand(const char *cp, /* input word */
|
|||||||
if (stype)
|
if (stype)
|
||||||
sp += slen;
|
sp += slen;
|
||||||
switch (stype & 0x7f) {
|
switch (stype & 0x7f) {
|
||||||
case '0':
|
case '0': {
|
||||||
/* XXX begin arithmetic eval. */
|
char *beg, *mid, *end, *stg;
|
||||||
break;
|
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 '#':
|
||||||
case '%':
|
case '%':
|
||||||
/* ! DOBLANK,DOBRACE_,DOTILDE */
|
/* ! DOBLANK,DOBRACE_,DOTILDE */
|
||||||
@ -365,6 +404,7 @@ expand(const char *cp, /* input word */
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case CSUBST: /* only get here if expanding word */
|
case CSUBST: /* only get here if expanding word */
|
||||||
|
do_CSUBST:
|
||||||
sp++; /* ({) skip the } or x */
|
sp++; /* ({) skip the } or x */
|
||||||
tilde_ok = 0; /* in case of ${unset:-} */
|
tilde_ok = 0; /* in case of ${unset:-} */
|
||||||
*dp = '\0';
|
*dp = '\0';
|
||||||
@ -427,38 +467,12 @@ expand(const char *cp, /* input word */
|
|||||||
(debunk(s, s, strlen(s) + 1), s));
|
(debunk(s, s, strlen(s) + 1), s));
|
||||||
}
|
}
|
||||||
case '0':
|
case '0':
|
||||||
{
|
dp = Xrestpos(ds, dp, st->base);
|
||||||
char i, *s = Xrestpos(ds, dp, st->base);
|
type = XSUB;
|
||||||
int from = 0, num = 0;
|
if (f&DOBLANK)
|
||||||
/* bool fromend = false; */
|
doblank++;
|
||||||
|
st = st->prev;
|
||||||
/* XXX use evaluate() from expr.c
|
continue;
|
||||||
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;
|
st = st->prev;
|
||||||
type = XBASE;
|
type = XBASE;
|
||||||
@ -778,25 +792,9 @@ varsub(Expand *xp, const char *sp, const char *word,
|
|||||||
stype = 0x80;
|
stype = 0x80;
|
||||||
c = word[slen + 0] == CHAR ? word[slen + 1] : 0;
|
c = word[slen + 0] == CHAR ? word[slen + 1] : 0;
|
||||||
}
|
}
|
||||||
if (stype == 0x80 && (ksh_isdigit(c) || c == ':')) {
|
if (stype == 0x80 && (ksh_isdigit(c) || c == '('/*)*/ ||
|
||||||
const char *tp = word + slen + 2;
|
(!c && word[slen] && word[slen] != CHAR))) {
|
||||||
bool had_colon = false;
|
|
||||||
|
|
||||||
stype |= '0';
|
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)) {
|
} else if (ctype(c, C_SUBOP1)) {
|
||||||
slen += 2;
|
slen += 2;
|
||||||
stype |= c;
|
stype |= c;
|
||||||
|
37
lex.c
37
lex.c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
/* Structure to keep track of the lexing state and the various pieces of info
|
||||||
* needed for each particular state. */
|
* needed for each particular state. */
|
||||||
@ -42,6 +42,13 @@ struct lex_state {
|
|||||||
#define ls_sletarray ls_info.u_sletarray
|
#define ls_sletarray ls_info.u_sletarray
|
||||||
} 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 */
|
Lex_state *base; /* used to point to next state block */
|
||||||
} ls_info;
|
} ls_info;
|
||||||
};
|
};
|
||||||
@ -155,6 +162,15 @@ yylex(int cf)
|
|||||||
((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
|
((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
|
||||||
Xcheck(ws, wp);
|
Xcheck(ws, wp);
|
||||||
switch (state) {
|
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:
|
case SBASE:
|
||||||
if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
|
if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
|
||||||
*wp = EOS; /* temporary */
|
*wp = EOS; /* temporary */
|
||||||
@ -270,6 +286,25 @@ yylex(int cf)
|
|||||||
if (c == ':') {
|
if (c == ':') {
|
||||||
*wp++ = CHAR, *wp++ = c;
|
*wp++ = CHAR, *wp++ = c;
|
||||||
c = getsc();
|
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,
|
/* If this is a trim operation,
|
||||||
* treat (,|,) specially in STBRACE.
|
* 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: 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 $ */
|
/* $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"
|
#define MKSH_VERSION "R29 2007/07/01"
|
||||||
|
|
||||||
#if HAVE_SYS_PARAM_H
|
#if HAVE_SYS_PARAM_H
|
||||||
@ -904,6 +904,7 @@ struct op {
|
|||||||
#define OPAT 9 /* open pattern: *(, @(, etc. */
|
#define OPAT 9 /* open pattern: *(, @(, etc. */
|
||||||
#define SPAT 10 /* separate pattern: | */
|
#define SPAT 10 /* separate pattern: | */
|
||||||
#define CPAT 11 /* close pattern: ) */
|
#define CPAT 11 /* close pattern: ) */
|
||||||
|
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IO redirection
|
* IO redirection
|
||||||
@ -1116,6 +1117,7 @@ struct source {
|
|||||||
#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
|
#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
|
||||||
#define STBRACE 12 /* parsing ${..[#%]..} */
|
#define STBRACE 12 /* parsing ${..[#%]..} */
|
||||||
#define SLETARRAY 13 /* inside =( ), just copy */
|
#define SLETARRAY 13 /* inside =( ), just copy */
|
||||||
|
#define SADELIM 14 /* like SBASE, looking for delimiter */
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
int i;
|
int i;
|
||||||
|
8
tree.c
8
tree.c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
#define INDENT 4
|
||||||
|
|
||||||
@ -268,6 +268,7 @@ tputS(char *wp, struct shf *shf)
|
|||||||
switch ((c = *wp++)) {
|
switch ((c = *wp++)) {
|
||||||
case EOS:
|
case EOS:
|
||||||
return;
|
return;
|
||||||
|
case ADELIM:
|
||||||
case CHAR:
|
case CHAR:
|
||||||
tputC(*wp++, shf);
|
tputC(*wp++, shf);
|
||||||
break;
|
break;
|
||||||
@ -484,6 +485,10 @@ wdscan(const char *wp, int c)
|
|||||||
switch (*wp++) {
|
switch (*wp++) {
|
||||||
case EOS:
|
case EOS:
|
||||||
return (wp);
|
return (wp);
|
||||||
|
case ADELIM:
|
||||||
|
if (c == ADELIM)
|
||||||
|
return (wp + 1);
|
||||||
|
/* FALLTHROUGH */
|
||||||
case CHAR:
|
case CHAR:
|
||||||
case QCHAR:
|
case QCHAR:
|
||||||
wp++;
|
wp++;
|
||||||
@ -546,6 +551,7 @@ wdstrip(const char *wp)
|
|||||||
switch ((c = *wp++)) {
|
switch ((c = *wp++)) {
|
||||||
case EOS:
|
case EOS:
|
||||||
return shf_sclose(&shf); /* null terminates */
|
return shf_sclose(&shf); /* null terminates */
|
||||||
|
case ADELIM:
|
||||||
case CHAR:
|
case CHAR:
|
||||||
case QCHAR:
|
case QCHAR:
|
||||||
shf_putchar(*wp++, &shf);
|
shf_putchar(*wp++, &shf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user