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: 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/08/03
@(#)MIRBSD KSH R40 2012/08/17
description:
Check version of shell.
stdin:
@ -38,7 +38,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
@(#)LEGACY KSH R40 2012/08/03
@(#)LEGACY KSH R40 2012/08/17
description:
Check version of legacy shell.
stdin:
@ -9505,26 +9505,6 @@ 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

View File

@ -1,5 +1,5 @@
# $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,
# 2011, 2012
@ -30,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)} || \

32
eval.c
View File

@ -23,7 +23,7 @@
#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
@ -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 *, int);
static int comsub(Expand *, const char *);
static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, int);
static void globit(XString *, char **, char *, XPtrV *, int);
@ -278,27 +278,18 @@ expand(const char *cp, /* input word */
quote = st->quotew;
continue;
case COMSUB:
case FUNSUB:
tilde_ok = 0;
if (f & DONTRUNCOMMAND) {
word = IFS_WORD;
*dp++ = '$';
if (c == FUNSUB) {
*dp++ = '{';
*dp++ = ' ';
} else
*dp++ = '(';
*dp++ = '(';
while (*sp != '\0') {
Xcheck(ds, dp);
*dp++ = *sp++;
}
if (c == FUNSUB) {
*dp++ = ';';
*dp++ = '}';
} else
*dp++ = ')';
*dp++ = ')';
} else {
type = comsub(&x, sp, c);
type = comsub(&x, sp);
if (type == XCOM && (f&DOBLANK))
doblank++;
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.
*/
static int
comsub(Expand *xp, const char *cp, int fn)
comsub(Expand *xp, const char *cp)
{
Source *s, *sold;
struct op *t;
@ -1327,14 +1318,11 @@ comsub(Expand *xp, const char *cp, int fn)
ksh_dup2(pv[1], 1, false);
close(pv[1]);
}
execute(t, XXCOM | XPIPEO |
(fn == FUNSUB ? XERROK : XFORK), NULL);
execute(t, XXCOM | XPIPEO | XFORK, NULL);
restfd(1, ofd1);
if (fn != FUNSUB) {
startlast();
/* waitlast() */
xp->split = true;
}
startlast();
/* waitlast() */
xp->split = true;
}
xp->u.shf = shf;

28
lex.c
View File

@ -23,7 +23,7 @@
#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
@ -109,7 +109,7 @@ void yyskiputf8bom(void);
static int backslash_skip;
static int ignore_backslash_newline;
static struct sretrace_info *retrace_info;
int subshell_nesting_type = 0;
uint8_t subshell_nesting_level = 0;
/* optimised getsc_bn() */
#define o_getsc() (*source->str != '\0' && *source->str != '\\' && \
@ -262,11 +262,6 @@ 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) {
@ -400,27 +395,14 @@ yylex(int cf)
} else {
ungetsc(c);
subst_command:
c = COMSUB;
subst_command2:
sp = yyrecursive(c);
sp = yyrecursive();
cz = strlen(sp) + 1;
XcheckN(ws, wp, cz);
*wp++ = c;
*wp++ = COMSUB;
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);
@ -1189,7 +1171,7 @@ readhere(struct ioword *iop)
/* end of here document marker, what to do? */
switch (c) {
case /*(*/ ')':
if (!subshell_nesting_type)
if (!subshell_nesting_level)
/*-
* not allowed outside $(...) or (...)
* => 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 $
.\"-
.\" 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: August 3 2012 $
.Dd $Mdocdate: August 17 2012 $
.\"
.\" 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 \&)
or (deprecated)
.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
@ -1231,8 +1226,6 @@ 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

7
sh.h
View File

@ -157,9 +157,9 @@
#endif
#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
#define MKSH_VERSION "R40 2012/08/03"
#define MKSH_VERSION "R40 2012/08/17"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -1283,7 +1283,6 @@ 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
@ -1906,7 +1905,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(int);
char *yyrecursive(void);
/* tree.c */
void fptreef(struct shf *, int, const char *, ...);
char *snptreef(char *, ssize_t, const char *, ...);

37
syn.c
View File

@ -23,11 +23,12 @@
#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 uint8_t subshell_nesting_level;
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
int start_line; /* line nesting began on */
@ -363,15 +364,12 @@ get_command(int cf)
Leave:
break;
case '(': /*)*/ {
int subshell_nesting_type_saved;
case '(': /*)*/
Subshell:
subshell_nesting_type_saved = subshell_nesting_type;
subshell_nesting_type = ')';
++subshell_nesting_level;
t = nested(TPAREN, '(', ')');
subshell_nesting_type = subshell_nesting_type_saved;
--subshell_nesting_level;
break;
}
case '{': /*}*/
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
*/
char *
yyrecursive(int subtype)
yyrecursive(void)
{
struct op *t;
char *cp;
bool old_reject;
int old_symbol, old_salias, old_nesting_type;
int old_symbol, old_salias;
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 */
old_nesting_type = subshell_nesting_type;
subshell_nesting_type = etok;
++subshell_nesting_level;
/* push reject state, parse recursively, pop reject state */
old_reject = reject;
@ -1150,7 +1135,7 @@ yyrecursive(int subtype)
old_salias = sALIAS;
sALIAS = 0;
/* we use TPAREN as a helper container here */
t = nested(TPAREN, stok, etok);
t = nested(TPAREN, '(', ')');
sALIAS = old_salias;
herep = old_herep;
reject = old_reject;
@ -1160,6 +1145,6 @@ yyrecursive(int subtype)
cp = snptreef(NULL, 0, "%T", t->left);
tfree(t, ATEMP);
subshell_nesting_type = old_nesting_type;
--subshell_nesting_level;
return (cp);
}

10
tree.c
View File

@ -23,7 +23,7 @@
#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
@ -342,10 +342,6 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
shf_putc(c, shf);
shf_puts(cs, shf);
break;
case FUNSUB:
shf_puts("${ ", shf);
cs = ";}";
goto pSUB;
case EXPRSUB:
shf_puts("$((", shf);
cs = "))";
@ -585,7 +581,6 @@ wdscan(const char *wp, int c)
wp++;
break;
case COMSUB:
case FUNSUB:
case EXPRSUB:
while (*wp++ != 0)
;
@ -825,9 +820,6 @@ 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;