implement better SASPAREN handling (actually, reusable very good for the

case where SASPAREN→COMSUB downgrading is done) by “logging” input and
restarting from there if needed
This commit is contained in:
tg 2011-03-13 01:11:58 +00:00
parent 9b8fafb757
commit 5710e78857

134
lex.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.135 2011/03/12 23:16:51 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.136 2011/03/13 01:11:58 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -46,6 +46,12 @@ __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.135 2011/03/12 23:16:51 tg Exp $");
#define SHERESTRING 16 /* parsing <<< string */ #define SHERESTRING 16 /* parsing <<< string */
#define SINVALID 255 /* invalid state */ #define SINVALID 255 /* invalid state */
struct sretrace_info {
struct sretrace_info *next;
XString xs;
char *xp;
};
/* /*
* 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.
@ -54,7 +60,7 @@ typedef struct lex_state {
union { union {
/* point to the next state block */ /* point to the next state block */
struct lex_state *base; struct lex_state *base;
/* marks start of $(( in output string */ /* marks start of state output in output string */
int start; int start;
/* SBQUOTE: true if in double quotes: "`...`" */ /* SBQUOTE: true if in double quotes: "`...`" */
/* SEQUOTE: got NUL, ignore rest of string */ /* SEQUOTE: got NUL, ignore rest of string */
@ -83,6 +89,8 @@ typedef struct {
} State_info; } State_info;
static void readhere(struct ioword *); static void readhere(struct ioword *);
static void ungetsc(int);
static void ungetsc_(int);
static int getsc__(void); static int getsc__(void);
static void getsc_line(Source *); static void getsc_line(Source *);
static int getsc_bn(void); static int getsc_bn(void);
@ -90,7 +98,6 @@ static int s_get(void);
static void s_put(int); static void s_put(int);
static char *get_brace_var(XString *, char *); static char *get_brace_var(XString *, char *);
static bool arraysub(char **); static bool arraysub(char **);
static const char *ungetsc(int);
static void gethere(bool); static void gethere(bool);
static Lex_state *push_state_(State_info *, Lex_state *); static Lex_state *push_state_(State_info *, Lex_state *);
static Lex_state *pop_state_(State_info *, Lex_state *); static Lex_state *pop_state_(State_info *, Lex_state *);
@ -99,6 +106,7 @@ static int dopprompt(const char *, int, bool);
static int backslash_skip; static int backslash_skip;
static int ignore_backslash_newline; static int ignore_backslash_newline;
static struct sretrace_info *retrace_info = NULL;
short comsub_nesting_level = 0; short comsub_nesting_level = 0;
/* optimised getsc_bn() */ /* optimised getsc_bn() */
@ -109,25 +117,38 @@ short comsub_nesting_level = 0;
#define _getsc_() ((*source->str != '\0') && !(source->flags & SF_FIRST) \ #define _getsc_() ((*source->str != '\0') && !(source->flags & SF_FIRST) \
? *source->str++ : getsc__()) ? *source->str++ : getsc__())
/* retrace helper */
#define _getsc_r(carg) { \
int cev = (carg); \
struct sretrace_info *rp = retrace_info; \
\
while (rp) { \
Xcheck(rp->xs, rp->xp); \
*rp->xp++ = cev; \
rp = rp->next; \
} \
\
return (cev); \
}
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
static int getsc(void); static int getsc(void);
static int getsc_(void);
static int static int
getsc(void) getsc(void)
{ {
return (_getsc()); _getsc_r(_getsc());
}
static int
getsc_(void)
{
return (_getsc_());
} }
#else #else
/* !MKSH_SMALL: use them inline */ static int getsc_r(int);
#define getsc() _getsc()
#define getsc_() _getsc_() static int
getsc_r(int c)
{
_getsc_r(c);
}
#define getsc() getsc_r(_getsc())
#endif #endif
#define STATE_BSIZE 8 #define STATE_BSIZE 8
@ -136,13 +157,32 @@ getsc_(void)
if (++statep == state_info.end) \ if (++statep == state_info.end) \
statep = push_state_(&state_info, statep); \ statep = push_state_(&state_info, statep); \
state = statep->type = (s); \ state = statep->type = (s); \
} while (0) } while (/* CONSTCOND */ 0)
#define POP_STATE() do { \ #define POP_STATE() do { \
if (--statep == state_info.base) \ if (--statep == state_info.base) \
statep = pop_state_(&state_info, statep); \ statep = pop_state_(&state_info, statep); \
state = statep->type; \ state = statep->type; \
} while (0) } while (/* CONSTCOND */ 0)
#define PUSH_SRETRACE() do { \
struct sretrace_info *ri; \
\
statep->ls_start = Xsavepos(ws, wp); \
ri = alloc(sizeof(struct sretrace_info), ATEMP); \
Xinit(ri->xs, ri->xp, 64, ATEMP); \
ri->next = retrace_info; \
retrace_info = ri; \
} while (/* CONSTCOND */ 0)
#define POP_SRETRACE() do { \
wp = Xrestpos(ws, wp, statep->ls_start); \
*retrace_info->xp = '\0'; \
sp = Xstring(retrace_info->xs, retrace_info->xp); \
dp = (void *)retrace_info; \
retrace_info = retrace_info->next; \
afree(dp, ATEMP); \
} while (/* CONSTCOND */ 0)
/** /**
* Lexical analyser * Lexical analyser
@ -351,11 +391,11 @@ yylex(int cf)
if (c == '(') /*)*/ { if (c == '(') /*)*/ {
c = getsc(); c = getsc();
if (c == '(') /*)*/ { if (c == '(') /*)*/ {
*wp++ = EXPRSUB;
PUSH_STATE(SASPAREN); PUSH_STATE(SASPAREN);
statep->nparen = 2; statep->nparen = 2;
statep->ls_start = PUSH_SRETRACE();
Xsavepos(ws, wp); *retrace_info->xp++ = '(';
*wp++ = EXPRSUB;
} else { } else {
ungetsc(c); ungetsc(c);
subst_command: subst_command:
@ -498,7 +538,7 @@ yylex(int cf)
statep->ls_bool = false; statep->ls_bool = false;
s2 = statep; s2 = statep;
base = state_info.base; base = state_info.base;
while (1) { while (/* CONSTCOND */ 1) {
for (; s2 != base; s2--) { for (; s2 != base; s2--) {
if (s2->type == SDQUOTE) { if (s2->type == SDQUOTE) {
statep->ls_bool = true; statep->ls_bool = true;
@ -588,11 +628,16 @@ yylex(int cf)
statep->nparen--; statep->nparen--;
if (statep->nparen == 1) { if (statep->nparen == 1) {
/* end of EXPRSUB */ /* end of EXPRSUB */
*wp++ = EOS; POP_SRETRACE();
/* EOS == '\0', coincidentally */ POP_STATE();
if ((c2 = getsc()) == /*(*/')') { if ((c2 = getsc()) == /*(*/ ')') {
POP_STATE(); c = strlen(sp) - 2;
XcheckN(ws, wp, c);
memcpy(wp, sp + 1, c);
wp += c;
afree(sp, ATEMP);
*wp++ = '\0';
break; break;
} else { } else {
Source *s; Source *s;
@ -603,23 +648,18 @@ yylex(int cf)
* assume we were really * assume we were really
* parsing a $(...) expression * parsing a $(...) expression
*/ */
wp = Xrestpos(ws, wp, --wp;
statep->ls_start);
POP_STATE();
/* dp = $((blah))\0 */
dp = wdstrip(wp, true, false);
s = pushs(SREREAD, s = pushs(SREREAD,
source->areap); source->areap);
s->start = s->str = s->start = s->str =
(s->u.freeme = dp) + 2; s->u.freeme = sp;
dp[strlen(dp) - 1] = 0;
/* s->str = (blah)\0 */
s->next = source; s->next = source;
source = s; source = s;
goto subst_command; goto subst_command;
} }
} }
} }
goto Sbase2;
*wp++ = c; *wp++ = c;
break; break;
@ -754,7 +794,7 @@ yylex(int cf)
c = 0; c = 0;
goto Done; goto Done;
} }
} }
*wp++ = CHAR; *wp++ = CHAR;
*wp++ = c; *wp++ = c;
break; break;
@ -1395,7 +1435,7 @@ getsc_line(Source *s)
else else
s->line++; s->line++;
while (1) { while (/* CONSTCOND */ 1) {
char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf); char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
if (!p && shf_error(s->u.shf) && if (!p && shf_error(s->u.shf) &&
@ -1607,7 +1647,7 @@ get_brace_var(XString *wsp, char *wp)
char c; char c;
state = PS_INITIAL; state = PS_INITIAL;
while (1) { while (/* CONSTCOND */ 1) {
c = getsc(); c = getsc();
/* State machine to figure out where the variable part ends. */ /* State machine to figure out where the variable part ends. */
switch (state) { switch (state) {
@ -1695,14 +1735,21 @@ arraysub(char **strp)
} }
/* Unget a char: handles case when we are already at the start of the buffer */ /* Unget a char: handles case when we are already at the start of the buffer */
static const char * static void
ungetsc(int c) ungetsc(int c)
{ {
if (backslash_skip) if (backslash_skip)
backslash_skip--; backslash_skip--;
/* Don't unget EOF... */ /* Don't unget EOF... */
if (source->str == null && c == '\0') if (source->str == null && c == '\0')
return (source->str); return;
if (retrace_info && Xlength(retrace_info->xs, retrace_info->xp))
retrace_info->xp--;
ungetsc_(c);
}
static void
ungetsc_(int c)
{
if (source->str > source->start) if (source->str > source->start)
source->str--; source->str--;
else { else {
@ -1714,7 +1761,6 @@ ungetsc(int c)
s->next = source; s->next = source;
source = s; source = s;
} }
return (source->str);
} }
@ -1725,22 +1771,22 @@ getsc_bn(void)
int c, c2; int c, c2;
if (ignore_backslash_newline) if (ignore_backslash_newline)
return (getsc_()); return (_getsc_());
if (backslash_skip == 1) { if (backslash_skip == 1) {
backslash_skip = 2; backslash_skip = 2;
return (getsc_()); return (_getsc_());
} }
backslash_skip = 0; backslash_skip = 0;
while (1) { while (/* CONSTCOND */ 1) {
c = getsc_(); c = _getsc_();
if (c == '\\') { if (c == '\\') {
if ((c2 = getsc_()) == '\n') if ((c2 = _getsc_()) == '\n')
/* ignore the \newline; get the next char... */ /* ignore the \newline; get the next char... */
continue; continue;
ungetsc(c2); ungetsc_(c2);
backslash_skip = 1; backslash_skip = 1;
} }
return (c); return (c);