replace the code related to << changes and <<< with cleaner code,

fixing a few bugs also (including new testcases, except x=<< issue)
This commit is contained in:
tg 2015-09-06 19:47:01 +00:00
parent 0f6aa7eaab
commit ed5cb56849
7 changed files with 63 additions and 97 deletions

11
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.706 2015/09/05 20:20:42 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.707 2015/09/06 19:46:56 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R51 2015/09/05 @(#)MIRBSD KSH R51 2015/09/06
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R51 2015/09/05 @(#)LEGACY KSH R51 2015/09/06
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -2325,6 +2325,8 @@ stdin:
tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<\$bar tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<\$bar
tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<-foo tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<-foo
tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<"$(echo "foo bar")" tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<"$(echo "foo bar")"
tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<"A $(echo "foo bar") B"
tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <<<\$b\$b$bar
expected-stdout: expected-stdout:
sbb sbb
sbb sbb
@ -2334,6 +2336,9 @@ expected-stdout:
$one $one
-sbb -sbb
sbb one sbb one
A sbb one B
$o$oone
onm
--- ---
name: heredoc-9b name: heredoc-9b
description: description:

4
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.171 2015/09/05 19:19:02 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.172 2015/09/06 19:46:59 tg Exp $");
/* /*
* string expansion * string expansion
@ -919,6 +919,8 @@ expand(
(word == IFS_IWS || word == IFS_NWS) && (word == IFS_IWS || word == IFS_NWS) &&
!ctype(c, C_IFSWS))) { !ctype(c, C_IFSWS))) {
emit_word: emit_word:
if (f & DOHERESTR)
*dp++ = '\n';
*dp++ = '\0'; *dp++ = '\0';
cp = Xclose(ds, dp); cp = Xclose(ds, dp);
if (fdo & DOBRACE) if (fdo & DOBRACE)

16
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.162 2015/09/05 19:19:03 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.163 2015/09/06 19:46:59 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -1518,9 +1518,9 @@ iosetup(struct ioword *iop, struct tbl *tp)
* unquoted, the string is expanded first. * unquoted, the string is expanded first.
*/ */
static int static int
hereinval(const char *content, int sub, char **resbuf, struct shf *shf) hereinval(struct ioword *iop, int sub, char **resbuf, struct shf *shf)
{ {
const char * volatile ccp = content; const char * volatile ccp = iop->heredoc;
struct source *s, *osource; struct source *s, *osource;
osource = source; osource = source;
@ -1531,7 +1531,9 @@ hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
/* special to iosetup(): don't print error */ /* special to iosetup(): don't print error */
return (-2); return (-2);
} }
if (sub) { if (iop->ioflag & IOHERESTR) {
ccp = evalstr(iop->delim, DOHERESTR | DOSCALAR | DOHEREDOC);
} else if (sub) {
/* do substitutions on the content of heredoc */ /* do substitutions on the content of heredoc */
s = pushs(SSTRING, ATEMP); s = pushs(SSTRING, ATEMP);
s->start = s->str = ccp; s->start = s->str = ccp;
@ -1560,7 +1562,7 @@ herein(struct ioword *iop, char **resbuf)
int i; int i;
/* ksh -c 'cat <<EOF' can cause this... */ /* ksh -c 'cat <<EOF' can cause this... */
if (iop->heredoc == NULL) { if (iop->heredoc == NULL && !(iop->ioflag & IOHERESTR)) {
warningf(true, "%s missing", "here document"); warningf(true, "%s missing", "here document");
/* special to iosetup(): don't print error */ /* special to iosetup(): don't print error */
return (-2); return (-2);
@ -1571,7 +1573,7 @@ herein(struct ioword *iop, char **resbuf)
/* skip all the fd setup if we just want the value */ /* skip all the fd setup if we just want the value */
if (resbuf != NULL) if (resbuf != NULL)
return (hereinval(iop->heredoc, i, resbuf, NULL)); return (hereinval(iop, i, resbuf, NULL));
/* /*
* Create temp file to hold content (done before newenv * Create temp file to hold content (done before newenv
@ -1588,7 +1590,7 @@ herein(struct ioword *iop, char **resbuf)
return (-2); return (-2);
} }
if (hereinval(iop->heredoc, i, NULL, shf) == -2) { if (hereinval(iop, i, NULL, shf) == -2) {
close(fd); close(fd);
/* special to iosetup(): don't print error */ /* special to iosetup(): don't print error */
return (-2); return (-2);

96
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.208 2015/09/06 13:10:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.209 2015/09/06 19:47:00 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -38,8 +38,8 @@ __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.208 2015/09/06 13:10:48 tg Exp $");
#define SQBRACE 7 /* inside "${}" */ #define SQBRACE 7 /* inside "${}" */
#define SBQUOTE 8 /* inside `` */ #define SBQUOTE 8 /* inside `` */
#define SASPAREN 9 /* inside $(( )) */ #define SASPAREN 9 /* inside $(( )) */
#define SHEREDELIM 10 /* parsing <<,<<-,<<< delimiter */ #define SHEREDELIM 10 /* parsing << or <<- delimiter */
#define SHEREDQUOTE 11 /* parsing " in <<,<<-,<<< delimiter */ #define SHEREDQUOTE 11 /* parsing " in << or <<- delimiter */
#define SPATTERN 12 /* parsing *(...|...) pattern (*+?@!) */ #define SPATTERN 12 /* parsing *(...|...) pattern (*+?@!) */
#define SADELIM 13 /* like SBASE, looking for delimiter */ #define SADELIM 13 /* like SBASE, looking for delimiter */
#define STBRACEKORN 14 /* parsing ${...[#%]...} !FSH */ #define STBRACEKORN 14 /* parsing ${...[#%]...} !FSH */
@ -98,7 +98,7 @@ 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 void gethere(bool); static void gethere(void);
static Lex_state *push_state_i(State_info *, Lex_state *); static Lex_state *push_state_i(State_info *, Lex_state *);
static Lex_state *pop_state_i(State_info *, Lex_state *); static Lex_state *pop_state_i(State_info *, Lex_state *);
@ -240,20 +240,6 @@ yylex(int cf)
/* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */ /* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */
statep->type = state; statep->type = state;
/* check for here string */
if (state == SHEREDELIM) {
c = getsc();
if (c == '<') {
state = SHEREDELIM;
while ((c = getsc()) == ' ' || c == '\t')
;
ungetsc(c);
c = '<';
goto accept_nonword;
}
ungetsc(c);
}
/* collect non-special or quoted characters to form word */ /* collect non-special or quoted characters to form word */
while (!((c = getsc()) == 0 || while (!((c = getsc()) == 0 ||
((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) { ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
@ -262,7 +248,6 @@ yylex(int cf)
c == /*{*/ '}') c == /*{*/ '}')
/* possibly end ${ :;} */ /* possibly end ${ :;} */
break; break;
accept_nonword:
Xcheck(ws, wp); Xcheck(ws, wp);
switch (state) { switch (state) {
case SADELIM: case SADELIM:
@ -806,7 +791,7 @@ yylex(int cf)
++statep->nparen; ++statep->nparen;
goto Sbase2; goto Sbase2;
/* <<, <<-, <<< delimiter */ /* << or <<- delimiter */
case SHEREDELIM: case SHEREDELIM:
/* /*
* here delimiters need a special case since * here delimiters need a special case since
@ -844,7 +829,7 @@ yylex(int cf)
} }
break; break;
/* " in <<, <<-, <<< delimiter */ /* " in << or <<- delimiter */
case SHEREDQUOTE: case SHEREDQUOTE:
if (c != '"') if (c != '"')
goto Subst; goto Subst;
@ -941,22 +926,12 @@ yylex(int cf)
iop->ioflag |= c == c2 ? iop->ioflag |= c == c2 ?
(c == '>' ? IOCAT : IOHERE) : IORDWR; (c == '>' ? IOCAT : IOHERE) : IORDWR;
if (iop->ioflag == IOHERE) { if (iop->ioflag == IOHERE) {
if ((c2 = getsc()) == '-') { if ((c2 = getsc()) == '-')
iop->ioflag |= IOSKIP; iop->ioflag |= IOSKIP;
c2 = getsc(); else if (c2 == '<')
} else if (c2 == '<')
iop->ioflag |= IOHERESTR; iop->ioflag |= IOHERESTR;
if (c2 == ' ') { else
/*XXX reentrancy hack IONDELIM */ ungetsc(c2);
c2 = getsc();
if (c2 != '\n') {
ungetsc(c2);
c2 = ' ';
}
}
ungetsc(c2);
if (c2 == '\n')
iop->ioflag |= IONDELIM;
} }
} else if (c2 == '&') } else if (c2 == '&')
iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0); iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0);
@ -1006,12 +981,14 @@ yylex(int cf)
} }
#endif #endif
} else if (c == '\n') { } else if (c == '\n') {
gethere(false); if (cf & HEREDELIM)
if (cf & CONTIN) ungetsc(c);
goto Again; else {
} else if (c == '\0') gethere();
/* need here strings at EOF */ if (cf & CONTIN)
gethere(true); goto Again;
}
}
return (c); return (c);
} }
@ -1034,23 +1011,8 @@ yylex(int cf)
/* copy word to unprefixed string ident */ /* copy word to unprefixed string ident */
sp = yylval.cp; sp = yylval.cp;
dp = ident; dp = ident;
if ((cf & HEREDELIM) && (sp[1] == '<')) { while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
herestringloop: *dp++ = *sp++;
switch ((c = *sp++)) {
case CHAR:
++sp;
/* FALLTHROUGH */
case OQUOTE:
case CQUOTE:
goto herestringloop;
default:
break;
}
/* dummy value */
*dp++ = 'x';
} else
while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
*dp++ = *sp++;
if (c != EOS) if (c != EOS)
/* word is not unquoted */ /* word is not unquoted */
dp = ident; dp = ident;
@ -1126,15 +1088,12 @@ yylex(int cf)
} }
static void static void
gethere(bool iseof) gethere(void)
{ {
struct ioword **p; struct ioword **p;
for (p = heres; p < herep; p++) for (p = heres; p < herep; p++)
if (iseof && !((*p)->ioflag & IOHERESTR)) if (!((*p)->ioflag & IOHERESTR))
/* only here strings at EOF */
return;
else
readhere(*p); readhere(*p);
herep = heres; herep = heres;
} }
@ -1152,16 +1111,7 @@ readhere(struct ioword *iop)
char *xp; char *xp;
size_t xpos; size_t xpos;
if (iop->ioflag & IOHERESTR) { eof = evalstr(iop->delim, 0);
/* process the here string */
iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
xpos = strlen(xp) - 1;
memmove(xp, xp + 1, xpos);
xp[xpos] = '\n';
return;
}
eof = iop->ioflag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
if (!(iop->ioflag & IOEVAL)) if (!(iop->ioflag & IOEVAL))
ignore_backslash_newline++; ignore_backslash_newline++;

5
sh.h
View File

@ -172,9 +172,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.743 2015/09/05 20:20:46 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.744 2015/09/06 19:47:00 tg Exp $");
#endif #endif
#define MKSH_VERSION "R51 2015/09/05" #define MKSH_VERSION "R51 2015/09/06"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -1454,6 +1454,7 @@ struct ioword {
#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */ #define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
#define DOSCALAR BIT(12) /* change field handling to non-list context */ #define DOSCALAR BIT(12) /* change field handling to non-list context */
#define DOHEREDOC BIT(13) /* change scalar handling to heredoc body */ #define DOHEREDOC BIT(13) /* change scalar handling to heredoc body */
#define DOHERESTR BIT(14) /* append a newline char */
#define X_EXTRA 20 /* this many extra bytes in X string */ #define X_EXTRA 20 /* this many extra bytes in X string */

18
syn.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.103 2015/09/05 19:19:11 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.104 2015/09/06 19:47:01 tg Exp $");
struct nesting_state { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -172,6 +172,8 @@ c_list(bool multi)
return (t); return (t);
} }
static const char IONDELIM_delim[] = { CHAR, '<', CHAR, '<', EOS };
static struct ioword * static struct ioword *
synio(int cf) synio(int cf)
{ {
@ -189,15 +191,19 @@ synio(int cf)
return (NULL); return (NULL);
ACCEPT; ACCEPT;
iop = yylval.iop; iop = yylval.iop;
if (iop->ioflag & IONDELIM)
goto gotnulldelim;
ishere = (iop->ioflag & IOTYPE) == IOHERE; ishere = (iop->ioflag & IOTYPE) == IOHERE;
musthave(LWORD, ishere ? HEREDELIM : 0); if (iop->ioflag & IOHERESTR) {
musthave(LWORD, 0);
} else if (ishere && tpeek(HEREDELIM) == '\n') {
ACCEPT;
yylval.cp = wdcopy(IONDELIM_delim, ATEMP);
iop->ioflag |= IOEVAL | IONDELIM;
} else
musthave(LWORD, ishere ? HEREDELIM : 0);
if (ishere) { if (ishere) {
iop->delim = yylval.cp; iop->delim = yylval.cp;
if (*ident != 0) { if (*ident != 0 && !(iop->ioflag & IOHERESTR)) {
/* unquoted */ /* unquoted */
gotnulldelim:
iop->ioflag |= IOEVAL; iop->ioflag |= IOEVAL;
} }
if (herep > &heres[HERES - 1]) if (herep > &heres[HERES - 1])

10
tree.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.76 2015/09/05 20:20:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.77 2015/09/06 19:47:01 tg Exp $");
#define INDENT 8 #define INDENT 8
@ -226,7 +226,6 @@ ptree(struct op *t, int indent, struct shf *shf)
shf_putc('\n', shf); shf_putc('\n', shf);
shf_puts(iop->heredoc, shf); shf_puts(iop->heredoc, shf);
fptreef(shf, indent, "%s", fptreef(shf, indent, "%s",
iop->ioflag & IONDELIM ? "<<" :
evalstr(iop->delim, 0)); evalstr(iop->delim, 0));
need_nl = true; need_nl = true;
} }
@ -265,6 +264,8 @@ pioact(struct shf *shf, struct ioword *iop)
shf_puts("<<", shf); shf_puts("<<", shf);
if (flag & IOSKIP) if (flag & IOSKIP)
shf_putc('-', shf); shf_putc('-', shf);
else if (flag & IOHERESTR)
shf_putc('<', shf);
break; break;
case IOCAT: case IOCAT:
shf_puts(">>", shf); shf_puts(">>", shf);
@ -283,9 +284,8 @@ pioact(struct shf *shf, struct ioword *iop)
} }
/* name/delim are NULL when printing syntax errors */ /* name/delim are NULL when printing syntax errors */
if (type == IOHERE) { if (type == IOHERE) {
if (iop->delim) if (iop->delim && !(iop->ioflag & IONDELIM))
wdvarput(shf, iop->delim, 0, WDS_TPUTS); wdvarput(shf, iop->delim, 0, WDS_TPUTS);
/*XXX see IONDELIM hack */
} else if (iop->name) { } else if (iop->name) {
if (flag & IONAMEXP) if (flag & IONAMEXP)
print_value_quoted(shf, iop->name); print_value_quoted(shf, iop->name);
@ -931,7 +931,7 @@ dumpioact(struct shf *shf, struct op *t)
DB(IOHERESTR) DB(IOHERESTR)
DB(IONDELIM) DB(IONDELIM)
shf_fprintf(shf, ",unit=%d", (int)iop->unit); shf_fprintf(shf, ",unit=%d", (int)iop->unit);
if (iop->delim) { if (iop->delim && !(iop->ioflag & IONDELIM)) {
shf_puts(",delim<", shf); shf_puts(",delim<", shf);
dumpwdvar(shf, iop->delim); dumpwdvar(shf, iop->delim);
shf_putc('>', shf); shf_putc('>', shf);