diff --git a/check.t b/check.t index 4dde011..b433c81 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.687 2015/03/20 23:37:52 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.688 2015/04/11 21:18:45 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, @@ -4842,6 +4842,66 @@ expected-stdout: 1a: 2: x[A B] --- +name: read-IFS-2 +description: + Complex tests, IFS either colon (IFS-NWS) or backslash (tricky) +stdin: + n=0 + showargs() { print -nr "$1"; shift; for s_arg in "$@"; do print -nr -- " [$s_arg]"; done; print; } + (IFS=\\ a=\<\\\>; showargs 3 $a) + (IFS=: b=\<:\>; showargs 4 $b) + print -r '<\>' | (IFS=\\ read f g; showargs 5 "$f" "$g") + print -r '<\\>' | (IFS=\\ read f g; showargs 6 "$f" "$g") + print '<\\\n>' | (IFS=\\ read f g; showargs 7 "$f" "$g") + print -r '<\>' | (IFS=\\ read f; showargs 8 "$f") + print -r '<\\>' | (IFS=\\ read f; showargs 9 "$f") + print '<\\\n>' | (IFS=\\ read f; showargs 10 "$f") + print -r '<\>' | (IFS=\\ read -r f g; showargs 11 "$f" "$g") + print -r '<\\>' | (IFS=\\ read -r f g; showargs 12 "$f" "$g") + print '<\\\n>' | (IFS=\\ read -r f g; showargs 13 "$f" "$g") + print -r '<\>' | (IFS=\\ read -r f; showargs 14 "$f") + print -r '<\\>' | (IFS=\\ read -r f; showargs 15 "$f") + print '<\\\n>' | (IFS=\\ read -r f; showargs 16 "$f") + print -r '<:>' | (IFS=: read f g; showargs 17 "$f" "$g") + print -r '<::>' | (IFS=: read f g; showargs 18 "$f" "$g") + print '<:\n>' | (IFS=: read f g; showargs 19 "$f" "$g") + print -r '<:>' | (IFS=: read f; showargs 20 "$f") + print -r '<::>' | (IFS=: read f; showargs 21 "$f") + print '<:\n>' | (IFS=: read f; showargs 22 "$f") + print -r '<:>' | (IFS=: read -r f g; showargs 23 "$f" "$g") + print -r '<::>' | (IFS=: read -r f g; showargs 24 "$f" "$g") + print '<:\n>' | (IFS=: read -r f g; showargs 25 "$f" "$g") + print -r '<:>' | (IFS=: read -r f; showargs 26 "$f") + print -r '<::>' | (IFS=: read -r f; showargs 27 "$f") + print '<:\n>' | (IFS=: read -r f; showargs 28 "$f") +expected-stdout: + 3 [<] [>] + 4 [<] [>] + 5 [<] [>] + 6 [<] [>] + 7 [<>] [] + 8 [<>] + 9 [<\>] + 10 [<>] + 11 [<] [>] + 12 [<] [\>] + 13 [<] [] + 14 [<\>] + 15 [<\\>] + 16 [<] + 17 [<] [>] + 18 [<] [:>] + 19 [<] [] + 20 [<:>] + 21 [<::>] + 22 [<] + 23 [<] [>] + 24 [<] [:>] + 25 [<] [] + 26 [<:>] + 27 [<::>] + 28 [<] +--- name: read-ksh-1 description: If no var specified, REPLY is used diff --git a/funcs.c b/funcs.c index 71a02b2..5a6771c 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.266 2015/03/20 21:01:41 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.267 2015/04/11 21:18:47 tg Exp $"); #if HAVE_KILLPG /* @@ -1821,9 +1821,10 @@ int c_read(const char **wp) { #define is_ifsws(c) (ctype((c), C_IFS) && ctype((c), C_IFSWS)) - int c, fd = 0, rv = 0, lastparm = 0; + int c, fd = 0, rv = 0; bool savehist = false, intoarray = false, aschars = false; bool rawmode = false, expanding = false; + bool lastparmmode = false, lastparmused = false; enum { LINES, BYTES, UPTO, READALL } readmode = LINES; char delim = '\n'; size_t bytesleft = 128, bytesread; @@ -2127,7 +2128,7 @@ c_read(const char **wp) } if (!intoarray && wp[1] == NULL) - lastparm = 1; + lastparmmode = true; c_read_splitlast: /* copy until IFS character */ @@ -2152,16 +2153,23 @@ c_read(const char **wp) } xsave = Xsavepos(xs, xp); /* copy word delimiter: IFSWS+IFS,IFSWS */ + expanding = false; while (bytesread) { char ch; ch = *ccp; if (!ctype(ch, C_IFS)) break; - Xcheck(xs, xp); - Xput(xs, xp, ch); + if (lastparmmode && !expanding && !rawmode && ch == '\\') { + expanding = true; + } else { + Xcheck(xs, xp); + Xput(xs, xp, ch); + } ++ccp; --bytesread; + if (expanding) + continue; if (!ctype(ch, C_IFSWS)) break; } @@ -2172,12 +2180,12 @@ c_read(const char **wp) --bytesread; } /* if no more parameters, rinse and repeat */ - if (lastparm && bytesread) { - ++lastparm; + if (lastparmmode && bytesread) { + lastparmused = true; goto c_read_splitlast; } /* get rid of the delimiter unless we pack the rest */ - if (lastparm < 2) + if (!lastparmused) xp = Xrestpos(xs, xp, xsave); c_read_gotword: Xput(xs, xp, '\0');