From b3d38f9cdf1cfe439035521c3bce600e9e1f8b05 Mon Sep 17 00:00:00 2001 From: tg Date: Sat, 4 Jun 2011 16:11:20 +0000 Subject: [PATCH] =?UTF-8?q?better=20parsing=20for=20x=3D(=E2=80=A6)=20?= =?UTF-8?q?=E2=80=93=20bug=20noted=20by=20Frank=20Terbeck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check.t | 33 ++++++++++++++++++++++++++++++--- lex.c | 50 +++++--------------------------------------------- sh.h | 5 ++--- syn.c | 49 +++++++++++++++++++++++++------------------------ 4 files changed, 62 insertions(+), 75 deletions(-) diff --git a/check.t b/check.t index d3f9d2f..ecd0ec3 100644 --- a/check.t +++ b/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 } diff --git a/lex.c b/lex.c index 0607bb8..0f924a0 100644 --- a/lex.c +++ b/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 */ diff --git a/sh.h b/sh.h index f0a2b36..d390dd9 100644 --- a/sh.h +++ b/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 */ diff --git a/syn.c b/syn.c index 16aa5b2..06796f2 100644 --- a/syn.c +++ b/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