better parsing for x=(…) – bug noted by Frank Terbeck
This commit is contained in:
parent
e0a913181b
commit
b3d38f9cdf
33
check.t
33
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.457 2011/05/29 16:38:58 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.458 2011/06/04 16:11:16 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 $
|
||||
@ -6132,7 +6132,7 @@ stdin:
|
||||
expected-stdout:
|
||||
5|a|$v|c d|$v|b|
|
||||
---
|
||||
name: arrays-2
|
||||
name: arrays-2a
|
||||
description:
|
||||
Check if bash-style arrays work as expected
|
||||
category: !smksh
|
||||
@ -6143,6 +6143,33 @@ stdin:
|
||||
expected-stdout:
|
||||
5|a|$v|c d|$v|b|
|
||||
---
|
||||
name: arrays-2b
|
||||
description:
|
||||
Check if bash-style arrays work as expected, with newlines
|
||||
category: !smksh
|
||||
stdin:
|
||||
test -n "$ZSH_VERSION" && setopt KSH_ARRAYS
|
||||
v="e f"
|
||||
foo=(a
|
||||
bc
|
||||
d \$v "$v" '$v' g
|
||||
)
|
||||
printf '%s|' "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
|
||||
foo=(a\
|
||||
bc
|
||||
d \$v "$v" '$v' g
|
||||
)
|
||||
printf '%s|' "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
|
||||
foo=(a\
|
||||
bc\\
|
||||
d \$v "$v" '$v'
|
||||
g)
|
||||
printf '%s|' "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
|
||||
expected-stdout:
|
||||
7|a|bc|d|$v|e f|$v|g|
|
||||
7|a|bc|d|$v|e f|$v|g|
|
||||
6|abc\|d|$v|e f|$v|g||
|
||||
---
|
||||
name: arrays-3
|
||||
description:
|
||||
Check if array bounds are uint32_t
|
||||
@ -7675,7 +7702,7 @@ expected-stdout:
|
||||
a+=b
|
||||
;|
|
||||
(*)
|
||||
eval set -A c+ -- d e
|
||||
set -A c+ -- d e
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
50
lex.c
50
lex.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.152 2011/05/29 06:19:27 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.153 2011/06/04 16:11:18 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
@ -41,9 +41,8 @@ __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.152 2011/05/29 06:19:27 tg Exp $");
|
||||
#define SHEREDQUOTE 11 /* parsing " in <<,<<- delimiter */
|
||||
#define SPATTERN 12 /* parsing *(...|...) pattern (*+?@!) */
|
||||
#define STBRACE 13 /* parsing ${...[#%]...} */
|
||||
#define SLETARRAY 14 /* inside =( ), just copy */
|
||||
#define SADELIM 15 /* like SBASE, looking for delimiter */
|
||||
#define SHERESTRING 16 /* parsing <<< string */
|
||||
#define SADELIM 14 /* like SBASE, looking for delimiter */
|
||||
#define SHERESTRING 15 /* parsing <<< string */
|
||||
#define SINVALID 255 /* invalid state */
|
||||
|
||||
struct sretrace_info {
|
||||
@ -220,12 +219,6 @@ yylex(int cf)
|
||||
*wp++ = OQUOTE;
|
||||
state = SLETPAREN;
|
||||
statep->nparen = 0;
|
||||
#ifndef MKSH_SMALL
|
||||
} else if (cf & LETARRAY) {
|
||||
state = SLETARRAY;
|
||||
statep->nparen = 0;
|
||||
PUSH_SRETRACE();
|
||||
#endif
|
||||
} else {
|
||||
/* normal lexing */
|
||||
state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
|
||||
@ -245,7 +238,7 @@ yylex(int cf)
|
||||
cf |= ALIAS;
|
||||
}
|
||||
|
||||
/* Initial state: one of SWORD SLETPAREN SLETARRAY SHEREDELIM SBASE */
|
||||
/* Initial state: one of SWORD SLETPAREN SHEREDELIM SBASE */
|
||||
statep->type = state;
|
||||
|
||||
/* check for here string */
|
||||
@ -779,30 +772,6 @@ yylex(int cf)
|
||||
++statep->nparen;
|
||||
goto Sbase2;
|
||||
|
||||
#ifndef MKSH_SMALL
|
||||
/* LETARRAY: =( ... ) */
|
||||
case SLETARRAY:
|
||||
if (c == '('/*)*/)
|
||||
++statep->nparen;
|
||||
else if (c == /*(*/')') {
|
||||
if (statep->nparen-- == 0) {
|
||||
POP_SRETRACE();
|
||||
/* drop trailing paren */
|
||||
c = strlen(dp = sp) - 1;
|
||||
XcheckN(ws, wp, c * 2);
|
||||
while (c--) {
|
||||
*wp++ = CHAR;
|
||||
*wp++ = *dp++;
|
||||
}
|
||||
afree(sp, ATEMP);
|
||||
/* assert: c == 0 */
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
/* reuse existing state machine */
|
||||
goto Sbase2;
|
||||
#endif
|
||||
|
||||
/* <<< delimiter */
|
||||
case SHERESTRING:
|
||||
if (c == '\\') {
|
||||
@ -934,11 +903,6 @@ yylex(int cf)
|
||||
/* XXX figure out what is missing */
|
||||
yyerror("no closing quote\n");
|
||||
|
||||
#ifndef MKSH_SMALL
|
||||
if (state == SLETARRAY && statep->nparen != -1)
|
||||
yyerror("%s: %s\n", T_synerr, "missing )");
|
||||
#endif
|
||||
|
||||
/* This done to avoid tests for SHEREDELIM wherever SBASE tested */
|
||||
if (state == SHEREDELIM || state == SHERESTRING)
|
||||
state = SBASE;
|
||||
@ -1046,11 +1010,7 @@ yylex(int cf)
|
||||
*wp++ = EOS;
|
||||
yylval.cp = Xclose(ws, wp);
|
||||
if (state == SWORD || state == SLETPAREN
|
||||
/* XXX ONEWORD? */
|
||||
#ifndef MKSH_SMALL
|
||||
|| state == SLETARRAY
|
||||
#endif
|
||||
)
|
||||
/* XXX ONEWORD? */)
|
||||
return (LWORD);
|
||||
|
||||
/* unget terminator */
|
||||
|
5
sh.h
5
sh.h
@ -151,7 +151,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.471 2011/05/29 16:31:42 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.472 2011/06/04 16:11:19 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R40 2011/05/29"
|
||||
|
||||
@ -1413,9 +1413,8 @@ typedef union {
|
||||
#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
|
||||
#define LQCHAR BIT(10) /* source string contains QCHAR */
|
||||
#define HEREDOC BIT(11) /* parsing a here document */
|
||||
#define LETARRAY BIT(12) /* copy expression inside =( ) */
|
||||
|
||||
#define HERES 10 /* max << in line */
|
||||
#define HERES 10 /* max number of << in line */
|
||||
|
||||
#undef CTRL
|
||||
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
|
||||
|
49
syn.c
49
syn.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.65 2011/05/29 02:18:57 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.66 2011/06/04 16:11:20 tg Exp $");
|
||||
|
||||
extern short subshell_nesting_level;
|
||||
|
||||
@ -292,6 +292,11 @@ get_command(int cf)
|
||||
break;
|
||||
|
||||
case '(':
|
||||
#ifndef MKSH_SMALL
|
||||
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
||||
XPsize(vars) == 1 && is_wdvarassign(yylval.cp))
|
||||
goto is_wdarrassign;
|
||||
#endif
|
||||
/*
|
||||
* Check for "> foo (echo hi)" which AT&T ksh
|
||||
* allows (not POSIX, but not disallowed)
|
||||
@ -301,11 +306,7 @@ get_command(int cf)
|
||||
ACCEPT;
|
||||
goto Subshell;
|
||||
}
|
||||
#ifndef MKSH_SMALL
|
||||
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
||||
XPsize(vars) == 1 && is_wdvarassign(yylval.cp))
|
||||
goto is_wdarrassign;
|
||||
#endif
|
||||
|
||||
/* must be a function */
|
||||
if (iopn != 0 || XPsize(args) != 1 ||
|
||||
XPsize(vars) != 0)
|
||||
@ -318,37 +319,37 @@ get_command(int cf)
|
||||
is_wdarrassign:
|
||||
{
|
||||
static const char set_cmd0[] = {
|
||||
CHAR, 'e', CHAR, 'v',
|
||||
CHAR, 'a', CHAR, 'l', EOS
|
||||
CHAR, 's', CHAR, 'e',
|
||||
CHAR, 't', EOS
|
||||
};
|
||||
static const char set_cmd1[] = {
|
||||
CHAR, 's', CHAR, 'e',
|
||||
CHAR, 't', CHAR, ' ',
|
||||
CHAR, '-', CHAR, 'A', EOS
|
||||
};
|
||||
static const char set_cmd2[] = {
|
||||
CHAR, '-', CHAR, '-', EOS
|
||||
};
|
||||
char *tcp;
|
||||
XPfree(vars);
|
||||
XPinit(vars, 16);
|
||||
/*
|
||||
* we know (or rather hope) that yylval.cp
|
||||
* contains a string "varname="
|
||||
*/
|
||||
tcp = wdcopy(yylval.cp, ATEMP);
|
||||
tcp[wdscan(tcp, EOS) - tcp - 3] = EOS;
|
||||
/* now make an array assignment command */
|
||||
t = newtp(TCOM);
|
||||
t->lineno = source->line;
|
||||
|
||||
ACCEPT;
|
||||
|
||||
/* manipulate the vars string */
|
||||
tcp = *(--vars.cur);
|
||||
/* 'varname=' -> 'varname' */
|
||||
tcp[wdscan(tcp, EOS) - tcp - 3] = EOS;
|
||||
|
||||
/* construct new args strings */
|
||||
XPput(args, wdcopy(set_cmd0, ATEMP));
|
||||
XPput(args, wdcopy(set_cmd1, ATEMP));
|
||||
XPput(args, tcp);
|
||||
XPput(args, wdcopy(set_cmd2, ATEMP));
|
||||
musthave(LWORD,LETARRAY);
|
||||
XPput(args, yylval.cp);
|
||||
break;
|
||||
|
||||
/* slurp in words till closing paren */
|
||||
while (token(CONTIN) == LWORD)
|
||||
XPput(args, yylval.cp);
|
||||
if (symbol != /*(*/ ')')
|
||||
syntaxerr(NULL);
|
||||
|
||||
goto Leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user