summaryrefslogtreecommitdiff
path: root/Src/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/parse.c')
-rw-r--r--Src/parse.c290
1 files changed, 195 insertions, 95 deletions
diff --git a/Src/parse.c b/Src/parse.c
index 5f1303f1c..433efb94e 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -202,7 +202,7 @@ struct heredocs *hdocs;
* sublists is that they can be executed faster, see exec.c. In the
* parser, the test if a list can be simplified is done quite simply
* by passing a int* around which gets set to non-zero if the thing
- * just parsed is `complex', i.e. may need to be run by forking or
+ * just parsed is `cmplx', i.e. may need to be run by forking or
* some such.
*
* In each of the above, strings are encoded as one word code. For empty
@@ -375,6 +375,8 @@ init_parse(void)
/* Build eprog. */
+/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */
+
static void
copy_ecstr(Eccstr s, char *p)
{
@@ -386,24 +388,25 @@ copy_ecstr(Eccstr s, char *p)
}
static Eprog
-bld_eprog(void)
+bld_eprog(int heap)
{
Eprog ret;
int l;
ecadd(WCB_END());
- ret = (Eprog) zhalloc(sizeof(*ret));
+ ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret));
ret->len = ((ecnpats * sizeof(Patprog)) +
(ecused * sizeof(wordcode)) +
ecsoffs);
ret->npats = ecnpats;
- ret->nref = -1; /* Eprog is on the heap */
- ret->pats = (Patprog *) zhalloc(ret->len);
+ ret->nref = heap ? -1 : 1;
+ ret->pats = heap ? (Patprog *) zhalloc(ret->len) :
+ (Patprog *) zshcalloc(ret->len);
ret->prog = (Wordcode) (ret->pats + ecnpats);
ret->strs = (char *) (ret->prog + ecused);
ret->shf = NULL;
- ret->flags = EF_HEAP;
+ ret->flags = heap ? EF_HEAP : EF_REAL;
ret->dump = NULL;
for (l = 0; l < ecnpats; l++)
ret->pats[l] = dummy_patprog1;
@@ -455,7 +458,7 @@ parse_event(void)
clear_hdocs();
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/**/
@@ -534,7 +537,7 @@ parse_list(void)
yyerror(0);
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/*
@@ -553,7 +556,7 @@ parse_cond(void)
clear_hdocs();
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/* This adds a list wordcode. The important bit about this is that it also
@@ -561,9 +564,9 @@ parse_cond(void)
/**/
static void
-set_list_code(int p, int type, int complex)
+set_list_code(int p, int type, int cmplx)
{
- if (!complex && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
+ if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) {
int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE);
ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p);
@@ -578,9 +581,9 @@ set_list_code(int p, int type, int complex)
/**/
static void
-set_sublist_code(int p, int type, int flags, int skip, int complex)
+set_sublist_code(int p, int type, int flags, int skip, int cmplx)
{
- if (complex)
+ if (cmplx)
ecbuf[p] = WCB_SUBLIST(type, flags, skip);
else {
ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip);
@@ -594,7 +597,7 @@ set_sublist_code(int p, int type, int flags, int skip, int complex)
/**/
static int
-par_list(int *complex)
+par_list(int *cmplx)
{
int p, lp = -1, c;
@@ -607,10 +610,10 @@ par_list(int *complex)
c = 0;
if (par_sublist(&c)) {
- *complex |= c;
+ *cmplx |= c;
if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
if (tok != SEPER)
- *complex = 1;
+ *cmplx = 1;
set_list_code(p, ((tok == SEPER) ? Z_SYNC :
(tok == AMPER) ? Z_ASYNC :
(Z_ASYNC | Z_DISOWN)), c);
@@ -635,13 +638,13 @@ par_list(int *complex)
/**/
static int
-par_list1(int *complex)
+par_list1(int *cmplx)
{
int p = ecadd(0), c = 0;
if (par_sublist(&c)) {
set_list_code(p, (Z_SYNC | Z_END), c);
- *complex |= c;
+ *cmplx |= c;
return 1;
} else {
ecused--;
@@ -655,7 +658,7 @@ par_list1(int *complex)
/**/
static int
-par_sublist(int *complex)
+par_sublist(int *cmplx)
{
int f, p, c = 0;
@@ -664,7 +667,7 @@ par_sublist(int *complex)
if ((f = par_sublist2(&c)) != -1) {
int e = ecused;
- *complex |= c;
+ *cmplx |= c;
if (tok == DBAR || tok == DAMPER) {
enum lextok qtok = tok;
int sl;
@@ -673,7 +676,7 @@ par_sublist(int *complex)
zshlex();
while (tok == SEPER)
zshlex();
- sl = par_sublist(complex);
+ sl = par_sublist(cmplx);
set_sublist_code(p, (sl ? (qtok == DBAR ?
WC_SUBLIST_OR : WC_SUBLIST_AND) :
WC_SUBLIST_END),
@@ -694,20 +697,20 @@ par_sublist(int *complex)
/**/
static int
-par_sublist2(int *complex)
+par_sublist2(int *cmplx)
{
int f = 0;
if (tok == COPROC) {
- *complex = 1;
+ *cmplx = 1;
f |= WC_SUBLIST_COPROC;
zshlex();
} else if (tok == BANG) {
- *complex = 1;
+ *cmplx = 1;
f |= WC_SUBLIST_NOT;
zshlex();
}
- if (!par_pline(complex) && !f)
+ if (!par_pline(cmplx) && !f)
return -1;
return f;
@@ -719,19 +722,19 @@ par_sublist2(int *complex)
/**/
static int
-par_pline(int *complex)
+par_pline(int *cmplx)
{
int p;
zlong line = toklineno;
p = ecadd(0);
- if (!par_cmd(complex)) {
+ if (!par_cmd(cmplx, 0)) {
ecused--;
return 0;
}
if (tok == BAR) {
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_PIPE);
zshlex();
while (tok == SEPER)
@@ -739,7 +742,7 @@ par_pline(int *complex)
ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
ecispace(p + 1, 1);
ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(complex)) {
+ if (!par_pline(cmplx)) {
tok = LEXERR;
}
cmdpop();
@@ -755,7 +758,7 @@ par_pline(int *complex)
ecbuf[r + 1] = 2;
ecbuf[r + 2] = ecstrcode("1");
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_ERRPIPE);
zshlex();
while (tok == SEPER)
@@ -763,7 +766,7 @@ par_pline(int *complex)
ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
ecispace(p + 1, 1);
ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(complex)) {
+ if (!par_pline(cmplx)) {
tok = LEXERR;
}
cmdpop();
@@ -777,18 +780,20 @@ par_pline(int *complex)
/*
* cmd : { redir } ( for | case | if | while | repeat |
* subsh | funcdef | time | dinbrack | dinpar | simple ) { redir }
+ *
+ * zsh_construct is passed through to par_subsh(), q.v.
*/
/**/
static int
-par_cmd(int *complex)
+par_cmd(int *cmplx, int zsh_construct)
{
int r, nr = 0;
r = ecused;
if (IS_REDIROP(tok)) {
- *complex = 1;
+ *cmplx = 1;
while (IS_REDIROP(tok)) {
nr += par_redir(&r, NULL);
}
@@ -796,57 +801,57 @@ par_cmd(int *complex)
switch (tok) {
case FOR:
cmdpush(CS_FOR);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case FOREACH:
cmdpush(CS_FOREACH);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case SELECT:
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_SELECT);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case CASE:
cmdpush(CS_CASE);
- par_case(complex);
+ par_case(cmplx);
cmdpop();
break;
case IF:
- par_if(complex);
+ par_if(cmplx);
break;
case WHILE:
cmdpush(CS_WHILE);
- par_while(complex);
+ par_while(cmplx);
cmdpop();
break;
case UNTIL:
cmdpush(CS_UNTIL);
- par_while(complex);
+ par_while(cmplx);
cmdpop();
break;
case REPEAT:
cmdpush(CS_REPEAT);
- par_repeat(complex);
+ par_repeat(cmplx);
cmdpop();
break;
case INPAR:
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_SUBSH);
- par_subsh(complex);
+ par_subsh(cmplx, zsh_construct);
cmdpop();
break;
case INBRACE:
cmdpush(CS_CURSH);
- par_subsh(complex);
+ par_subsh(cmplx, zsh_construct);
cmdpop();
break;
case FUNC:
cmdpush(CS_FUNCDEF);
- par_funcdef(complex);
+ par_funcdef(cmplx);
cmdpop();
break;
case DINBRACK:
@@ -864,7 +869,7 @@ par_cmd(int *complex)
static int inpartime = 0;
if (!inpartime) {
- *complex = 1;
+ *cmplx = 1;
inpartime = 1;
par_time();
inpartime = 0;
@@ -877,13 +882,13 @@ par_cmd(int *complex)
{
int sr;
- if (!(sr = par_simple(complex, nr))) {
+ if (!(sr = par_simple(cmplx, nr))) {
if (!nr)
return 0;
} else {
/* Take account of redirections */
if (sr > 1) {
- *complex = 1;
+ *cmplx = 1;
r += sr - 1;
}
}
@@ -891,7 +896,7 @@ par_cmd(int *complex)
break;
}
if (IS_REDIROP(tok)) {
- *complex = 1;
+ *cmplx = 1;
while (IS_REDIROP(tok))
(void)par_redir(&r, NULL);
}
@@ -909,7 +914,7 @@ par_cmd(int *complex)
/**/
static void
-par_for(int *complex)
+par_for(int *cmplx)
{
int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT);
int type;
@@ -994,25 +999,28 @@ par_for(int *complex)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (csh || isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (unset(SHORTLOOPS)) {
YYERRORV(oecused);
} else
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[p] = (sel ?
WCB_SELECT(type, ecused - 1 - p) :
@@ -1028,7 +1036,7 @@ par_for(int *complex)
/**/
static void
-par_case(int *complex)
+par_case(int *cmplx)
{
int oecused = ecused, brflag, p, pp, n = 1, type;
int ona, onc;
@@ -1145,7 +1153,7 @@ par_case(int *complex)
pp = ecadd(0);
ecstr(str);
ecadd(ecnpats++);
- par_save_list(complex);
+ par_save_list(cmplx);
n++;
if (tok == SEMIAMP)
type = WC_CASE_AND;
@@ -1175,7 +1183,7 @@ par_case(int *complex)
/**/
static void
-par_if(int *complex)
+par_if(int *cmplx)
{
int oecused = ecused, p, pp, type, usebrace = 0;
enum lextok xtok;
@@ -1186,9 +1194,12 @@ par_if(int *complex)
for (;;) {
xtok = tok;
cmdpush(xtok == IF ? CS_IF : CS_ELIF);
- zshlex();
- if (xtok == FI)
+ if (xtok == FI) {
+ incmdpos = 0;
+ zshlex();
break;
+ }
+ zshlex();
if (xtok == ELSE)
break;
while (tok == SEPER)
@@ -1199,7 +1210,7 @@ par_if(int *complex)
}
pp = ecadd(0);
type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF);
- par_save_list(complex);
+ par_save_list(cmplx);
incmdpos = 1;
if (tok == ENDINPUT) {
cmdpop();
@@ -1214,7 +1225,7 @@ par_if(int *complex)
cmdpop();
cmdpush(nc);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
incmdpos = 1;
cmdpop();
@@ -1223,12 +1234,13 @@ par_if(int *complex)
cmdpop();
cmdpush(nc);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE) {
cmdpop();
YYERRORV(oecused);
}
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
+ /* command word (else) allowed to follow immediately */
zshlex();
incmdpos = 1;
if (tok == SEPER)
@@ -1240,7 +1252,7 @@ par_if(int *complex)
} else {
cmdpop();
cmdpush(nc);
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
incmdpos = 1;
break;
@@ -1254,18 +1266,19 @@ par_if(int *complex)
zshlex();
if (tok == INBRACE && usebrace) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE) {
cmdpop();
YYERRORV(oecused);
}
} else {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != FI) {
cmdpop();
YYERRORV(oecused);
}
}
+ incmdpos = 0;
ecbuf[pp] = WCB_IF(WC_IF_ELSE, ecused - 1 - pp);
zshlex();
cmdpop();
@@ -1280,31 +1293,33 @@ par_if(int *complex)
/**/
static void
-par_while(int *complex)
+par_while(int *cmplx)
{
int oecused = ecused, p;
int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE);
p = ecadd(0);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
incmdpos = 1;
while (tok == SEPER)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
zshlex();
@@ -1320,7 +1335,7 @@ par_while(int *complex)
/**/
static void
-par_repeat(int *complex)
+par_repeat(int *cmplx)
{
int oecused = ecused, p;
@@ -1337,25 +1352,27 @@ par_repeat(int *complex)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
zshlex();
} else if (unset(SHORTLOOPS)) {
YYERRORV(oecused);
} else
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[p] = WCB_REPEAT(ecused - 1 - p);
}
@@ -1363,11 +1380,15 @@ par_repeat(int *complex)
/*
* subsh : INPAR list OUTPAR |
* INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ]
+ *
+ * With zsh_construct non-zero, we're doing a zsh special in which
+ * the following token is not considered in command position. This
+ * is used for arguments of anonymous functions.
*/
/**/
static void
-par_subsh(int *complex)
+par_subsh(int *cmplx, int zsh_construct)
{
enum lextok otok = tok;
int oecused = ecused, p, pp;
@@ -1376,11 +1397,11 @@ par_subsh(int *complex)
/* Extra word only needed for always block */
pp = ecadd(0);
zshlex();
- par_list(complex);
+ par_list(cmplx);
ecadd(WCB_END());
if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE))
YYERRORV(oecused);
- incmdpos = 1;
+ incmdpos = !zsh_construct;
zshlex();
/* Optional always block. No intervening SEPERs allowed. */
@@ -1397,7 +1418,7 @@ par_subsh(int *complex)
cmdpush(CS_ALWAYS);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
while (tok == SEPER)
zshlex();
@@ -1420,7 +1441,7 @@ par_subsh(int *complex)
/**/
static void
-par_funcdef(int *complex)
+par_funcdef(int *cmplx)
{
int oecused = ecused, num = 0, onp, p, c = 0;
int so, oecssub = ecssub;
@@ -1502,7 +1523,8 @@ par_funcdef(int *complex)
num++;
zshlex();
}
- *complex = (num > 0);
+ if (num > 0)
+ *cmplx = 1;
ecbuf[parg] = ecused - parg; /*?*/
ecbuf[parg+1] = num;
}
@@ -1564,15 +1586,15 @@ par_dinbrack(void)
/**/
static int
-par_simple(int *complex, int nr)
+par_simple(int *cmplx, int nr)
{
int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
- int c = *complex, nrediradd, assignments = 0;
+ int c = *cmplx, nrediradd, assignments = 0;
r = ecused;
for (;;) {
if (tok == NOCORRECT) {
- *complex = c = 1;
+ *cmplx = c = 1;
nocorrect = 1;
} else if (tok == ENVSTRING) {
char *p, *name, *str;
@@ -1600,7 +1622,7 @@ par_simple(int *complex, int nr)
*/
if (p[1] == Inpar &&
(*p == Equals || *p == Inang || *p == OutangProc)) {
- *complex = 1;
+ *cmplx = 1;
break;
}
}
@@ -1612,10 +1634,10 @@ par_simple(int *complex, int nr)
int oldcmdpos = incmdpos, n, type2;
/*
- * We consider array setting complex because it can
+ * We consider array setting cmplx because it can
* contain process substitutions, which need a valid job.
*/
- *complex = c = 1;
+ *cmplx = c = 1;
p = ecadd(0);
incmdpos = 0;
if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') {
@@ -1647,7 +1669,7 @@ par_simple(int *complex, int nr)
if (tok == STRING) {
int redir_var = 0;
- *complex = 1;
+ *cmplx = 1;
incmdpos = 0;
if (!isset(IGNOREBRACES) && *tokstr == Inbrace)
@@ -1666,7 +1688,7 @@ par_simple(int *complex, int nr)
if (IS_REDIROP(tok) && tokfd == -1)
{
- *complex = c = 1;
+ *cmplx = c = 1;
nrediradd = par_redir(&r, idstring);
p += nrediradd;
sr += nrediradd;
@@ -1687,7 +1709,7 @@ par_simple(int *complex, int nr)
zshlex();
}
} else if (IS_REDIROP(tok)) {
- *complex = c = 1;
+ *cmplx = c = 1;
nrediradd = par_redir(&r, NULL);
p += nrediradd;
sr += nrediradd;
@@ -1702,7 +1724,7 @@ par_simple(int *complex, int nr)
if (assignments)
YYERROR(oecused);
- *complex = c;
+ *cmplx = c;
lineno = 0;
incmdpos = 1;
cmdpush(CS_FUNCDEF);
@@ -1745,10 +1767,21 @@ par_simple(int *complex, int nr)
sl = ecadd(0);
(void)ecadd(WCB_PIPE(WC_PIPE_END, 0));
- if (!par_cmd(&c)) {
+ if (!par_cmd(&c, argc == 0)) {
cmdpop();
YYERROR(oecused);
}
+ if (argc == 0) {
+ /*
+ * Anonymous function, possibly with arguments.
+ * N.B. for cmplx structures in particular
+ * ( ... ) we rely on lower level code doing this
+ * to get the immediately following word (the
+ * first token after the ")" has already been
+ * read).
+ */
+ incmdpos = 0;
+ }
set_sublist_code(sl, WC_SUBLIST_END, 0, ecused - 1 - sl, c);
set_list_code(ll, (Z_SYNC | Z_END), c);
@@ -1775,7 +1808,8 @@ par_simple(int *complex, int nr)
argc++;
zshlex();
}
- *complex = (argc > 0);
+ if (argc > 0)
+ *cmplx = 1;
ecbuf[parg] = ecused - parg; /*?*/
ecbuf[parg+1] = argc;
}
@@ -2542,6 +2576,73 @@ ecgetredirs(Estate s)
return ret;
}
+/*
+ * Copy the consecutive set of redirections in the state at s.
+ * Return NULL if none, else an Eprog consisting only of the
+ * redirections from permanently allocated memory.
+ *
+ * s is left in the state ready for whatever follows the redirections.
+ */
+
+/**/
+Eprog
+eccopyredirs(Estate s)
+{
+ Wordcode pc = s->pc;
+ wordcode code = *pc;
+ int ncode, ncodes = 0, r, type;
+
+ if (wc_code(code) != WC_REDIR)
+ return NULL;
+
+ init_parse();
+
+ while (wc_code(code) == WC_REDIR) {
+ type = WC_REDIR_TYPE(code);
+
+ DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH,
+ "unexpanded here document");
+
+ if (WC_REDIR_FROM_HEREDOC(code))
+ ncode = 5;
+ else
+ ncode = 3;
+ if (WC_REDIR_VARID(code))
+ ncode++;
+ pc += ncode;
+ ncodes += ncode;
+ code = *pc;
+ }
+ r = ecused;
+ ecispace(r, ncodes);
+
+ code = *s->pc;
+ while (wc_code(code) == WC_REDIR) {
+ s->pc++;
+
+ ecbuf[r++] = code;
+ /* fd1 */
+ ecbuf[r++] = *s->pc++;
+ /* name or HERE string */
+ /* No DUP needed as we'll copy into Eprog immediately below */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ if (WC_REDIR_FROM_HEREDOC(code))
+ {
+ /* terminator, raw */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ /* terminator, munged */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ }
+ if (WC_REDIR_VARID(code))
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+
+ code = *s->pc;
+ }
+
+ /* bld_eprog() appends a useful WC_END marker */
+ return bld_eprog(0);
+}
+
/**/
mod_export struct eprog dummy_eprog;
@@ -3534,4 +3635,3 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func)
}
return ret;
}
-