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:
		
							
								
								
									
										11
									
								
								check.t
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								check.t
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								eval.c
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								exec.c
									
									
									
									
									
								
							| @@ -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); | ||||||
|   | |||||||
							
								
								
									
										86
									
								
								lex.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								lex.c
									
									
									
									
									
								
							| @@ -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 */ |  | ||||||
| 					c2 = getsc(); |  | ||||||
| 					if (c2 != '\n') { |  | ||||||
| 					ungetsc(c2); | 					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) | ||||||
|  | 				ungetsc(c); | ||||||
|  | 			else { | ||||||
|  | 				gethere(); | ||||||
| 				if (cf & CONTIN) | 				if (cf & CONTIN) | ||||||
| 					goto Again; | 					goto Again; | ||||||
| 		} else if (c == '\0') | 			} | ||||||
| 			/* need here strings at EOF */ | 		} | ||||||
| 			gethere(true); |  | ||||||
| 		return (c); | 		return (c); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1034,21 +1011,6 @@ 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] == '<')) { |  | ||||||
|  herestringloop: |  | ||||||
| 		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) | 	while ((dp - ident) < IDENT && (c = *sp++) == CHAR) | ||||||
| 		*dp++ = *sp++; | 		*dp++ = *sp++; | ||||||
| 	if (c != EOS) | 	if (c != EOS) | ||||||
| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								sh.h
									
									
									
									
									
								
							| @@ -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 */ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								syn.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								syn.c
									
									
									
									
									
								
							| @@ -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; | ||||||
|  | 	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); | 		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
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tree.c
									
									
									
									
									
								
							| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user