This is an internally visible change - no effect visible to the
user is expected. With the previous commits to parser.c, we no longer need to handle reading here documents in the (massive) readtoken1() function. That allows its code to be simplified and made easier to read and understand (several goto's goto goto heaven. RIP) (from kre@)
This commit is contained in:
parent
f6e1dd671e
commit
21cf17379f
281
bin/sh/parser.c
281
bin/sh/parser.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parser.c,v 1.112 2016/03/27 14:40:20 christos Exp $ */
|
||||
/* $NetBSD: parser.c,v 1.113 2016/03/31 16:12:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: parser.c,v 1.112 2016/03/27 14:40:20 christos Exp $");
|
||||
__RCSID("$NetBSD: parser.c,v 1.113 2016/03/31 16:12:09 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -1460,7 +1460,7 @@ parseredir(const char *out, int c)
|
||||
STATIC int
|
||||
readtoken1(int firstc, char const *syn, int magicq)
|
||||
{
|
||||
int c = firstc;
|
||||
int c;
|
||||
char * out;
|
||||
int len;
|
||||
struct nodelist *bqlist;
|
||||
@ -1484,161 +1484,160 @@ readtoken1(int firstc, char const *syn, int magicq)
|
||||
parenlevel = 0;
|
||||
|
||||
STARTSTACKSTR(out);
|
||||
loop: { /* for each line, until end of word */
|
||||
for (;;) { /* until end of line or end of word */
|
||||
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
|
||||
switch(syntax[c]) {
|
||||
case CNL: /* '\n' */
|
||||
if (syntax == BASESYNTAX)
|
||||
goto endword; /* exit outer loop */
|
||||
USTPUTC(c, out);
|
||||
|
||||
for (c = firstc ;; c = pgetc_macro()) { /* until of token */
|
||||
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
|
||||
switch (syntax[c]) {
|
||||
case CNL: /* '\n' */
|
||||
if (syntax == BASESYNTAX)
|
||||
break; /* exit loop */
|
||||
USTPUTC(c, out);
|
||||
plinno++;
|
||||
if (doprompt)
|
||||
setprompt(2);
|
||||
else
|
||||
setprompt(0);
|
||||
continue;
|
||||
|
||||
case CWORD:
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
case CCTL:
|
||||
if (!magicq || ISDBLQUOTE())
|
||||
USTPUTC(CTLESC, out);
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
case CBACK: /* backslash */
|
||||
c = pgetc();
|
||||
if (c == PEOF) {
|
||||
USTPUTC('\\', out);
|
||||
pungetc();
|
||||
continue;
|
||||
}
|
||||
if (c == '\n') {
|
||||
plinno++;
|
||||
if (doprompt)
|
||||
setprompt(2);
|
||||
else
|
||||
setprompt(0);
|
||||
c = pgetc();
|
||||
goto loop; /* continue outer loop */
|
||||
case CWORD:
|
||||
continue;
|
||||
}
|
||||
quotef = 1; /* current token is quoted */
|
||||
if (ISDBLQUOTE() && c != '\\' && c != '`' &&
|
||||
c != '$' && (c != '"' || magicq))
|
||||
USTPUTC('\\', out);
|
||||
if (SQSYNTAX[c] == CCTL)
|
||||
USTPUTC(CTLESC, out);
|
||||
else if (!magicq) {
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
case CCTL:
|
||||
if (!magicq || ISDBLQUOTE())
|
||||
USTPUTC(CTLESC, out);
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
case CBACK: /* backslash */
|
||||
c = pgetc();
|
||||
if (c == PEOF) {
|
||||
USTPUTC('\\', out);
|
||||
pungetc();
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
plinno++;
|
||||
if (doprompt)
|
||||
setprompt(2);
|
||||
else
|
||||
setprompt(0);
|
||||
break;
|
||||
}
|
||||
quotef = 1;
|
||||
if (ISDBLQUOTE() && c != '\\' &&
|
||||
c != '`' && c != '$' &&
|
||||
(c != '"' || magicq))
|
||||
USTPUTC('\\', out);
|
||||
if (SQSYNTAX[c] == CCTL)
|
||||
USTPUTC(CTLESC, out);
|
||||
else if (!magicq) {
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
USTPUTC(c, out);
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
break;
|
||||
}
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
case CSQUOTE:
|
||||
if (syntax != SQSYNTAX) {
|
||||
if (!magicq)
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
quotef = 1;
|
||||
TS_PUSH();
|
||||
syntax = SQSYNTAX;
|
||||
quoted = SQ;
|
||||
break;
|
||||
}
|
||||
if (magicq && arinest == 0 && varnest == 0) {
|
||||
/* Ignore inside quoted here document */
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
}
|
||||
/* End of single quotes... */
|
||||
TS_POP();
|
||||
if (syntax == BASESYNTAX && varnest != 0)
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
break;
|
||||
case CDQUOTE:
|
||||
if (magicq && arinest == 0 && varnest == 0) {
|
||||
/* Ignore inside here document */
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
case CSQUOTE:
|
||||
if (syntax != SQSYNTAX) {
|
||||
if (!magicq)
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
quotef = 1;
|
||||
if (arinest) {
|
||||
if (ISDBLQUOTE()) {
|
||||
TS_POP();
|
||||
} else {
|
||||
TS_PUSH();
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (magicq)
|
||||
break;
|
||||
TS_PUSH();
|
||||
syntax = SQSYNTAX;
|
||||
quoted = SQ;
|
||||
continue;
|
||||
}
|
||||
if (magicq && arinest == 0 && varnest == 0) {
|
||||
/* Ignore inside quoted here document */
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
}
|
||||
/* End of single quotes... */
|
||||
TS_POP();
|
||||
if (syntax == BASESYNTAX && varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
continue;
|
||||
case CDQUOTE:
|
||||
if (magicq && arinest == 0 && varnest == 0) {
|
||||
/* Ignore inside here document */
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
}
|
||||
quotef = 1;
|
||||
if (arinest) {
|
||||
if (ISDBLQUOTE()) {
|
||||
TS_POP();
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
} else {
|
||||
TS_PUSH();
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
break;
|
||||
case CVAR: /* '$' */
|
||||
PARSESUB(); /* parse substitution */
|
||||
break;
|
||||
case CENDVAR: /* CLOSEBRACE */
|
||||
if (varnest > 0 && !ISDBLQUOTE()) {
|
||||
TS_POP();
|
||||
USTPUTC(CTLENDVAR, out);
|
||||
} else {
|
||||
USTPUTC(c, out);
|
||||
}
|
||||
break;
|
||||
case CLP: /* '(' in arithmetic */
|
||||
parenlevel++;
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
case CRP: /* ')' in arithmetic */
|
||||
if (parenlevel > 0) {
|
||||
USTPUTC(c, out);
|
||||
--parenlevel;
|
||||
} else {
|
||||
if (pgetc() == ')') {
|
||||
if (--arinest == 0) {
|
||||
TS_POP();
|
||||
USTPUTC(CTLENDARI, out);
|
||||
} else
|
||||
USTPUTC(')', out);
|
||||
} else {
|
||||
/*
|
||||
* unbalanced parens
|
||||
* (don't 2nd guess - no error)
|
||||
*/
|
||||
pungetc();
|
||||
USTPUTC(')', out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CBQUOTE: /* '`' */
|
||||
out = parsebackq(stack, out, &bqlist, 1);
|
||||
break;
|
||||
case CEOF:
|
||||
goto endword; /* exit outer loop */
|
||||
default:
|
||||
if (varnest == 0 && !ISDBLQUOTE())
|
||||
goto endword; /* exit outer loop */
|
||||
continue;
|
||||
}
|
||||
if (magicq)
|
||||
continue;
|
||||
if (ISDBLQUOTE()) {
|
||||
TS_POP();
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
} else {
|
||||
TS_PUSH();
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
continue;
|
||||
case CVAR: /* '$' */
|
||||
PARSESUB(); /* parse substitution */
|
||||
continue;
|
||||
case CENDVAR: /* CLOSEBRACE */
|
||||
if (varnest > 0 && !ISDBLQUOTE()) {
|
||||
TS_POP();
|
||||
USTPUTC(CTLENDVAR, out);
|
||||
} else {
|
||||
USTPUTC(c, out);
|
||||
}
|
||||
c = pgetc_macro();
|
||||
continue;
|
||||
case CLP: /* '(' in arithmetic */
|
||||
parenlevel++;
|
||||
USTPUTC(c, out);
|
||||
continue;;
|
||||
case CRP: /* ')' in arithmetic */
|
||||
if (parenlevel > 0) {
|
||||
USTPUTC(c, out);
|
||||
--parenlevel;
|
||||
} else {
|
||||
if (pgetc() == ')') {
|
||||
if (--arinest == 0) {
|
||||
TS_POP();
|
||||
USTPUTC(CTLENDARI, out);
|
||||
} else
|
||||
USTPUTC(')', out);
|
||||
} else {
|
||||
/*
|
||||
* unbalanced parens
|
||||
* (don't 2nd guess - no error)
|
||||
*/
|
||||
pungetc();
|
||||
USTPUTC(')', out);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
case CBQUOTE: /* '`' */
|
||||
out = parsebackq(stack, out, &bqlist, 1);
|
||||
continue;
|
||||
case CEOF: /* --> c == PEOF */
|
||||
break; /* will exit loop */
|
||||
default:
|
||||
if (varnest == 0 && !ISDBLQUOTE())
|
||||
break; /* exit loop */
|
||||
USTPUTC(c, out);
|
||||
continue;
|
||||
}
|
||||
break; /* break from switch -> break from for loop too */
|
||||
}
|
||||
endword:
|
||||
|
||||
if (syntax == ARISYNTAX) {
|
||||
cleanup_state_stack(stack);
|
||||
synerror("Missing '))'");
|
||||
@ -1653,13 +1652,14 @@ endword:
|
||||
/* { */
|
||||
synerror("Missing '}'");
|
||||
}
|
||||
|
||||
USTPUTC('\0', out);
|
||||
len = out - stackblock();
|
||||
out = stackblock();
|
||||
|
||||
if (!magicq) {
|
||||
if ((c == '<' || c == '>')
|
||||
&& quotef == 0
|
||||
&& (*out == '\0' || is_number(out))) {
|
||||
&& quotef == 0 && (*out == '\0' || is_number(out))) {
|
||||
parseredir(out, c);
|
||||
cleanup_state_stack(stack);
|
||||
return lasttoken = TREDIR;
|
||||
@ -1667,6 +1667,7 @@ endword:
|
||||
pungetc();
|
||||
}
|
||||
}
|
||||
|
||||
quoteflag = quotef;
|
||||
backquotelist = bqlist;
|
||||
grabstackblock(len);
|
||||
|
Loading…
Reference in New Issue
Block a user