Op 24-03-16 om 04:04 schreef Theo Buehler:
On Fri, Mar 04, 2016 at 11:29:38AM +0100, Dmitrij D. Czarkoff wrote:
Martijn Dekker said:
So this patch makes quoted "$@" act according to the standard even when
IFS is empty. Quoted "$*" is unchanged. For the unspecified (not
standardised) cases of unquoted $@ and $*, this patch makes ksh act like
AT&T ksh93, bash, zsh and (d)ash, which seems safest from a
compatibility point of view.

This makes sense to me, and changes seem reasonable.  I've re-generated
diff against -current.  Anyone willing to OK it?

I think this is ok.

However, since this patch is rather subtle, it would be nice if someone
more experienced could look this over as well. Note that this appears
to have been in the snapshots for a while.

Now it's out of the snapshots again, but it wasn't applied. Has it been rejected for some reason?

If not, is there anyone more experienced who could look this over? (See below.)

@@ -420,6 +446,7 @@ expand(char *cp,    /* input word */
                                        if (f&DOBLANK)
                                                doblank++;
                                        st = st->prev;
+                                       word = quote || (!*x.str) ? IFS_WORD : 
IFS_IWS;

This line would need some wrapping. While I'm here: the parens are a bit
strange. Since the precedence here is not completely obvious anyway, I
think they are more confusing than helpful. Why not

                                        word = (quote || !*x.str) ? IFS_WORD : 
IFS_IWS;

or even

                                        if (quote || !*x.str)
                                                word = IFS_WORD;
                                        else
                                                word = IFS_IWS;


I agree. The latter version is much easier to read. Here is a new diff against -current with it applied.

Thanks,

- M.

Index: bin/ksh/eval.c
===================================================================
RCS file: /cvs/src/bin/ksh/eval.c,v
retrieving revision 1.50
diff -u -p -r1.50 eval.c
--- bin/ksh/eval.c	5 Mar 2016 12:30:17 -0000	1.50
+++ bin/ksh/eval.c	6 May 2016 20:05:57 -0000
@@ -47,6 +47,8 @@ typedef struct Expand {
 #define IFS_WORD	0	/* word has chars (or quotes) */
 #define IFS_WS		1	/* have seen IFS white-space */
 #define IFS_NWS		2	/* have seen IFS non-white-space */
+#define IFS_IWS		3	/* beginning of word, ignore IFS white-space */
+#define IFS_QUOTE	4	/* beg.w/quote, becomes IFS_WORD unless "$@" */
 
 static	int	varsub(Expand *, char *, char *, int *, int *);
 static	int	comsub(Expand *, char *);
@@ -215,7 +217,17 @@ expand(char *cp,	/* input word */
 				c = *sp++;
 				break;
 			case OQUOTE:
-				word = IFS_WORD;
+				switch (word) {
+				case IFS_QUOTE:
+					/* """something */
+					word = IFS_WORD;
+					break;
+				case IFS_WORD:
+					break;
+				default:
+					word = IFS_QUOTE;
+					break;
+				}
 				tilde_ok = 0;
 				quote = 1;
 				continue;
@@ -295,6 +307,8 @@ expand(char *cp,	/* input word */
 				if (f&DOBLANK)
 					doblank++;
 				tilde_ok = 0;
+				if (word == IFS_QUOTE && type != XNULLSUB)
+					word = IFS_WORD;
 				if (type == XBASE) {	/* expand? */
 					if (!st->next) {
 						SubType *newst;
@@ -356,6 +370,11 @@ expand(char *cp,	/* input word */
 						f |= DOTEMP_;
 						/* FALLTHROUGH */
 					default:
+						/* '-' '+' '?' */
+						if (quote)
+							word = IFS_WORD;
+						else if (dp == Xstring(ds, dp))
+							word = IFS_IWS;
 						/* Enable tilde expansion */
 						tilde_ok = 1;
 						f |= DOTILDE;
@@ -385,10 +404,17 @@ expand(char *cp,	/* input word */
 					 */
 					x.str = trimsub(str_val(st->var),
 						dp, st->stype);
-					if (x.str[0] != '\0' || st->quote)
+					if (x.str[0] != '\0') {
+						word = IFS_IWS;
 						type = XSUB;
-					else
+					} else if (quote) {
+						word = IFS_WORD;
+						type = XSUB;
+					} else {
+						if (dp == Xstring(ds, dp))
+							word = IFS_IWS;
 						type = XNULLSUB;
+					}
 					if (f&DOBLANK)
 						doblank++;
 					st = st->prev;
@@ -420,6 +446,10 @@ expand(char *cp,	/* input word */
 					if (f&DOBLANK)
 						doblank++;
 					st = st->prev;
+					if (quote || !*x.str)
+						word = IFS_WORD;
+					else
+						word = IFS_IWS;
 					continue;
 				case '?':
 				    {
@@ -461,12 +491,8 @@ expand(char *cp,	/* input word */
 			type = XBASE;
 			if (f&DOBLANK) {
 				doblank--;
-				/* not really correct: x=; "$x$@" should
-				 * generate a null argument and
-				 * set A; "${@:+}" shouldn't.
-				 */
-				if (dp == Xstring(ds, dp))
-					word = IFS_WS;
+				if (dp == Xstring(ds, dp) && word != IFS_WORD)
+					word = IFS_IWS;
 			}
 			continue;
 
@@ -501,7 +527,12 @@ expand(char *cp,	/* input word */
 				if (c == 0) {
 					if (quote && !x.split)
 						continue;
+					if (!quote && word == IFS_WS)
+						continue;
+					/* this is so we don't terminate */
 					c = ' ';
+					/* now force-emit a word */
+					goto emit_word;
 				}
 				if (quote && x.split) {
 					/* terminate word for "$@" */
@@ -552,15 +583,15 @@ expand(char *cp,	/* input word */
 			 *	-----------------------------------
 			 *	IFS_WORD	w/WS	w/NWS	w
 			 *	IFS_WS		-/WS	w/NWS	-
-			 *	IFS_NWS		-/NWS	w/NWS	w
+			 *	IFS_NWS		-/NWS	w/NWS	-
+			 *	IFS_IWS		-/WS	w/NWS	-
 			 *   (w means generate a word)
-			 * Note that IFS_NWS/0 generates a word (at&t ksh
-			 * doesn't do this, but POSIX does).
 			 */
-			if (word == IFS_WORD ||
-			    (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) {
-				char *p;
-
+			if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c &&
+			    (word == IFS_IWS || word == IFS_NWS) &&
+			    !ctype(c, C_IFSWS))) {
+ 				char *p;
+ emit_word:
 				*dp++ = '\0';
 				p = Xclose(ds, dp);
 #ifdef BRACE_EXPAND
Index: regress/bin/ksh/ifs.t
===================================================================
RCS file: /cvs/src/regress/bin/ksh/ifs.t,v
retrieving revision 1.1
diff -u -p -r1.1 ifs.t
--- regress/bin/ksh/ifs.t	2 Dec 2013 20:39:44 -0000	1.1
+++ regress/bin/ksh/ifs.t	6 May 2016 20:06:17 -0000
@@ -45,10 +45,10 @@ stdin:
 	showargs 3 $@
 	showargs 4 "$@"
 expected-stdout:
-	 <1> <A B C>
+	 <1> <A> <B> <C>
 	 <2> <ABC>
-	 <3> <A B C>
-	 <4> <A B C>
+	 <3> <A> <B> <C>
+	 <4> <A> <B> <C>
 ---
 
 name: IFS-space-colon-1

Reply via email to