* PATCH: fix some (z) splitting oddities
@ 2010-10-05 21:11 Peter Stephenson
2010-10-06 1:48 ` Bart Schaefer
0 siblings, 1 reply; 2+ messages in thread
From: Peter Stephenson @ 2010-10-05 21:11 UTC (permalink / raw)
To: Zsh Hackers' List
No question of these being special syntactic markers, they were just
plain wrong and inconsistent; see the new test for the cases I fixed.
I've take the easy way out when fixing them on the basis that the results
are at least consistent if not necessarily ideal.
Index: Src/hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hist.c,v
retrieving revision 1.101
diff -p -u -r1.101 hist.c
--- Src/hist.c 2 Oct 2010 21:03:04 -0000 1.101
+++ Src/hist.c 5 Oct 2010 21:04:59 -0000
@@ -2869,6 +2869,7 @@ bufferwords(LinkList list, char *buf, in
int num = 0, cur = -1, got = 0, ne = noerrs;
int owb = wb, owe = we, oadx = addedx, ozp = zleparse, onc = nocomments;
int ona = noaliases, ocs = zlemetacs, oll = zlemetall;
+ int forloop = 0;
char *p, *addedspaceptr;
if (!list)
@@ -2942,25 +2943,84 @@ bufferwords(LinkList list, char *buf, in
ctxtlex();
if (tok == ENDINPUT || tok == LEXERR)
break;
- if (tokstr && *tokstr) {
- untokenize((p = dupstring(tokstr)));
- if (ingetptr() == addedspaceptr + 1) {
- /*
- * Whoops, we've read past the space we added, probably
- * because we were expecting a terminator but when
- * it didn't turn up we shrugged our shoulders thinking
- * it might as well be a complete string anyway.
- * So remove the space. C.f. below for the case
- * where the missing terminator caused a lex error.
- * We use the same paranoid test.
- */
- int plen = strlen(p);
- if (plen && p[plen-1] == ' ' &&
- (plen == 1 || p[plen-2] != Meta))
- p[plen-1] = '\0';
+ if (tok == FOR) {
+ /*
+ * The way for (( expr1 ; expr2; expr3 )) is parsed is:
+ * - a FOR tok
+ * - a DINPAR with no tokstr
+ * - two DINPARS with tokstr's expr1, expr2.
+ * - a DOUTPAR with tokstr expr3.
+ *
+ * We'll decrement the variable forloop as we verify
+ * the various stages.
+ *
+ * Don't ask me, ma'am, I'm just the programmer.
+ */
+ forloop = 5;
+ } else {
+ switch (forloop) {
+ case 1:
+ if (tok != DOUTPAR)
+ forloop = 0;
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ if (tok != DINPAR)
+ forloop = 0;
+ break;
+
+ default:
+ /* nothing to do */
+ break;
+ }
+ }
+ if (tokstr) {
+ switch (tok) {
+ case ENVARRAY:
+ p = dyncat(tokstr, "=(");
+ break;
+
+ case DINPAR:
+ if (forloop) {
+ /* See above. */
+ p = dyncat(tokstr, ";");
+ } else {
+ /*
+ * Mathematical expressions analysed as a single
+ * word. That's correct because it behaves like
+ * double quotes. Whitespace in the middle is
+ * similarly retained, so just add the parentheses back.
+ */
+ p = tricat("((", tokstr, "))");
+ }
+ break;
+
+ default:
+ p = dupstring(tokstr);
+ break;
+ }
+ if (*p) {
+ untokenize(p);
+ if (ingetptr() == addedspaceptr + 1) {
+ /*
+ * Whoops, we've read past the space we added, probably
+ * because we were expecting a terminator but when
+ * it didn't turn up we shrugged our shoulders thinking
+ * it might as well be a complete string anyway.
+ * So remove the space. C.f. below for the case
+ * where the missing terminator caused a lex error.
+ * We use the same paranoid test.
+ */
+ int plen = strlen(p);
+ if (plen && p[plen-1] == ' ' &&
+ (plen == 1 || p[plen-2] != Meta))
+ p[plen-1] = '\0';
+ }
+ addlinknode(list, p);
+ num++;
}
- addlinknode(list, p);
- num++;
} else if (buf) {
if (IS_REDIROP(tok) && tokfd >= 0) {
char b[20];
@@ -2973,6 +3033,16 @@ bufferwords(LinkList list, char *buf, in
num++;
}
}
+ if (forloop) {
+ if (forloop == 1) {
+ /*
+ * Final "))" of for loop to match opening,
+ * since we've just added the preceding element.
+ */
+ addlinknode(list, dupstring("))"));
+ }
+ forloop--;
+ }
if (!got && !zleparse) {
got = 1;
cur = num - 1;
Index: Test/D04parameter.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/D04parameter.ztst,v
retrieving revision 1.43
diff -p -u -r1.43 D04parameter.ztst
--- Test/D04parameter.ztst 12 May 2010 10:17:58 -0000 1.43
+++ Test/D04parameter.ztst 5 Oct 2010 21:04:59 -0000
@@ -389,6 +389,34 @@
>)
>ten( more
+ strings=(
+ 'foo=(1 2 3)'
+ '(( 3 + 1 == 8 / 2 ))'
+ 'for (( i = 1 ; i < 10 ; i++ ))'
+ )
+ for string in $strings; do
+ array=(${(z)string})
+ for (( i = 1; i <= ${#array}; i++ )); do
+ print -r -- "${i}:${array[i]}:"
+ done
+ done
+0:Some syntactical expressions that are hard to split into words with (z).
+>1:foo=(:
+>2:1:
+>3:2:
+>4:3:
+>5:):
+>1:(( 3 + 1 == 8 / 2 )):
+>1:for:
+>2:((:
+# Leading whitespace is removed, because the word proper hasn't started;
+# trailing whitespace is left because the word is terminated by the
+# semicolon or double parentheses. Bit confusing but sort of consistent.
+>3:i = 1 ;:
+>4:i < 10 ;:
+>5:i++ :
+>6:)):
+
psvar=(dog)
setopt promptsubst
foo='It shouldn'\''t $(happen) to a %1v.'
--
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: PATCH: fix some (z) splitting oddities
2010-10-05 21:11 PATCH: fix some (z) splitting oddities Peter Stephenson
@ 2010-10-06 1:48 ` Bart Schaefer
0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2010-10-06 1:48 UTC (permalink / raw)
To: Zsh Hackers' List
On Oct 5, 10:11pm, Peter Stephenson wrote:
}
} No question of these being special syntactic markers, they were just
} plain wrong and inconsistent; see the new test for the cases I fixed.
There was a considerable discussion on austin-group a few months ago
about the problems of parsing ((...)) in terms of distinguishing math
expressions from nested subshells, etc. After "for", at least it's
unambigous.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2010-10-06 1:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-05 21:11 PATCH: fix some (z) splitting oddities Peter Stephenson
2010-10-06 1:48 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).