with accepted interpretation (*sigh*); merge VARASN|ARRAYVAR→CMDASN
This commit is contained in:
tg
2016-01-19 23:12:15 +00:00
parent 44be0bdb0b
commit 046d8e5b7a
6 changed files with 57 additions and 30 deletions

20
check.t
View File

@@ -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
View File

@@ -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);

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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);