implement ksh93 feature ${ foo;}
This commit is contained in:
		
							
								
								
									
										42
									
								
								check.t
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								check.t
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| # $MirOS: src/bin/mksh/check.t,v 1.552 2012/07/30 19:58:03 tg Exp $ | ||||
| # $MirOS: src/bin/mksh/check.t,v 1.553 2012/07/30 21:37:08 tg Exp $ | ||||
| # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ | ||||
| # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ | ||||
| # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ | ||||
| @@ -29,7 +29,7 @@ | ||||
| # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD | ||||
|  | ||||
| expected-stdout: | ||||
| 	@(#)MIRBSD KSH R40 2012/07/21 | ||||
| 	@(#)MIRBSD KSH R40 2012/07/30 | ||||
| description: | ||||
| 	Check version of shell. | ||||
| stdin: | ||||
| @@ -38,7 +38,7 @@ name: KSH_VERSION | ||||
| category: shell:legacy-no | ||||
| --- | ||||
| expected-stdout: | ||||
| 	@(#)LEGACY KSH R40 2012/07/21 | ||||
| 	@(#)LEGACY KSH R40 2012/07/30 | ||||
| description: | ||||
| 	Check version of legacy shell. | ||||
| stdin: | ||||
| @@ -6194,21 +6194,6 @@ expected-stdout: | ||||
| expected-stderr-pattern: | ||||
| 	/(Unrecognized character .... ignored at \..t4 line 1)*/ | ||||
| --- | ||||
| name: utf8bom-3 | ||||
| description: | ||||
| 	Reading the UTF-8 BOM should enable the utf8-mode flag | ||||
| 	(temporarily for COMSUBs) | ||||
| stdin: | ||||
| 	"$__progname" -c ':; if [[ $- = *U* ]]; then echo 1 on; else echo 1 off; fi' | ||||
| 	"$__progname" -c ':; if [[ $- = *U* ]]; then echo 2 on; else echo 2 off; fi' | ||||
| 	"$__progname" -c 'if [[ $- = *U* ]]; then echo 3 on; else echo 3 off; fi; x=$(:; if [[ $- = *U* ]]; then echo 4 on; else echo 4 off; fi); echo $x; if [[ $- = *U* ]]; then echo 5 on; else echo 5 off; fi' | ||||
| expected-stdout: | ||||
| 	1 off | ||||
| 	2 on | ||||
| 	3 off | ||||
| 	4 on | ||||
| 	5 off | ||||
| --- | ||||
| name: utf8opt-1a | ||||
| description: | ||||
| 	Check that the utf8-mode flag is not set at non-interactive startup | ||||
| @@ -9520,6 +9505,26 @@ expected-stdout: | ||||
| 		x=$(( echo $(true >&3 ) $((1+ 2)) ) | tr u x )  | ||||
| 	}  | ||||
| --- | ||||
| name: funsub-1 | ||||
| description: | ||||
| 	Check that non-subenvironment command substitution works | ||||
| stdin: | ||||
| 	set -e | ||||
| 	foo=bar | ||||
| 	echo "ob $foo ." | ||||
| 	echo "${ | ||||
| 		echo "ib $foo :" | ||||
| 		foo=baz | ||||
| 		echo "ia $foo :" | ||||
| 		false | ||||
| 	}" . | ||||
| 	echo "oa $foo ." | ||||
| expected-stdout: | ||||
| 	ob bar . | ||||
| 	ib bar : | ||||
| 	ia baz : . | ||||
| 	oa baz . | ||||
| --- | ||||
| name: test-stnze-1 | ||||
| description: | ||||
| 	Check that the short form [ $x ] works | ||||
| @@ -9613,7 +9618,6 @@ expected-stdout: | ||||
| name: event-subst-3 | ||||
| description: | ||||
| 	Check that '!' substitution in noninteractive mode is ignored | ||||
| category: !smksh | ||||
| file-setup: file 755 "falsetto" | ||||
| 	#! /bin/sh | ||||
| 	echo molto bene | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| # $Id$ | ||||
| # $MirOS: src/bin/mksh/dot.mkshrc,v 1.69 2011/12/31 01:07:19 tg Exp $ | ||||
| # $MirOS: src/bin/mksh/dot.mkshrc,v 1.70 2012/07/30 21:37:10 tg Exp $ | ||||
| #- | ||||
| # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 | ||||
| # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, | ||||
| #		2011, 2012 | ||||
| #	Thorsten Glaser <tg@mirbsd.org> | ||||
| # | ||||
| # Provided that these terms and disclaimer and all copyright notices | ||||
| @@ -29,7 +30,7 @@ function precmd { | ||||
|  | ||||
| 	(( e )) && print -n "$e|" | ||||
| } | ||||
| PS1=$'\001\r''$(precmd)${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \? | ||||
| PS1=$'\001\r''${ precmd;}${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \? | ||||
| 	)}@${HOSTNAME%%.*}:$(local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || \ | ||||
| 	d=${d/#$p/~}; local m=${%d} n p=...; (( m > 0 )) || m=${#d} | ||||
| 	(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || \ | ||||
|   | ||||
							
								
								
									
										41
									
								
								eval.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								eval.c
									
									
									
									
									
								
							| @@ -23,7 +23,7 @@ | ||||
|  | ||||
| #include "sh.h" | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.122 2012/07/30 17:28:21 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.123 2012/07/30 21:37:11 tg Exp $"); | ||||
|  | ||||
| /* | ||||
|  * string expansion | ||||
| @@ -58,7 +58,7 @@ typedef struct Expand { | ||||
| #define IFS_NWS		2	/* have seen IFS non-white-space */ | ||||
|  | ||||
| static int varsub(Expand *, const char *, const char *, int *, int *); | ||||
| static int comsub(Expand *, const char *); | ||||
| static int comsub(Expand *, const char *, int); | ||||
| static char *trimsub(char *, char *, int); | ||||
| static void glob(char *, XPtrV *, int); | ||||
| static void globit(XString *, char **, char *, XPtrV *, int); | ||||
| @@ -278,17 +278,27 @@ expand(const char *cp,	/* input word */ | ||||
| 				quote = st->quotew; | ||||
| 				continue; | ||||
| 			case COMSUB: | ||||
| 			case FUNSUB: | ||||
| 				tilde_ok = 0; | ||||
| 				if (f & DONTRUNCOMMAND) { | ||||
| 					word = IFS_WORD; | ||||
| 					*dp++ = '$'; *dp++ = '('; | ||||
| 					*dp++ = '$'; | ||||
| 					if (c == FUNSUB) { | ||||
| 						*dp++ = '{'; | ||||
| 						*dp++ = ' '; | ||||
| 					} else | ||||
| 						*dp++ = '('; | ||||
| 					while (*sp != '\0') { | ||||
| 						Xcheck(ds, dp); | ||||
| 						*dp++ = *sp++; | ||||
| 					} | ||||
| 					if (c == FUNSUB) { | ||||
| 						*dp++ = ';'; | ||||
| 						*dp++ = '}'; | ||||
| 					} else | ||||
| 						*dp++ = ')'; | ||||
| 				} else { | ||||
| 					type = comsub(&x, sp); | ||||
| 					type = comsub(&x, sp, c); | ||||
| 					if (type == XCOM && (f&DOBLANK)) | ||||
| 						doblank++; | ||||
| 					sp = strnul(sp) + 1; | ||||
| @@ -611,8 +621,8 @@ expand(const char *cp,	/* input word */ | ||||
| 					case '#': | ||||
| 					case '%': | ||||
| 						/* ! DOBLANK,DOBRACE,DOTILDE */ | ||||
| 						f = DOPAT | (f&DONTRUNCOMMAND) | | ||||
| 						    DOTEMP; | ||||
| 						f = (f & DONTRUNCOMMAND) | | ||||
| 						    DOPAT | DOTEMP; | ||||
| 						st->quotew = quote = 0; | ||||
| 						/* | ||||
| 						 * Prepend open pattern (so | | ||||
| @@ -1272,7 +1282,7 @@ varsub(Expand *xp, const char *sp, const char *word, | ||||
|  * Run the command in $(...) and read its output. | ||||
|  */ | ||||
| static int | ||||
| comsub(Expand *xp, const char *cp) | ||||
| comsub(Expand *xp, const char *cp, int fn) | ||||
| { | ||||
| 	Source *s, *sold; | ||||
| 	struct op *t; | ||||
| @@ -1286,10 +1296,15 @@ comsub(Expand *xp, const char *cp) | ||||
| 	afree(s, ATEMP); | ||||
| 	source = sold; | ||||
|  | ||||
| 	UTFMODE = old_utfmode; | ||||
|  | ||||
| 	if (t == NULL) | ||||
| 		return (XBASE); | ||||
|  | ||||
| 	if (t != NULL && t->type == TCOM && | ||||
| 	/* no waitlast() unless specifically enabled later */ | ||||
| 	xp->split = false; | ||||
|  | ||||
| 	if (t->type == TCOM && | ||||
| 	    *t->args == NULL && *t->vars == NULL && t->ioact != NULL) { | ||||
| 		/* $(<file) */ | ||||
| 		struct ioword *io = *t->ioact; | ||||
| @@ -1302,10 +1317,9 @@ comsub(Expand *xp, const char *cp) | ||||
| 			SHF_MAPHI|SHF_CLEXEC); | ||||
| 		if (shf == NULL) | ||||
| 			errorf("%s: %s %s", name, "can't open", "$() input"); | ||||
| 		/* no waitlast() */ | ||||
| 		xp->split = false; | ||||
| 	} else { | ||||
| 		int ofd1, pv[2]; | ||||
|  | ||||
| 		openpipe(pv); | ||||
| 		shf = shf_fdopen(pv[0], SHF_RD, NULL); | ||||
| 		ofd1 = savefd(1); | ||||
| @@ -1313,14 +1327,16 @@ comsub(Expand *xp, const char *cp) | ||||
| 			ksh_dup2(pv[1], 1, false); | ||||
| 			close(pv[1]); | ||||
| 		} | ||||
| 		execute(t, XFORK|XXCOM|XPIPEO, NULL); | ||||
| 		execute(t, XXCOM | XPIPEO | | ||||
| 		    (fn == FUNSUB ? XERROK : XFORK), NULL); | ||||
| 		restfd(1, ofd1); | ||||
| 		if (fn != FUNSUB) { | ||||
| 			startlast(); | ||||
| 			/* waitlast() */ | ||||
| 			xp->split = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	UTFMODE = old_utfmode; | ||||
| 	xp->u.shf = shf; | ||||
| 	return (XCOM); | ||||
| } | ||||
| @@ -1328,7 +1344,6 @@ comsub(Expand *xp, const char *cp) | ||||
| /* | ||||
|  * perform #pattern and %pattern substitution in ${} | ||||
|  */ | ||||
|  | ||||
| static char * | ||||
| trimsub(char *str, char *pat, int how) | ||||
| { | ||||
|   | ||||
							
								
								
									
										28
									
								
								lex.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								lex.c
									
									
									
									
									
								
							| @@ -23,7 +23,7 @@ | ||||
|  | ||||
| #include "sh.h" | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.165 2012/07/01 15:54:55 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.166 2012/07/30 21:37:12 tg Exp $"); | ||||
|  | ||||
| /* | ||||
|  * states while lexing word | ||||
| @@ -109,7 +109,7 @@ void yyskiputf8bom(void); | ||||
| static int backslash_skip; | ||||
| static int ignore_backslash_newline; | ||||
| static struct sretrace_info *retrace_info; | ||||
| short subshell_nesting_level = 0; | ||||
| int subshell_nesting_type = 0; | ||||
|  | ||||
| /* optimised getsc_bn() */ | ||||
| #define o_getsc()	(*source->str != '\0' && *source->str != '\\' && \ | ||||
| @@ -262,6 +262,11 @@ yylex(int cf) | ||||
| 	while (!((c = getsc()) == 0 || | ||||
| 	    ((state == SBASE || state == SHEREDELIM || state == SHERESTRING) && | ||||
| 	    ctype(c, C_LEX1)))) { | ||||
| 		if (state == SBASE && | ||||
| 		    subshell_nesting_type == /*{*/ '}' && | ||||
| 		    c == /*{*/ '}') | ||||
| 			/* possibly end ${ :;} */ | ||||
| 			break; | ||||
|  accept_nonword: | ||||
| 		Xcheck(ws, wp); | ||||
| 		switch (state) { | ||||
| @@ -395,14 +400,27 @@ yylex(int cf) | ||||
| 					} else { | ||||
| 						ungetsc(c); | ||||
|  subst_command: | ||||
| 						sp = yyrecursive(); | ||||
| 						c = COMSUB; | ||||
|  subst_command2: | ||||
| 						sp = yyrecursive(c); | ||||
| 						cz = strlen(sp) + 1; | ||||
| 						XcheckN(ws, wp, cz); | ||||
| 						*wp++ = COMSUB; | ||||
| 						*wp++ = c; | ||||
| 						memcpy(wp, sp, cz); | ||||
| 						wp += cz; | ||||
| 					} | ||||
| 				} else if (c == '{') /*}*/ { | ||||
| 					c = getsc(); | ||||
| 					if (ctype(c, C_IFSWS)) { | ||||
| 						/* | ||||
| 						 * non-subenvironment | ||||
| 						 * "command" substitution | ||||
| 						 */ | ||||
| 						c = FUNSUB; | ||||
| 						goto subst_command2; | ||||
| 					} | ||||
| 					ungetsc(c); | ||||
|  | ||||
| 					*wp++ = OSUBST; | ||||
| 					*wp++ = '{'; /*}*/ | ||||
| 					wp = get_brace_var(&ws, wp); | ||||
| @@ -1171,7 +1189,7 @@ readhere(struct ioword *iop) | ||||
| 		/* end of here document marker, what to do? */ | ||||
| 		switch (c) { | ||||
| 		case /*(*/ ')': | ||||
| 			if (!subshell_nesting_level) | ||||
| 			if (!subshell_nesting_type) | ||||
| 				/*- | ||||
| 				 * not allowed outside $(...) or (...) | ||||
| 				 * => mismatch | ||||
|   | ||||
							
								
								
									
										6
									
								
								misc.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								misc.c
									
									
									
									
									
								
							| @@ -30,7 +30,7 @@ | ||||
| #include <grp.h> | ||||
| #endif | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.196 2012/07/20 21:18:45 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.197 2012/07/30 21:37:13 tg Exp $"); | ||||
|  | ||||
| #define KSH_CHVT_FLAG | ||||
| #ifdef MKSH_SMALL | ||||
| @@ -101,9 +101,9 @@ initctypes(void) | ||||
| 	chtypes['_'] |= C_ALPHA; | ||||
| 	setctypes("0123456789", C_DIGIT); | ||||
| 	/* \0 added automatically */ | ||||
| 	setctypes(" \t\n|&;<>()", C_LEX1); | ||||
| 	setctypes(TC_LEX1, C_LEX1); | ||||
| 	setctypes("*@#!$-?", C_VAR1); | ||||
| 	setctypes(" \t\n", C_IFSWS); | ||||
| 	setctypes(TC_IFSWS, C_IFSWS); | ||||
| 	setctypes("=-+?", C_SUBOP1); | ||||
| 	setctypes("\t\n \"#$&'()*;<=>?[\\]`|", C_QUOTE); | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								mksh.1
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								mksh.1
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| .\" $MirOS: src/bin/mksh/mksh.1,v 1.290 2012/07/25 19:40:40 tg Exp $ | ||||
| .\" $MirOS: src/bin/mksh/mksh.1,v 1.291 2012/07/30 21:37:13 tg Exp $ | ||||
| .\" $OpenBSD: ksh.1,v 1.144 2012/07/08 08:13:20 guenther Exp $ | ||||
| .\"- | ||||
| .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, | ||||
| @@ -74,7 +74,7 @@ | ||||
| .\" with -mandoc, it might implement .Mx itself, but we want to | ||||
| .\" use our own definition. And .Dd must come *first*, always. | ||||
| .\" | ||||
| .Dd $Mdocdate: July 25 2012 $ | ||||
| .Dd $Mdocdate: July 30 2012 $ | ||||
| .\" | ||||
| .\" Check which macro package we use, and do other -mdoc setup. | ||||
| .\" | ||||
| @@ -1145,9 +1145,15 @@ or | ||||
| command substitutions take the form | ||||
| .Pf $( Ns Ar command Ns \&) | ||||
| or (deprecated) | ||||
| .Pf \` Ns Ar command Ns \` ; | ||||
| .Pf \` Ns Ar command Ns \` | ||||
| or (executed in the current environment) | ||||
| .Pf ${\ \& Ar command Ns \&;} | ||||
| and strip trailing newlines; | ||||
| and arithmetic substitutions take the form | ||||
| .Pf $(( Ns Ar expression Ns )) . | ||||
| Parsing the current-environment command substitution requires a space, | ||||
| tab or newline after the opening brace and that the closing brace be | ||||
| recognised as a keyword (i.e. is preceded by a newline or semicolon). | ||||
| .Pp | ||||
| If a substitution appears outside of double quotes, the results of the | ||||
| substitution are generally subject to word or field splitting according to | ||||
| @@ -1225,6 +1231,8 @@ A command substitution is replaced by the output generated by the specified | ||||
| command which is run in a subshell. | ||||
| For | ||||
| .Pf $( Ns Ar command Ns \&) | ||||
| and | ||||
| .Pf ${\ \& Ar command Ns \&;} | ||||
| substitutions, normal quoting rules are used when | ||||
| .Ar command | ||||
| is parsed; however, for the deprecated | ||||
| @@ -1963,7 +1971,7 @@ x=$(print \e\e001) | ||||
| PS1="$x$(print \e\er)$x$(tput smso)$x\e$PWD$x$(tput rmso)$x\*(Gt " | ||||
| .Ed | ||||
| .Pp | ||||
| Due to pressure from David G. Korn, | ||||
| Due to a strong suggestion from David G. Korn, | ||||
| .Nm | ||||
| now also supports the following form: | ||||
| .Bd -literal -offset indent | ||||
|   | ||||
							
								
								
									
										9
									
								
								sh.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								sh.h
									
									
									
									
									
								
							| @@ -157,9 +157,9 @@ | ||||
| #endif | ||||
|  | ||||
| #ifdef EXTERN | ||||
| __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.575 2012/07/30 17:04:30 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.576 2012/07/30 21:37:15 tg Exp $"); | ||||
| #endif | ||||
| #define MKSH_VERSION "R40 2012/07/21" | ||||
| #define MKSH_VERSION "R40 2012/07/30" | ||||
|  | ||||
| /* arithmetic types: C implementation */ | ||||
| #if !HAVE_CAN_INTTYPES | ||||
| @@ -765,6 +765,8 @@ EXTERN const char Tgbuiltin[] E_INIT("=builtin"); | ||||
| #define Tbuiltin	(Tgbuiltin + 1)		/* "builtin" */ | ||||
| EXTERN const char T_function[] E_INIT(" function"); | ||||
| #define Tfunction	(T_function + 1)	/* "function" */ | ||||
| EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n"); | ||||
| #define TC_IFSWS	(TC_LEX1 + 7)		/* space tab newline */ | ||||
|  | ||||
| typedef uint8_t Temp_type; | ||||
| /* expanded heredoc */ | ||||
| @@ -1281,6 +1283,7 @@ struct op { | ||||
| #define SPAT	10	/* separate pattern: | */ | ||||
| #define CPAT	11	/* close pattern: ) */ | ||||
| #define ADELIM	12	/* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */ | ||||
| #define FUNSUB	14	/* ${ foo;} substitution (NUL terminated) */ | ||||
|  | ||||
| /* | ||||
|  * IO redirection | ||||
| @@ -1903,7 +1906,7 @@ ssize_t shf_vfprintf(struct shf *, const char *, va_list) | ||||
| void initkeywords(void); | ||||
| struct op *compile(Source *, bool); | ||||
| bool parse_usec(const char *, struct timeval *); | ||||
| char *yyrecursive(void); | ||||
| char *yyrecursive(int); | ||||
| /* tree.c */ | ||||
| void fptreef(struct shf *, int, const char *, ...); | ||||
| char *snptreef(char *, ssize_t, const char *, ...); | ||||
|   | ||||
							
								
								
									
										36
									
								
								syn.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								syn.c
									
									
									
									
									
								
							| @@ -23,9 +23,9 @@ | ||||
|  | ||||
| #include "sh.h" | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.78 2012/07/30 17:04:31 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.79 2012/07/30 21:37:16 tg Exp $"); | ||||
|  | ||||
| extern short subshell_nesting_level; | ||||
| extern int subshell_nesting_type; | ||||
| extern void yyskiputf8bom(void); | ||||
|  | ||||
| struct nesting_state { | ||||
| @@ -363,12 +363,15 @@ get_command(int cf) | ||||
|  Leave: | ||||
| 		break; | ||||
|  | ||||
| 	case '(': | ||||
| 	case '(': /*)*/ { | ||||
| 		int subshell_nesting_type_saved; | ||||
|  Subshell: | ||||
| 		++subshell_nesting_level; | ||||
| 		subshell_nesting_type_saved = subshell_nesting_type; | ||||
| 		subshell_nesting_type = ')'; | ||||
| 		t = nested(TPAREN, '(', ')'); | ||||
| 		--subshell_nesting_level; | ||||
| 		subshell_nesting_type = subshell_nesting_type_saved; | ||||
| 		break; | ||||
| 	    } | ||||
|  | ||||
| 	case '{': /*}*/ | ||||
| 		t = nested(TBRACE, '{', '}'); | ||||
| @@ -1115,16 +1118,29 @@ parse_usec(const char *s, struct timeval *tv) | ||||
|  * a COMSUB recursively using the main shell parser and lexer | ||||
|  */ | ||||
| char * | ||||
| yyrecursive(void) | ||||
| yyrecursive(int subtype) | ||||
| { | ||||
| 	struct op *t; | ||||
| 	char *cp; | ||||
| 	bool old_reject; | ||||
| 	int old_symbol, old_salias; | ||||
| 	int old_symbol, old_salias, old_nesting_type; | ||||
| 	struct ioword **old_herep; | ||||
| 	int stok, etok; | ||||
|  | ||||
| 	switch (subtype) { | ||||
| 	case FUNSUB: | ||||
| 		stok = '{'; | ||||
| 		etok = '}'; | ||||
| 		break; | ||||
| 	case COMSUB: | ||||
| 	default: | ||||
| 		stok = '('; | ||||
| 		etok = ')'; | ||||
| 	} | ||||
|  | ||||
| 	/* tell the lexer to accept a closing parenthesis as EOD */ | ||||
| 	++subshell_nesting_level; | ||||
| 	old_nesting_type = subshell_nesting_type; | ||||
| 	subshell_nesting_type = etok; | ||||
|  | ||||
| 	/* push reject state, parse recursively, pop reject state */ | ||||
| 	old_reject = reject; | ||||
| @@ -1134,7 +1150,7 @@ yyrecursive(void) | ||||
| 	old_salias = sALIAS; | ||||
| 	sALIAS = 0; | ||||
| 	/* we use TPAREN as a helper container here */ | ||||
| 	t = nested(TPAREN, '(', ')'); | ||||
| 	t = nested(TPAREN, stok, etok); | ||||
| 	sALIAS = old_salias; | ||||
| 	herep = old_herep; | ||||
| 	reject = old_reject; | ||||
| @@ -1144,6 +1160,6 @@ yyrecursive(void) | ||||
| 	cp = snptreef(NULL, 0, "%T", t->left); | ||||
| 	tfree(t, ATEMP); | ||||
|  | ||||
| 	--subshell_nesting_level; | ||||
| 	subshell_nesting_type = old_nesting_type; | ||||
| 	return (cp); | ||||
| } | ||||
|   | ||||
							
								
								
									
										21
									
								
								tree.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								tree.c
									
									
									
									
									
								
							| @@ -23,7 +23,7 @@ | ||||
|  | ||||
| #include "sh.h" | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.62 2012/07/30 19:58:05 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.63 2012/07/30 21:37:17 tg Exp $"); | ||||
|  | ||||
| #define INDENT	8 | ||||
|  | ||||
| @@ -292,6 +292,7 @@ static const char * | ||||
| wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode) | ||||
| { | ||||
| 	int c; | ||||
| 	const char *cs; | ||||
|  | ||||
| 	/*- | ||||
| 	 * problems: | ||||
| @@ -335,16 +336,20 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode) | ||||
| 		} | ||||
| 		case COMSUB: | ||||
| 			shf_puts("$(", shf); | ||||
| 			cs = ")"; | ||||
|  pSUB: | ||||
| 			while ((c = *wp++) != 0) | ||||
| 				shf_putc(c, shf); | ||||
| 			shf_putc(')', shf); | ||||
| 			shf_puts(cs, shf); | ||||
| 			break; | ||||
| 		case FUNSUB: | ||||
| 			shf_puts("${ ", shf); | ||||
| 			cs = ";}"; | ||||
| 			goto pSUB; | ||||
| 		case EXPRSUB: | ||||
| 			shf_puts("$((", shf); | ||||
| 			while ((c = *wp++) != 0) | ||||
| 				shf_putc(c, shf); | ||||
| 			shf_puts("))", shf); | ||||
| 			break; | ||||
| 			cs = "))"; | ||||
| 			goto pSUB; | ||||
| 		case OQUOTE: | ||||
| 			if (opmode & WDS_TPUTS) { | ||||
| 				quotelevel++; | ||||
| @@ -580,6 +585,7 @@ wdscan(const char *wp, int c) | ||||
| 			wp++; | ||||
| 			break; | ||||
| 		case COMSUB: | ||||
| 		case FUNSUB: | ||||
| 		case EXPRSUB: | ||||
| 			while (*wp++ != 0) | ||||
| 				; | ||||
| @@ -819,6 +825,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel) | ||||
|  closeandout: | ||||
| 			shf_putc('>', shf); | ||||
| 			break; | ||||
| 		case FUNSUB: | ||||
| 			shf_puts("FUNSUB<", shf); | ||||
| 			goto dumpsub; | ||||
| 		case EXPRSUB: | ||||
| 			shf_puts("EXPRSUB<", shf); | ||||
| 			goto dumpsub; | ||||
|   | ||||
							
								
								
									
										4
									
								
								var.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								var.c
									
									
									
									
									
								
							| @@ -27,7 +27,7 @@ | ||||
| #include <sys/sysctl.h> | ||||
| #endif | ||||
|  | ||||
| __RCSID("$MirOS: src/bin/mksh/var.c,v 1.152 2012/07/01 15:38:09 tg Exp $"); | ||||
| __RCSID("$MirOS: src/bin/mksh/var.c,v 1.153 2012/07/30 21:37:17 tg Exp $"); | ||||
|  | ||||
| /*- | ||||
|  * Variables | ||||
| @@ -1254,7 +1254,7 @@ unsetspec(struct tbl *vp) | ||||
| 		flushcom(true); | ||||
| 		break; | ||||
| 	case V_IFS: | ||||
| 		setctypes(" \t\n", C_IFS); | ||||
| 		setctypes(TC_IFSWS, C_IFS); | ||||
| 		ifs0 = ' '; | ||||
| 		break; | ||||
| 	case V_TMPDIR: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user