remove ${ foo;} from mksh again due to buffering issues jilles found

This commit is contained in:
tg 2012-08-17 18:34:25 +00:00
parent f18b1fae85
commit bb5e56d4c4
8 changed files with 37 additions and 118 deletions

26
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.554 2012/08/03 18:45:29 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.555 2012/08/17 18:34:18 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas 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: 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 $ # $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 # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R40 2012/08/03 @(#)MIRBSD KSH R40 2012/08/17
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -38,7 +38,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R40 2012/08/03 @(#)LEGACY KSH R40 2012/08/17
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:
@ -9505,26 +9505,6 @@ expected-stdout:
x=$(( echo $(true >&3 ) $((1+ 2)) ) | tr u x ) 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 name: test-stnze-1
description: description:
Check that the short form [ $x ] works Check that the short form [ $x ] works

View File

@ -1,5 +1,5 @@
# $Id$ # $Id$
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.70 2012/07/30 21:37:10 tg Exp $ # $MirOS: src/bin/mksh/dot.mkshrc,v 1.71 2012/08/17 18:34:20 tg Exp $
#- #-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 # 2011, 2012
@ -30,7 +30,7 @@ function precmd {
(( e )) && print -n "$e|" (( 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 = ?(*/) ]] || \ )}@${HOSTNAME%%.*}:$(local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || \
d=${d/#$p/~}; local m=${%d} n p=...; (( m > 0 )) || m=${#d} d=${d/#$p/~}; local m=${%d} n p=...; (( m > 0 )) || m=${#d}
(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || \ (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || \

22
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.123 2012/07/30 21:37:11 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.124 2012/08/17 18:34:20 tg Exp $");
/* /*
* string expansion * string expansion
@ -58,7 +58,7 @@ typedef struct Expand {
#define IFS_NWS 2 /* have seen IFS non-white-space */ #define IFS_NWS 2 /* have seen IFS non-white-space */
static int varsub(Expand *, const char *, const char *, int *, int *); static int varsub(Expand *, const char *, const char *, int *, int *);
static int comsub(Expand *, const char *, int); static int comsub(Expand *, const char *);
static char *trimsub(char *, char *, int); static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, int); static void glob(char *, XPtrV *, int);
static void globit(XString *, char **, char *, XPtrV *, int); static void globit(XString *, char **, char *, XPtrV *, int);
@ -278,27 +278,18 @@ expand(const char *cp, /* input word */
quote = st->quotew; quote = st->quotew;
continue; continue;
case COMSUB: case COMSUB:
case FUNSUB:
tilde_ok = 0; tilde_ok = 0;
if (f & DONTRUNCOMMAND) { if (f & DONTRUNCOMMAND) {
word = IFS_WORD; word = IFS_WORD;
*dp++ = '$'; *dp++ = '$';
if (c == FUNSUB) {
*dp++ = '{';
*dp++ = ' ';
} else
*dp++ = '('; *dp++ = '(';
while (*sp != '\0') { while (*sp != '\0') {
Xcheck(ds, dp); Xcheck(ds, dp);
*dp++ = *sp++; *dp++ = *sp++;
} }
if (c == FUNSUB) {
*dp++ = ';';
*dp++ = '}';
} else
*dp++ = ')'; *dp++ = ')';
} else { } else {
type = comsub(&x, sp, c); type = comsub(&x, sp);
if (type == XCOM && (f&DOBLANK)) if (type == XCOM && (f&DOBLANK))
doblank++; doblank++;
sp = strnul(sp) + 1; sp = strnul(sp) + 1;
@ -1282,7 +1273,7 @@ varsub(Expand *xp, const char *sp, const char *word,
* Run the command in $(...) and read its output. * Run the command in $(...) and read its output.
*/ */
static int static int
comsub(Expand *xp, const char *cp, int fn) comsub(Expand *xp, const char *cp)
{ {
Source *s, *sold; Source *s, *sold;
struct op *t; struct op *t;
@ -1327,15 +1318,12 @@ comsub(Expand *xp, const char *cp, int fn)
ksh_dup2(pv[1], 1, false); ksh_dup2(pv[1], 1, false);
close(pv[1]); close(pv[1]);
} }
execute(t, XXCOM | XPIPEO | execute(t, XXCOM | XPIPEO | XFORK, NULL);
(fn == FUNSUB ? XERROK : XFORK), NULL);
restfd(1, ofd1); restfd(1, ofd1);
if (fn != FUNSUB) {
startlast(); startlast();
/* waitlast() */ /* waitlast() */
xp->split = true; xp->split = true;
} }
}
xp->u.shf = shf; xp->u.shf = shf;
return (XCOM); return (XCOM);

28
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.166 2012/07/30 21:37:12 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.167 2012/08/17 18:34:21 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -109,7 +109,7 @@ void yyskiputf8bom(void);
static int backslash_skip; static int backslash_skip;
static int ignore_backslash_newline; static int ignore_backslash_newline;
static struct sretrace_info *retrace_info; static struct sretrace_info *retrace_info;
int subshell_nesting_type = 0; uint8_t subshell_nesting_level = 0;
/* optimised getsc_bn() */ /* optimised getsc_bn() */
#define o_getsc() (*source->str != '\0' && *source->str != '\\' && \ #define o_getsc() (*source->str != '\0' && *source->str != '\\' && \
@ -262,11 +262,6 @@ yylex(int cf)
while (!((c = getsc()) == 0 || while (!((c = getsc()) == 0 ||
((state == SBASE || state == SHEREDELIM || state == SHERESTRING) && ((state == SBASE || state == SHEREDELIM || state == SHERESTRING) &&
ctype(c, C_LEX1)))) { ctype(c, C_LEX1)))) {
if (state == SBASE &&
subshell_nesting_type == /*{*/ '}' &&
c == /*{*/ '}')
/* possibly end ${ :;} */
break;
accept_nonword: accept_nonword:
Xcheck(ws, wp); Xcheck(ws, wp);
switch (state) { switch (state) {
@ -400,27 +395,14 @@ yylex(int cf)
} else { } else {
ungetsc(c); ungetsc(c);
subst_command: subst_command:
c = COMSUB; sp = yyrecursive();
subst_command2:
sp = yyrecursive(c);
cz = strlen(sp) + 1; cz = strlen(sp) + 1;
XcheckN(ws, wp, cz); XcheckN(ws, wp, cz);
*wp++ = c; *wp++ = COMSUB;
memcpy(wp, sp, cz); memcpy(wp, sp, cz);
wp += cz; wp += cz;
} }
} else if (c == '{') /*}*/ { } else if (c == '{') /*}*/ {
c = getsc();
if (ctype(c, C_IFSWS)) {
/*
* non-subenvironment
* "command" substitution
*/
c = FUNSUB;
goto subst_command2;
}
ungetsc(c);
*wp++ = OSUBST; *wp++ = OSUBST;
*wp++ = '{'; /*}*/ *wp++ = '{'; /*}*/
wp = get_brace_var(&ws, wp); wp = get_brace_var(&ws, wp);
@ -1189,7 +1171,7 @@ readhere(struct ioword *iop)
/* end of here document marker, what to do? */ /* end of here document marker, what to do? */
switch (c) { switch (c) {
case /*(*/ ')': case /*(*/ ')':
if (!subshell_nesting_type) if (!subshell_nesting_level)
/*- /*-
* not allowed outside $(...) or (...) * not allowed outside $(...) or (...)
* => mismatch * => mismatch

11
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.292 2012/08/03 18:34:31 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.293 2012/08/17 18:34:22 tg Exp $
.\" $OpenBSD: ksh.1,v 1.144 2012/07/08 08:13:20 guenther Exp $ .\" $OpenBSD: ksh.1,v 1.144 2012/07/08 08:13:20 guenther Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -74,7 +74,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: August 3 2012 $ .Dd $Mdocdate: August 17 2012 $
.\" .\"
.\" Check which macro package we use, and do other -mdoc setup. .\" Check which macro package we use, and do other -mdoc setup.
.\" .\"
@ -1146,14 +1146,9 @@ command substitutions take the form
.Pf $( Ns Ar command Ns \&) .Pf $( Ns Ar command Ns \&)
or (deprecated) 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 strip trailing newlines;
and arithmetic substitutions take the form and arithmetic substitutions take the form
.Pf $(( Ns Ar expression Ns )) . .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 .Pp
If a substitution appears outside of double quotes, the results of the If a substitution appears outside of double quotes, the results of the
substitution are generally subject to word or field splitting according to substitution are generally subject to word or field splitting according to
@ -1231,8 +1226,6 @@ A command substitution is replaced by the output generated by the specified
command which is run in a subshell. command which is run in a subshell.
For For
.Pf $( Ns Ar command Ns \&) .Pf $( Ns Ar command Ns \&)
and
.Pf ${\ \& Ar command Ns \&;}
substitutions, normal quoting rules are used when substitutions, normal quoting rules are used when
.Ar command .Ar command
is parsed; however, for the deprecated is parsed; however, for the deprecated

7
sh.h
View File

@ -157,9 +157,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.577 2012/08/03 18:45:32 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.578 2012/08/17 18:34:24 tg Exp $");
#endif #endif
#define MKSH_VERSION "R40 2012/08/03" #define MKSH_VERSION "R40 2012/08/17"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -1283,7 +1283,6 @@ struct op {
#define SPAT 10 /* separate pattern: | */ #define SPAT 10 /* separate pattern: | */
#define CPAT 11 /* close pattern: ) */ #define CPAT 11 /* close pattern: ) */
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */ #define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
#define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */
/* /*
* IO redirection * IO redirection
@ -1906,7 +1905,7 @@ ssize_t shf_vfprintf(struct shf *, const char *, va_list)
void initkeywords(void); void initkeywords(void);
struct op *compile(Source *, bool); struct op *compile(Source *, bool);
bool parse_usec(const char *, struct timeval *); bool parse_usec(const char *, struct timeval *);
char *yyrecursive(int); char *yyrecursive(void);
/* tree.c */ /* tree.c */
void fptreef(struct shf *, int, const char *, ...); void fptreef(struct shf *, int, const char *, ...);
char *snptreef(char *, ssize_t, const char *, ...); char *snptreef(char *, ssize_t, const char *, ...);

37
syn.c
View File

@ -23,11 +23,12 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.79 2012/07/30 21:37:16 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.80 2012/08/17 18:34:25 tg Exp $");
extern int subshell_nesting_type;
extern void yyskiputf8bom(void); extern void yyskiputf8bom(void);
extern uint8_t subshell_nesting_level;
struct nesting_state { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
int start_line; /* line nesting began on */ int start_line; /* line nesting began on */
@ -363,15 +364,12 @@ get_command(int cf)
Leave: Leave:
break; break;
case '(': /*)*/ { case '(': /*)*/
int subshell_nesting_type_saved;
Subshell: Subshell:
subshell_nesting_type_saved = subshell_nesting_type; ++subshell_nesting_level;
subshell_nesting_type = ')';
t = nested(TPAREN, '(', ')'); t = nested(TPAREN, '(', ')');
subshell_nesting_type = subshell_nesting_type_saved; --subshell_nesting_level;
break; break;
}
case '{': /*}*/ case '{': /*}*/
t = nested(TBRACE, '{', '}'); t = nested(TBRACE, '{', '}');
@ -1118,29 +1116,16 @@ parse_usec(const char *s, struct timeval *tv)
* a COMSUB recursively using the main shell parser and lexer * a COMSUB recursively using the main shell parser and lexer
*/ */
char * char *
yyrecursive(int subtype) yyrecursive(void)
{ {
struct op *t; struct op *t;
char *cp; char *cp;
bool old_reject; bool old_reject;
int old_symbol, old_salias, old_nesting_type; int old_symbol, old_salias;
struct ioword **old_herep; 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 */ /* tell the lexer to accept a closing parenthesis as EOD */
old_nesting_type = subshell_nesting_type; ++subshell_nesting_level;
subshell_nesting_type = etok;
/* push reject state, parse recursively, pop reject state */ /* push reject state, parse recursively, pop reject state */
old_reject = reject; old_reject = reject;
@ -1150,7 +1135,7 @@ yyrecursive(int subtype)
old_salias = sALIAS; old_salias = sALIAS;
sALIAS = 0; sALIAS = 0;
/* we use TPAREN as a helper container here */ /* we use TPAREN as a helper container here */
t = nested(TPAREN, stok, etok); t = nested(TPAREN, '(', ')');
sALIAS = old_salias; sALIAS = old_salias;
herep = old_herep; herep = old_herep;
reject = old_reject; reject = old_reject;
@ -1160,6 +1145,6 @@ yyrecursive(int subtype)
cp = snptreef(NULL, 0, "%T", t->left); cp = snptreef(NULL, 0, "%T", t->left);
tfree(t, ATEMP); tfree(t, ATEMP);
subshell_nesting_type = old_nesting_type; --subshell_nesting_level;
return (cp); return (cp);
} }

10
tree.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.63 2012/07/30 21:37:17 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.64 2012/08/17 18:34:25 tg Exp $");
#define INDENT 8 #define INDENT 8
@ -342,10 +342,6 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
shf_putc(c, shf); shf_putc(c, shf);
shf_puts(cs, shf); shf_puts(cs, shf);
break; break;
case FUNSUB:
shf_puts("${ ", shf);
cs = ";}";
goto pSUB;
case EXPRSUB: case EXPRSUB:
shf_puts("$((", shf); shf_puts("$((", shf);
cs = "))"; cs = "))";
@ -585,7 +581,6 @@ wdscan(const char *wp, int c)
wp++; wp++;
break; break;
case COMSUB: case COMSUB:
case FUNSUB:
case EXPRSUB: case EXPRSUB:
while (*wp++ != 0) while (*wp++ != 0)
; ;
@ -825,9 +820,6 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
closeandout: closeandout:
shf_putc('>', shf); shf_putc('>', shf);
break; break;
case FUNSUB:
shf_puts("FUNSUB<", shf);
goto dumpsub;
case EXPRSUB: case EXPRSUB:
shf_puts("EXPRSUB<", shf); shf_puts("EXPRSUB<", shf);
goto dumpsub; goto dumpsub;