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?

-- 
Dmitrij D. Czarkoff

Index: bin/ksh/eval.c
===================================================================
RCS file: /cvs/src/bin/ksh/eval.c,v
retrieving revision 1.49
diff -u -p -r1.49 eval.c
--- bin/ksh/eval.c      30 Dec 2015 09:07:00 -0000      1.49
+++ bin/ksh/eval.c      4 Mar 2016 09:39:07 -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 if (quote) {
+                                               word = IFS_WORD;
                                                type = XSUB;
-                                       else
+                                       } else {
+                                               if (dp == Xstring(ds, dp))
+                                                       word = IFS_IWS;
                                                type = XNULLSUB;
+                                       }
                                        if (f&DOBLANK)
                                                doblank++;
                                        st = st->prev;
@@ -420,6 +446,7 @@ expand(char *cp,    /* input word */
                                        if (f&DOBLANK)
                                                doblank++;
                                        st = st->prev;
+                                       word = quote || (!*x.str) ? IFS_WORD : 
IFS_IWS;
                                        continue;
                                case '?':
                                    {
@@ -461,12 +488,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 +524,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 +580,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       4 Mar 2016 09:39:07 -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