align with future POSIX on http://austingroupbugs.net/view.php?id=351
with accepted interpretation (*sigh*); merge VARASN|ARRAYVAR→CMDASN
This commit is contained in:
20
check.t
20
check.t
@@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.719 2016/01/14 23:19:12 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.720 2016/01/19 23:12:10 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 R52 2016/01/14
|
@(#)MIRBSD KSH R52 2016/01/19
|
||||||
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 R52 2016/01/14
|
@(#)LEGACY KSH R52 2016/01/19
|
||||||
description:
|
description:
|
||||||
Check version of legacy shell.
|
Check version of legacy shell.
|
||||||
stdin:
|
stdin:
|
||||||
@@ -6592,12 +6592,24 @@ description:
|
|||||||
env-setup: !HOME=/sweet!
|
env-setup: !HOME=/sweet!
|
||||||
stdin:
|
stdin:
|
||||||
echo ${A=a=}~ b=~ c=d~ ~
|
echo ${A=a=}~ b=~ c=d~ ~
|
||||||
|
export e=~ f=d~
|
||||||
|
command command export g=~ h=d~
|
||||||
|
echo ". $e . $f ."
|
||||||
|
echo ". $g . $h ."
|
||||||
set -o posix
|
set -o posix
|
||||||
unset A
|
unset A e f g h
|
||||||
echo ${A=a=}~ b=~ c=d~ ~
|
echo ${A=a=}~ b=~ c=d~ ~
|
||||||
|
export e=~ f=d~
|
||||||
|
command command export g=~ h=d~
|
||||||
|
echo ". $e . $f ."
|
||||||
|
echo ". $g . $h ."
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
a=/sweet b=/sweet c=d~ /sweet
|
a=/sweet b=/sweet c=d~ /sweet
|
||||||
|
. /sweet . d~ .
|
||||||
|
. /sweet . d~ .
|
||||||
a=~ b=~ c=d~ /sweet
|
a=~ b=~ c=d~ /sweet
|
||||||
|
. /sweet . d~ .
|
||||||
|
. /sweet . d~ .
|
||||||
---
|
---
|
||||||
name: tilde-expand-2
|
name: tilde-expand-2
|
||||||
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.179 2016/01/14 22:30:43 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.180 2016/01/19 23:12:12 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* string expansion
|
* string expansion
|
||||||
@@ -1324,7 +1324,7 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
|
|||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if ((io->ioflag & IOTYPE) != IOREAD)
|
if ((io->ioflag & IOTYPE) != IOREAD)
|
||||||
errorf("%s: %s", "funny $() command",
|
errorf("%s: %s", T_funny_command,
|
||||||
snptreef(NULL, 32, "%R", io));
|
snptreef(NULL, 32, "%R", io));
|
||||||
shf = shf_open(name = evalstr(io->ioname, DOTILDE), O_RDONLY,
|
shf = shf_open(name = evalstr(io->ioname, DOTILDE), O_RDONLY,
|
||||||
0, SHF_MAPHI | SHF_CLEXEC);
|
0, SHF_MAPHI | SHF_CLEXEC);
|
||||||
|
4
funcs.c
4
funcs.c
@@ -38,7 +38,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.290 2016/01/14 22:49:31 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.291 2016/01/19 23:12:13 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@@ -103,7 +103,7 @@ const struct builtin mkshbuiltins[] = {
|
|||||||
{"cd", c_cd},
|
{"cd", c_cd},
|
||||||
/* dash compatibility hack */
|
/* dash compatibility hack */
|
||||||
{"chdir", c_cd},
|
{"chdir", c_cd},
|
||||||
{"command", c_command},
|
{Tcommand, c_command},
|
||||||
{"*=continue", c_brkcont},
|
{"*=continue", c_brkcont},
|
||||||
{"echo", c_print},
|
{"echo", c_print},
|
||||||
{"*=eval", c_eval},
|
{"*=eval", c_eval},
|
||||||
|
6
lex.c
6
lex.c
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.216 2016/01/19 23:09:48 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.217 2016/01/19 23:12:14 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* states while lexing word
|
* states while lexing word
|
||||||
@@ -269,7 +269,7 @@ yylex(int cf)
|
|||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SBASE:
|
case SBASE:
|
||||||
if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
|
if (c == '[' && (cf & CMDASN)) {
|
||||||
/* temporary */
|
/* temporary */
|
||||||
*wp = EOS;
|
*wp = EOS;
|
||||||
if (is_wdvarname(Xstring(ws, wp), false)) {
|
if (is_wdvarname(Xstring(ws, wp), false)) {
|
||||||
@@ -1092,7 +1092,7 @@ yylex(int cf)
|
|||||||
}
|
}
|
||||||
} else if (cf & ALIAS) {
|
} else if (cf & ALIAS) {
|
||||||
/* retain typeset et al. even when quoted */
|
/* retain typeset et al. even when quoted */
|
||||||
if (assign_command((dp = wdstrip(yylval.cp, 0))))
|
if (assign_command((dp = wdstrip(yylval.cp, 0)), true))
|
||||||
strlcpy(ident, dp, sizeof(ident));
|
strlcpy(ident, dp, sizeof(ident));
|
||||||
afree(dp, ATEMP);
|
afree(dp, ATEMP);
|
||||||
}
|
}
|
||||||
|
13
sh.h
13
sh.h
@@ -175,9 +175,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.755 2016/01/14 23:18:11 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.756 2016/01/19 23:12:14 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R52 2016/01/14"
|
#define MKSH_VERSION "R52 2016/01/19"
|
||||||
|
|
||||||
/* arithmetic types: C implementation */
|
/* arithmetic types: C implementation */
|
||||||
#if !HAVE_CAN_INTTYPES
|
#if !HAVE_CAN_INTTYPES
|
||||||
@@ -864,6 +864,8 @@ EXTERN const char Tgbuiltin[] E_INIT("=builtin");
|
|||||||
#define Tbuiltin (Tgbuiltin + 1) /* "builtin" */
|
#define Tbuiltin (Tgbuiltin + 1) /* "builtin" */
|
||||||
EXTERN const char T_function[] E_INIT(" function");
|
EXTERN const char T_function[] E_INIT(" function");
|
||||||
#define Tfunction (T_function + 1) /* "function" */
|
#define Tfunction (T_function + 1) /* "function" */
|
||||||
|
EXTERN const char T_funny_command[] E_INIT("funny $() command");
|
||||||
|
#define Tcommand (T_funny_command + 10) /* "command" */
|
||||||
EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
|
EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
|
||||||
#define TC_IFSWS (TC_LEX1 + 7) /* space tab newline */
|
#define TC_IFSWS (TC_LEX1 + 7) /* space tab newline */
|
||||||
|
|
||||||
@@ -1632,13 +1634,12 @@ typedef union {
|
|||||||
#define ALIAS BIT(2) /* recognise alias */
|
#define ALIAS BIT(2) /* recognise alias */
|
||||||
#define KEYWORD BIT(3) /* recognise keywords */
|
#define KEYWORD BIT(3) /* recognise keywords */
|
||||||
#define LETEXPR BIT(4) /* get expression inside (( )) */
|
#define LETEXPR BIT(4) /* get expression inside (( )) */
|
||||||
#define VARASN BIT(5) /* check for var=word */
|
#define CMDASN BIT(5) /* parse x[1 & 2] as one word, for typeset */
|
||||||
#define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */
|
#define HEREDOC BIT(6) /* parsing a here document body */
|
||||||
#define ESACONLY BIT(7) /* only accept esac keyword */
|
#define ESACONLY BIT(7) /* only accept esac keyword */
|
||||||
#define CMDWORD BIT(8) /* parsing simple command (alias related) */
|
#define CMDWORD BIT(8) /* parsing simple command (alias related) */
|
||||||
#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
|
#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
|
||||||
#define LQCHAR BIT(10) /* source string contains QCHAR */
|
#define LQCHAR BIT(10) /* source string contains QCHAR */
|
||||||
#define HEREDOC BIT(11) /* parsing a here document body */
|
|
||||||
|
|
||||||
#define HERES 10 /* max number of << in line */
|
#define HERES 10 /* max number of << in line */
|
||||||
|
|
||||||
@@ -1989,7 +1990,7 @@ char *shf_smprintf(const char *, ...)
|
|||||||
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
|
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
|
||||||
MKSH_A_FORMAT(__printf__, 2, 0);
|
MKSH_A_FORMAT(__printf__, 2, 0);
|
||||||
/* syn.c */
|
/* syn.c */
|
||||||
int assign_command(const char *);
|
int assign_command(const char *, bool);
|
||||||
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 *);
|
||||||
|
40
syn.c
40
syn.c
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.108 2016/01/14 19:52:20 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.109 2016/01/19 23:12:15 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) */
|
||||||
@@ -272,7 +272,6 @@ get_command(int cf)
|
|||||||
int c, iopn = 0, syniocf, lno;
|
int c, iopn = 0, syniocf, lno;
|
||||||
struct ioword *iop, **iops;
|
struct ioword *iop, **iops;
|
||||||
XPtrV args, vars;
|
XPtrV args, vars;
|
||||||
char *tcp;
|
|
||||||
struct nesting_state old_nesting;
|
struct nesting_state old_nesting;
|
||||||
|
|
||||||
/* NUFILE is small enough to leave this addition unchecked */
|
/* NUFILE is small enough to leave this addition unchecked */
|
||||||
@@ -281,7 +280,7 @@ get_command(int cf)
|
|||||||
XPinit(vars, 16);
|
XPinit(vars, 16);
|
||||||
|
|
||||||
syniocf = KEYWORD|sALIAS;
|
syniocf = KEYWORD|sALIAS;
|
||||||
switch (c = token(cf|KEYWORD|sALIAS|VARASN)) {
|
switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) {
|
||||||
default:
|
default:
|
||||||
REJECT;
|
REJECT;
|
||||||
afree(iops, ATEMP);
|
afree(iops, ATEMP);
|
||||||
@@ -296,9 +295,18 @@ get_command(int cf)
|
|||||||
syniocf &= ~(KEYWORD|sALIAS);
|
syniocf &= ~(KEYWORD|sALIAS);
|
||||||
t = newtp(TCOM);
|
t = newtp(TCOM);
|
||||||
t->lineno = source->line;
|
t->lineno = source->line;
|
||||||
|
goto get_command_begin;
|
||||||
while (/* CONSTCOND */ 1) {
|
while (/* CONSTCOND */ 1) {
|
||||||
cf = (t->u.evalflags ? ARRAYVAR : 0) |
|
bool check_assign_cmd;
|
||||||
(XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD);
|
|
||||||
|
if (XPsize(args) == 0) {
|
||||||
|
get_command_begin:
|
||||||
|
check_assign_cmd = true;
|
||||||
|
cf = sALIAS | CMDASN;
|
||||||
|
} else if (t->u.evalflags)
|
||||||
|
cf = CMDWORD | CMDASN;
|
||||||
|
else
|
||||||
|
cf = CMDWORD;
|
||||||
switch (tpeek(cf)) {
|
switch (tpeek(cf)) {
|
||||||
case REDIR:
|
case REDIR:
|
||||||
while ((iop = synio(cf)) != NULL) {
|
while ((iop = synio(cf)) != NULL) {
|
||||||
@@ -316,9 +324,12 @@ get_command(int cf)
|
|||||||
* dubious but AT&T ksh acts this way
|
* dubious but AT&T ksh acts this way
|
||||||
*/
|
*/
|
||||||
if (iopn == 0 && XPsize(vars) == 0 &&
|
if (iopn == 0 && XPsize(vars) == 0 &&
|
||||||
XPsize(args) == 0 &&
|
check_assign_cmd) {
|
||||||
assign_command(ident))
|
if (assign_command(ident, false))
|
||||||
t->u.evalflags = DOVACHECK;
|
t->u.evalflags = DOVACHECK;
|
||||||
|
else if (strcmp(ident, Tcommand) != 0)
|
||||||
|
check_assign_cmd = false;
|
||||||
|
}
|
||||||
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
||||||
is_wdvarassign(yylval.cp))
|
is_wdvarassign(yylval.cp))
|
||||||
XPput(vars, yylval.cp);
|
XPput(vars, yylval.cp);
|
||||||
@@ -329,6 +340,8 @@ get_command(int cf)
|
|||||||
case '(' /*)*/:
|
case '(' /*)*/:
|
||||||
if (XPsize(args) == 0 && XPsize(vars) == 1 &&
|
if (XPsize(args) == 0 && XPsize(vars) == 1 &&
|
||||||
is_wdvarassign(yylval.cp)) {
|
is_wdvarassign(yylval.cp)) {
|
||||||
|
char *tcp;
|
||||||
|
|
||||||
/* wdarrassign: foo=(bar) */
|
/* wdarrassign: foo=(bar) */
|
||||||
ACCEPT;
|
ACCEPT;
|
||||||
|
|
||||||
@@ -432,7 +445,7 @@ get_command(int cf)
|
|||||||
case FOR:
|
case FOR:
|
||||||
case SELECT:
|
case SELECT:
|
||||||
t = newtp((c == FOR) ? TFOR : TSELECT);
|
t = newtp((c == FOR) ? TFOR : TSELECT);
|
||||||
musthave(LWORD, ARRAYVAR);
|
musthave(LWORD, CMDASN);
|
||||||
if (!is_wdvarname(yylval.cp, true))
|
if (!is_wdvarname(yylval.cp, true))
|
||||||
yyerror("%s: %s\n", c == FOR ? "for" : Tselect,
|
yyerror("%s: %s\n", c == FOR ? "for" : Tselect,
|
||||||
"bad identifier");
|
"bad identifier");
|
||||||
@@ -573,7 +586,7 @@ elsepart(void)
|
|||||||
{
|
{
|
||||||
struct op *t;
|
struct op *t;
|
||||||
|
|
||||||
switch (token(KEYWORD|sALIAS|VARASN)) {
|
switch (token(KEYWORD|sALIAS|CMDASN)) {
|
||||||
case ELSE:
|
case ELSE:
|
||||||
if ((t = c_list(true)) == NULL)
|
if ((t = c_list(true)) == NULL)
|
||||||
syntaxerr(NULL);
|
syntaxerr(NULL);
|
||||||
@@ -944,13 +957,14 @@ compile(Source *s, bool skiputf8bom)
|
|||||||
* $
|
* $
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
assign_command(const char *s)
|
assign_command(const char *s, bool docommand)
|
||||||
{
|
{
|
||||||
if (!*s)
|
if (!*s)
|
||||||
return (0);
|
return (0);
|
||||||
return ((strcmp(s, Talias) == 0) ||
|
return ((strcmp(s, Talias) == 0) ||
|
||||||
(strcmp(s, Texport) == 0) ||
|
(strcmp(s, Texport) == 0) ||
|
||||||
(strcmp(s, Treadonly) == 0) ||
|
(strcmp(s, Treadonly) == 0) ||
|
||||||
|
(docommand && (strcmp(s, Tcommand) == 0)) ||
|
||||||
(strcmp(s, Ttypeset) == 0));
|
(strcmp(s, Ttypeset) == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -992,7 +1006,7 @@ static const char db_gthan[] = { CHAR, '>', EOS };
|
|||||||
static Test_op
|
static Test_op
|
||||||
dbtestp_isa(Test_env *te, Test_meta meta)
|
dbtestp_isa(Test_env *te, Test_meta meta)
|
||||||
{
|
{
|
||||||
int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
|
int c = tpeek(CMDASN | (meta == TM_BINOP ? 0 : CONTIN));
|
||||||
bool uqword;
|
bool uqword;
|
||||||
char *save = NULL;
|
char *save = NULL;
|
||||||
Test_op ret = TO_NONOP;
|
Test_op ret = TO_NONOP;
|
||||||
@@ -1038,7 +1052,7 @@ static const char *
|
|||||||
dbtestp_getopnd(Test_env *te, Test_op op MKSH_A_UNUSED,
|
dbtestp_getopnd(Test_env *te, Test_op op MKSH_A_UNUSED,
|
||||||
bool do_eval MKSH_A_UNUSED)
|
bool do_eval MKSH_A_UNUSED)
|
||||||
{
|
{
|
||||||
int c = tpeek(ARRAYVAR);
|
int c = tpeek(CMDASN);
|
||||||
|
|
||||||
if (c != LWORD)
|
if (c != LWORD)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
Reference in New Issue
Block a user