allow “function stop () {” (bashism, an evil one)

This commit is contained in:
tg
2009-09-19 18:36:59 +00:00
parent e0f000fb83
commit 7806fe510a
3 changed files with 57 additions and 10 deletions

29
check.t
View File

@@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.305 2009/09/07 17:24:47 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.306 2009/09/19 18:36:57 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 $
@@ -5256,6 +5256,33 @@ expected-stdout:
bar bar
rab rab
--- ---
name: bash-function-parens
description:
ensure the keyword function is ignored when preceding
POSIX style function declarations (bashism)
stdin:
mk() {
echo '#!'"$__progname"
echo "$1 {"
echo ' echo "bar='\''$0'\'\"
echo '}'
echo ${2:-foo}
}
mk 'function foo' >f-korn
mk 'foo ()' >f-dash
mk 'function foo ()' >f-bash
mk 'function stop ()' stop >f-stop
chmod +x f-*
echo "korn: $(./f-korn)"
echo "dash: $(./f-dash)"
echo "bash: $(./f-bash)"
echo "stop: $(./f-stop)"
expected-stdout:
korn: bar='foo'
dash: bar='./f-dash'
bash: bar='./f-bash'
stop: bar='./f-stop'
---
name: integer-base-one-1 name: integer-base-one-1
description: description:
check if the use of fake integer base 1 works check if the use of fake integer base 1 works

11
mksh.1
View File

@@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.185 2009/09/19 15:16:04 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.186 2009/09/19 18:36:58 tg Exp $
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $ .\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
@@ -749,6 +749,15 @@ below).
Whitespace (space or tab) after Whitespace (space or tab) after
.Ar name .Ar name
will be ignored most of the time. will be ignored most of the time.
.It Xo function Ar name Ns ()
.No { Ar list ; No }
.Xc
The same as
.Ar name Ns ()
.Pq Nm bash Ns ism .
The
.Ic function
keyword is ignored.
.It Xo Ic time Op Fl p .It Xo Ic time Op Fl p
.Op Ar pipeline .Op Ar pipeline
.Xc .Xc

27
syn.c
View File

@@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.41 2009/08/28 20:30:59 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.42 2009/09/19 18:36:59 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) */
@@ -41,7 +41,7 @@ static struct op *thenpart(void);
static struct op *elsepart(void); static struct op *elsepart(void);
static struct op *caselist(void); static struct op *caselist(void);
static struct op *casepart(int); static struct op *casepart(int);
static struct op *function_body(char *, int); static struct op *function_body(char *, bool);
static char **wordlist(void); static char **wordlist(void);
static struct op *block(int, struct op *, struct op *, char **); static struct op *block(int, struct op *, struct op *, char **);
static struct op *newtp(int); static struct op *newtp(int);
@@ -595,7 +595,7 @@ casepart(int endtok)
static struct op * static struct op *
function_body(char *name, function_body(char *name,
int ksh_func) /* function foo { ... } vs foo() { .. } */ bool ksh_func) /* function foo { ... } vs foo() { .. } */
{ {
char *sname, *p; char *sname, *p;
struct op *t; struct op *t;
@@ -612,21 +612,32 @@ function_body(char *name,
if (ctype(*p, C_QUOTE) || *p == '=') if (ctype(*p, C_QUOTE) || *p == '=')
yyerror("%s: invalid function name\n", sname); yyerror("%s: invalid function name\n", sname);
t = newtp(TFUNCT);
t->str = sname;
t->u.ksh_func = ksh_func;
t->lineno = source->line;
/* Note that POSIX allows only compound statements after foo(), sh and /* Note that POSIX allows only compound statements after foo(), sh and
* AT&T ksh allow any command, go with the later since it shouldn't * AT&T ksh allow any command, go with the later since it shouldn't
* break anything. However, for function foo, AT&T ksh only accepts * break anything. However, for function foo, AT&T ksh only accepts
* an open-brace. * an open-brace.
*/ */
if (ksh_func) { if (ksh_func) {
if (tpeek(CONTIN|KEYWORD|ALIAS) == '(' /* ) */) {
struct tbl *tp;
/* function foo () { */
ACCEPT;
musthave(')', 0);
/* degrade to POSIX function */
ksh_func = false;
if ((tp = ktsearch(&aliases, sname, hash(sname))))
ktdelete(tp);
}
musthave('{', CONTIN|KEYWORD|ALIAS); /* } */ musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
REJECT; REJECT;
} }
t = newtp(TFUNCT);
t->str = sname;
t->u.ksh_func = ksh_func;
t->lineno = source->line;
old_func_parse = e->flags & EF_FUNC_PARSE; old_func_parse = e->flags & EF_FUNC_PARSE;
e->flags |= EF_FUNC_PARSE; e->flags |= EF_FUNC_PARSE;
if ((t->left = get_command(CONTIN)) == NULL) { if ((t->left = get_command(CONTIN)) == NULL) {