f233325
diff -up diffutils-3.6/src/diff.c.i18n diffutils-3.6/src/diff.c
f233325
--- diffutils-3.6/src/diff.c.i18n	2017-05-06 20:02:54.000000000 +0100
f233325
+++ diffutils-3.6/src/diff.c	2017-05-22 10:52:21.989254674 +0100
f233325
@@ -76,6 +76,8 @@ static void try_help (char const *, char
2ce78f3
 static void check_stdout (void);
2ce78f3
 static void usage (void);
2ce78f3
 
2ce78f3
+bool (*lines_differ) (char const *, size_t, char const *, size_t);
2ce78f3
+
2ce78f3
 /* If comparing directories, compare their common subdirectories
2ce78f3
    recursively.  */
2ce78f3
 static bool recursive;
f233325
@@ -298,6 +300,13 @@ main (int argc, char **argv)
2ce78f3
   excluded = new_exclude ();
f233325
   presume_output_tty = false;
2ce78f3
 
2ce78f3
+#ifdef HANDLE_MULTIBYTE
2ce78f3
+  if (MB_CUR_MAX > 1)
2ce78f3
+    lines_differ = lines_differ_multibyte;
2ce78f3
+  else
2ce78f3
+#endif
2ce78f3
+    lines_differ = lines_differ_singlebyte;
2ce78f3
+
2ce78f3
   /* Decode the options.  */
2ce78f3
 
2ce78f3
   while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
f233325
diff -up diffutils-3.6/src/diff.h.i18n diffutils-3.6/src/diff.h
f233325
--- diffutils-3.6/src/diff.h.i18n	2017-01-01 11:22:36.000000000 +0000
f233325
+++ diffutils-3.6/src/diff.h	2017-05-22 10:51:09.050371844 +0100
2ce78f3
@@ -23,6 +23,17 @@
2ce78f3
 #include <stdio.h>
2ce78f3
 #include <unlocked-io.h>
2ce78f3
 
2ce78f3
+/* For platforms which support the ISO C ammendment 1 functionality we
2ce78f3
+   support user-defined character classes. */
2ce78f3
+#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H
2ce78f3
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
2ce78f3
+# include <wchar.h>
2ce78f3
+# include <wctype.h>
2ce78f3
+# if defined (HAVE_MBRTOWC)
2ce78f3
+#  define HANDLE_MULTIBYTE	1
2ce78f3
+# endif
2ce78f3
+#endif
2ce78f3
+
2ce78f3
 /* What kind of changes a hunk contains.  */
2ce78f3
 enum changes
2ce78f3
 {
f233325
@@ -381,7 +392,11 @@ extern void print_sdiff_script (struct c
2ce78f3
 extern char const change_letter[4];
2ce78f3
 extern char const pr_program[];
2ce78f3
 extern char *concat (char const *, char const *, char const *);
9778ec9
-extern bool lines_differ (char const *, char const *) _GL_ATTRIBUTE_PURE;
9778ec9
+extern bool (*lines_differ) (char const *, size_t, char const *, size_t) _GL_ATTRIBUTE_PURE;
9778ec9
+extern bool lines_differ_singlebyte (char const *, size_t, char const *, size_t) _GL_ATTRIBUTE_PURE;
2ce78f3
+#ifdef HANDLE_MULTIBYTE
9778ec9
+extern bool lines_differ_multibyte (char const *, size_t, char const *, size_t) _GL_ATTRIBUTE_PURE;
2ce78f3
+#endif
2ce78f3
 extern lin translate_line_number (struct file_data const *, lin);
2ce78f3
 extern struct change *find_change (struct change *);
2ce78f3
 extern struct change *find_reverse_change (struct change *);
f233325
diff -up diffutils-3.6/src/io.c.i18n diffutils-3.6/src/io.c
f233325
--- diffutils-3.6/src/io.c.i18n	2017-01-01 11:22:36.000000000 +0000
f233325
+++ diffutils-3.6/src/io.c	2017-05-22 10:51:09.050371844 +0100
9778ec9
@@ -23,6 +23,7 @@
2ce78f3
 #include <cmpbuf.h>
2ce78f3
 #include <file-type.h>
2ce78f3
 #include <xalloc.h>
2ce78f3
+#include <assert.h>
2ce78f3
 
2ce78f3
 /* Rotate an unsigned value to the left.  */
2ce78f3
 #define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n)))
f233325
@@ -215,6 +216,28 @@ slurp (struct file_data *current)
2ce78f3
 
2ce78f3
 /* Split the file into lines, simultaneously computing the equivalence
2ce78f3
    class for each line.  */
2ce78f3
+#ifdef HANDLE_MULTIBYTE
2ce78f3
+# define MBC2WC(P, END, MBLENGTH, WC, STATE, CONVFAIL)		\
2ce78f3
+do								\
2ce78f3
+  {								\
2ce78f3
+    mbstate_t state_bak = STATE;				\
2ce78f3
+								\
2ce78f3
+    CONVFAIL = 0;						\
2ce78f3
+    MBLENGTH = mbrtowc (&WC, P, END - (char const *)P, &STATE);	\
2ce78f3
+								\
2ce78f3
+    switch (MBLENGTH)						\
2ce78f3
+      {								\
2ce78f3
+      case (size_t)-2:						\
2ce78f3
+      case (size_t)-1:						\
2ce78f3
+	STATE = state_bak;					\
2ce78f3
+	++CONVFAIL;						\
2ce78f3
+	/* Fall through. */					\
2ce78f3
+      case 0:							\
2ce78f3
+	MBLENGTH = 1;						\
2ce78f3
+      }								\
2ce78f3
+  }								\
2ce78f3
+ while (0)
2ce78f3
+#endif
2ce78f3
 
2ce78f3
 static void
2ce78f3
 find_and_hash_each_line (struct file_data *current)
f233325
@@ -241,12 +264,300 @@ find_and_hash_each_line (struct file_dat
2ce78f3
   bool same_length_diff_contents_compare_anyway =
2ce78f3
     diff_length_compare_anyway | ig_case;
2ce78f3
 
2ce78f3
+#ifdef HANDLE_MULTIBYTE
2ce78f3
+  wchar_t wc;
2ce78f3
+  size_t mblength;
2ce78f3
+  mbstate_t state;
2ce78f3
+  int convfail;
2ce78f3
+
2ce78f3
+  memset (&state, '\0', sizeof (mbstate_t));
2ce78f3
+#endif
2ce78f3
+
2ce78f3
   while (p < suffix_begin)
2ce78f3
     {
2ce78f3
       char const *ip = p;
2ce78f3
       hash_value h = 0;
2ce78f3
       unsigned char c;
2ce78f3
 
2ce78f3
+#ifdef HANDLE_MULTIBYTE
2ce78f3
+      if (MB_CUR_MAX > 1)
2ce78f3
+	{
2ce78f3
+	  wchar_t lo_wc;
2ce78f3
+	  char mbc[MB_LEN_MAX];
2ce78f3
+	  mbstate_t state_wc;
2ce78f3
+
2ce78f3
+	  /* Hash this line until we find a newline.  */
2ce78f3
+	  switch (ig_white_space)
2ce78f3
+	    {
2ce78f3
+	    case IGNORE_ALL_SPACE:
2ce78f3
+	      while (1)
2ce78f3
+		{
2ce78f3
+		  if (*p == '\n')
2ce78f3
+		    {
2ce78f3
+		      ++p;
2ce78f3
+		      break;
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+
2ce78f3
+		  if (convfail)
2ce78f3
+		    mbc[0] = *p++;
2ce78f3
+		  else if (!iswspace (wc))
2ce78f3
+		    {
2ce78f3
+		      bool flag = 0;
2ce78f3
+
2ce78f3
+		      if (ig_case)
2ce78f3
+			{
2ce78f3
+			  lo_wc = towlower (wc);
2ce78f3
+			  if (lo_wc != wc)
2ce78f3
+			    {
2ce78f3
+			      flag = 1;
2ce78f3
+
2ce78f3
+			      p += mblength;
2ce78f3
+			      memset (&state_wc, '\0', sizeof(mbstate_t));
2ce78f3
+			      mblength = wcrtomb (mbc, lo_wc, &state_wc);
2ce78f3
+
2ce78f3
+			      assert (mblength != (size_t)-1 &&
2ce78f3
+				      mblength != (size_t)-2);
2ce78f3
+
2ce78f3
+			      mblength = (mblength < 1) ? 1 : mblength;
2ce78f3
+			    }
2ce78f3
+			}
2ce78f3
+
2ce78f3
+		      if (!flag)
2ce78f3
+			{
2ce78f3
+			  for (i = 0; i < mblength; i++)
2ce78f3
+			    mbc[i] = *p++;
2ce78f3
+			}
2ce78f3
+		    }
2ce78f3
+		  else
2ce78f3
+		    {
2ce78f3
+		      p += mblength;
2ce78f3
+		      continue;
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  for (i = 0; i < mblength; i++)
2ce78f3
+		    h = HASH (h, mbc[i]);
2ce78f3
+		}
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    case IGNORE_SPACE_CHANGE:
2ce78f3
+	      while (1)
2ce78f3
+		{
2ce78f3
+		  if (*p == '\n')
2ce78f3
+		    {
2ce78f3
+		      ++p;
2ce78f3
+		      break;
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+
2ce78f3
+		  if (!convfail && iswspace (wc))
2ce78f3
+		    {
2ce78f3
+		      while (1)
2ce78f3
+			{
2ce78f3
+			  if (*p == '\n')
2ce78f3
+			    {
2ce78f3
+			      ++p;
2ce78f3
+			      goto hashing_done;
2ce78f3
+			    }
2ce78f3
+
2ce78f3
+			  p += mblength;
2ce78f3
+			  MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+			  if (convfail || !iswspace (wc))
2ce78f3
+			    break;
2ce78f3
+			}
2ce78f3
+		      h = HASH (h, ' ');
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  /* WC is now the first non-space.  */
2ce78f3
+		  if (convfail)
2ce78f3
+		    mbc[0] = *p++;
2ce78f3
+		  else
2ce78f3
+		    {
2ce78f3
+		      bool flag = 0;
2ce78f3
+
2ce78f3
+		      if (ignore_case)
2ce78f3
+			{
2ce78f3
+			  lo_wc = towlower (wc);
2ce78f3
+			  if (lo_wc != wc)
2ce78f3
+			    {
2ce78f3
+			      flag = 1;
2ce78f3
+
2ce78f3
+			      p += mblength;
2ce78f3
+			      memset (&state_wc, '\0', sizeof(mbstate_t));
2ce78f3
+			      mblength = wcrtomb (mbc, lo_wc, &state_wc);
2ce78f3
+
2ce78f3
+			      assert (mblength != (size_t)-1 &&
2ce78f3
+				      mblength != (size_t)-2);
2ce78f3
+
2ce78f3
+			      mblength = (mblength < 1) ? 1 : mblength;
2ce78f3
+			    }
2ce78f3
+			}
2ce78f3
+
2ce78f3
+		      if (!flag)
2ce78f3
+			{
2ce78f3
+			  for (i = 0; i < mblength; i++)
2ce78f3
+			    mbc[i] = *p++;
2ce78f3
+			}
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  for (i = 0; i < mblength; i++)
2ce78f3
+		    h = HASH (h, mbc[i]);
2ce78f3
+		}
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    case IGNORE_TAB_EXPANSION:
2ce78f3
+	    case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
2ce78f3
+	    case IGNORE_TRAILING_SPACE:
2ce78f3
+	      {
2ce78f3
+		size_t column = 0;
2ce78f3
+		while (1)
2ce78f3
+		  {
2ce78f3
+		    if (*p == '\n')
2ce78f3
+		      {
2ce78f3
+			++p;
2ce78f3
+			break;
2ce78f3
+		      }
2ce78f3
+
2ce78f3
+		    MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+
2ce78f3
+		    if (!convfail
2ce78f3
+			&& ig_white_space & IGNORE_TRAILING_SPACE
2ce78f3
+			&& iswspace (wc))
2ce78f3
+		      {
2ce78f3
+			char const *p1 = p;
2ce78f3
+			while (1)
2ce78f3
+			  {
2ce78f3
+			    if (*p1 == '\n')
2ce78f3
+			      {
5b4e2e3
+				p = p1 + 1;
2ce78f3
+				goto hashing_done;
2ce78f3
+			      }
2ce78f3
+
2ce78f3
+			    p1 += mblength;
2ce78f3
+			    MBC2WC (p1, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+			    if (convfail || !iswspace (wc))
2ce78f3
+			      break;
2ce78f3
+			  }
2ce78f3
+		      }
2ce78f3
+
2ce78f3
+		    size_t repetitions = 1;
5b4e2e3
+		    bool no_convert = 0;
2ce78f3
+
2ce78f3
+		    if (ig_white_space & IGNORE_TAB_EXPANSION)
2ce78f3
+		      {
2ce78f3
+			if (convfail)
2ce78f3
+			  column++;
2ce78f3
+			else
2ce78f3
+			  switch (wc)
2ce78f3
+			    {
2ce78f3
+			    case L'\b':
2ce78f3
+			      column -= 0 < column;
2ce78f3
+			      break;
2ce78f3
+
2ce78f3
+			    case L'\t':
3f1ab3a
+			      mbc[0] = ' ';
3f1ab3a
+			      mblength = 1;
5b4e2e3
+			      no_convert = 1;
3f1ab3a
+			      p++;
3f1ab3a
+			      assert(mblength == 1);
2ce78f3
+			      repetitions = tabsize - column % tabsize;
2ce78f3
+			      column = (column + repetitions < column
2ce78f3
+					? 0
2ce78f3
+					: column + repetitions);
2ce78f3
+			      break;
2ce78f3
+
2ce78f3
+			    case L'\r':
2ce78f3
+			      column = 0;
2ce78f3
+			      break;
2ce78f3
+
2ce78f3
+			    default:
2ce78f3
+			      column += wcwidth (wc);
2ce78f3
+			      break;
2ce78f3
+			    }
5b4e2e3
+		      }
2ce78f3
+
5b4e2e3
+		    if (ig_case)
5b4e2e3
+		      {
5b4e2e3
+			lo_wc = towlower (wc);
5b4e2e3
+			if (lo_wc != wc)
2ce78f3
+			  {
5b4e2e3
+			    no_convert = 1;
5b4e2e3
+			    p += mblength;
5b4e2e3
+			    memset (&state_wc, '\0', sizeof(mbstate_t));
5b4e2e3
+			    mblength = wcrtomb (mbc, lo_wc, &state_wc);
2ce78f3
+
5b4e2e3
+			    assert (mblength != (size_t)-1 &&
5b4e2e3
+				    mblength != (size_t)-2);
2ce78f3
+
5b4e2e3
+			    mblength = (mblength < 1) ? 1 : mblength;
2ce78f3
+			  }
2ce78f3
+		      }
2ce78f3
+
5b4e2e3
+		    if (!no_convert)
5b4e2e3
+		      for (i = 0; i < mblength; i++)
5b4e2e3
+			mbc[i] = *p++;
5b4e2e3
+
2ce78f3
+		    do
2ce78f3
+		      {
2ce78f3
+			for (i = 0; i < mblength; i++)
2ce78f3
+			  h = HASH (h, mbc[i]);
2ce78f3
+		      }
2ce78f3
+		    while (--repetitions != 0);
2ce78f3
+		  }
2ce78f3
+	      }
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    default:
2ce78f3
+	      while (1)
2ce78f3
+		{
2ce78f3
+		  if (*p == '\n')
2ce78f3
+		    {
2ce78f3
+		      ++p;
2ce78f3
+		      break;
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
2ce78f3
+
2ce78f3
+		  if (convfail)
2ce78f3
+		    mbc[0] = *p++;
2ce78f3
+		  else
2ce78f3
+		    {
2ce78f3
+		      int flag = 0;
2ce78f3
+
2ce78f3
+		      if (ig_case)
2ce78f3
+			{
2ce78f3
+			  lo_wc = towlower (wc);
2ce78f3
+			  if (lo_wc != wc)
2ce78f3
+			    {
2ce78f3
+			      flag = 1;
2ce78f3
+			      p += mblength;
2ce78f3
+			      memset (&state_wc, '\0', sizeof(mbstate_t));
2ce78f3
+			      mblength = wcrtomb (mbc, lo_wc, &state_wc);
2ce78f3
+
2ce78f3
+			      assert (mblength != (size_t)-1 &&
2ce78f3
+				      mblength != (size_t)-2);
2ce78f3
+
2ce78f3
+			      mblength = (mblength < 1) ? 1 : mblength;
2ce78f3
+			    }
2ce78f3
+			}
2ce78f3
+
2ce78f3
+		      if (!flag)
2ce78f3
+			{
2ce78f3
+			  for (i = 0; i < mblength; i++)
2ce78f3
+			    mbc[i] = *p++;
2ce78f3
+			}
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  for (i = 0; i < mblength; i++)
2ce78f3
+		    h = HASH (h, mbc[i]);
2ce78f3
+		}
2ce78f3
+	    }
2ce78f3
+	}
2ce78f3
+      else
2ce78f3
+#endif
2ce78f3
+
2ce78f3
       /* Hash this line until we find a newline.  */
2ce78f3
       switch (ig_white_space)
2ce78f3
 	{
f233325
@@ -397,7 +708,7 @@ find_and_hash_each_line (struct file_dat
2ce78f3
 	    else if (!diff_length_compare_anyway)
2ce78f3
 	      continue;
2ce78f3
 
2ce78f3
-	    if (! lines_differ (eqline, ip))
2ce78f3
+	    if (! lines_differ (eqline, eqs[i].length + 1, ip, length + 1))
2ce78f3
 	      break;
2ce78f3
 	  }
2ce78f3
 
f233325
diff -up diffutils-3.6/src/util.c.i18n diffutils-3.6/src/util.c
f233325
--- diffutils-3.6/src/util.c.i18n	2017-05-18 18:39:59.000000000 +0100
f233325
+++ diffutils-3.6/src/util.c	2017-05-22 10:51:09.050371844 +0100
f233325
@@ -985,7 +985,8 @@ finish_output (void)
2ce78f3
    Return nonzero if the lines differ.  */
2ce78f3
 
2ce78f3
 bool
2ce78f3
-lines_differ (char const *s1, char const *s2)
2ce78f3
+lines_differ_singlebyte (char const *s1, size_t s1len,
2ce78f3
+			 char const *s2, size_t s2len)
2ce78f3
 {
2ce78f3
   register char const *t1 = s1;
2ce78f3
   register char const *t2 = s2;
f233325
@@ -1141,6 +1142,354 @@ lines_differ (char const *s1, char const
2ce78f3
 
2ce78f3
   return true;
2ce78f3
 }
2ce78f3
+
2ce78f3
+#ifdef HANDLE_MULTIBYTE
2ce78f3
+# define MBC2WC(T, END, MBLENGTH, WC, STATE, CONVFAIL)	\
2ce78f3
+do							\
2ce78f3
+  {							\
2ce78f3
+    mbstate_t bak = STATE;				\
2ce78f3
+							\
2ce78f3
+    CONVFAIL = 0;					\
2ce78f3
+    MBLENGTH = mbrtowc (&WC, T, END - T, &STATE);	\
2ce78f3
+							\
2ce78f3
+    switch (MBLENGTH)					\
2ce78f3
+      {							\
2ce78f3
+      case (size_t)-2:					\
2ce78f3
+      case (size_t)-1:					\
2ce78f3
+	STATE = bak;					\
2ce78f3
+	++CONVFAIL;					\
2ce78f3
+	/* Fall through. */				\
2ce78f3
+      case 0:						\
2ce78f3
+	MBLENGTH = 1;					\
2ce78f3
+      }							\
2ce78f3
+  }							\
2ce78f3
+ while (0)
2ce78f3
+
2ce78f3
+bool
2ce78f3
+lines_differ_multibyte (char const *s1, size_t s1len,
2ce78f3
+			char const *s2, size_t s2len)
2ce78f3
+{
2ce78f3
+  char const *end1, *end2;
2ce78f3
+  char c1, c2;
2ce78f3
+  wchar_t wc1, wc2, wc1_bak, wc2_bak;
2ce78f3
+  size_t mblen1, mblen2;
2ce78f3
+  mbstate_t state1, state2, state1_bak, state2_bak;
2ce78f3
+  int convfail1, convfail2, convfail1_bak, convfail2_bak;
2ce78f3
+  
2ce78f3
+  char const *t1 = s1;
2ce78f3
+  char const *t2 = s2;
2ce78f3
+  char const *t1_bak, *t2_bak;
2ce78f3
+  size_t column = 0;
2ce78f3
+
2ce78f3
+  if (ignore_white_space == IGNORE_NO_WHITE_SPACE  && !ignore_case)
2ce78f3
+    {
2ce78f3
+      while (*t1 != '\n')
2ce78f3
+	if (*t1++ != *t2++)
2ce78f3
+	  return 1;
2ce78f3
+      return 0;
2ce78f3
+    }
2ce78f3
+
2ce78f3
+  end1 = t1 + s1len;
2ce78f3
+  end2 = t2 + s2len;
2ce78f3
+
2ce78f3
+  memset (&state1, '\0', sizeof (mbstate_t));
2ce78f3
+  memset (&state2, '\0', sizeof (mbstate_t));
2ce78f3
+
2ce78f3
+  while (1)
2ce78f3
+    {
2ce78f3
+      c1 = *t1;
2ce78f3
+      c2 = *t2;
2ce78f3
+      MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
2ce78f3
+      MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
2ce78f3
+
2ce78f3
+      /* Test for exact char equality first, since it's a common case.  */
2ce78f3
+      if (convfail1 ^ convfail2)
2ce78f3
+	break;
2ce78f3
+      else if (convfail1 && convfail2 && c1 != c2)
2ce78f3
+	break;
2ce78f3
+      else if (!convfail1 && !convfail2 && wc1 != wc2)
2ce78f3
+	{
2ce78f3
+	  switch (ignore_white_space)
2ce78f3
+	    {
2ce78f3
+	    case IGNORE_ALL_SPACE:
2ce78f3
+	      /* For -w, just skip past any white space.  */
2ce78f3
+	      while (1)
2ce78f3
+		{
2ce78f3
+		  if (convfail1)
2ce78f3
+		    break;
2ce78f3
+		  else if (wc1 == L'\n' || !iswspace (wc1))
2ce78f3
+		    break;
2ce78f3
+
2ce78f3
+		  t1 += mblen1;
2ce78f3
+		  c1 = *t1;
2ce78f3
+		  MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
2ce78f3
+		}
2ce78f3
+
2ce78f3
+	      while (1)
2ce78f3
+		{
2ce78f3
+		  if (convfail2)
2ce78f3
+		    break;
2ce78f3
+		  else if (wc2 == L'\n' || !iswspace (wc2))
2ce78f3
+		    break;
2ce78f3
+
2ce78f3
+		  t2 += mblen2;
2ce78f3
+		  c2 = *t2;
2ce78f3
+		  MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
2ce78f3
+		}
2ce78f3
+	      t1 += mblen1;
2ce78f3
+	      t2 += mblen2;
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    case IGNORE_SPACE_CHANGE:
2ce78f3
+	      /* For -b, advance past any sequence of white space in
2ce78f3
+		 line 1 and consider it just one space, or nothing at
2ce78f3
+		 all if it is at the end of the line.  */
2ce78f3
+	      if (wc1 != L'\n' && iswspace (wc1))
2ce78f3
+		{
2ce78f3
+		  size_t mblen_bak;
2ce78f3
+		  mbstate_t state_bak;
2ce78f3
+
2ce78f3
+		  do
2ce78f3
+		    {
2ce78f3
+		      t1 += mblen1;
2ce78f3
+		      mblen_bak = mblen1;
2ce78f3
+		      state_bak = state1;
2ce78f3
+		      MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
2ce78f3
+		    }
2ce78f3
+		  while (!convfail1 && (wc1 != L'\n' && iswspace (wc1)));
2ce78f3
+
2ce78f3
+		  state1 = state_bak;
2ce78f3
+		  mblen1 = mblen_bak;
2ce78f3
+		  t1 -= mblen1;
2ce78f3
+		  convfail1 = 0;
2ce78f3
+		  wc1 = L' ';
2ce78f3
+		}
2ce78f3
+
2ce78f3
+	      /* Likewise for line 2.  */
2ce78f3
+	      if (wc2 != L'\n' && iswspace (wc2))
2ce78f3
+		{
2ce78f3
+		  size_t mblen_bak;
2ce78f3
+		  mbstate_t state_bak;
2ce78f3
+
2ce78f3
+		  do
2ce78f3
+		    {
2ce78f3
+		      t2 += mblen2;
2ce78f3
+		      mblen_bak = mblen2;
2ce78f3
+		      state_bak = state2;
2ce78f3
+		      MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
2ce78f3
+		    }
2ce78f3
+		  while (!convfail2 && (wc2 != L'\n' && iswspace (wc2)));
2ce78f3
+
2ce78f3
+		  state2 = state_bak;
2ce78f3
+		  mblen2 = mblen_bak;
2ce78f3
+		  t2 -= mblen2;
2ce78f3
+		  convfail2 = 0;
2ce78f3
+		  wc2 = L' ';
2ce78f3
+		}
2ce78f3
+
2ce78f3
+	      if (wc1 != wc2)
2ce78f3
+		{
2ce78f3
+		  /* If we went too far when doing the simple test for
2ce78f3
+		     equality, go back to the first non-whitespace
2ce78f3
+		     character in both sides and try again.  */
2ce78f3
+		  if (wc2 == L' ' && wc1 != L'\n' &&
2ce78f3
+		      t1 > s1 &&
2ce78f3
+		      !convfail1_bak && iswspace (wc1_bak))
2ce78f3
+		    {
2ce78f3
+		      t1 = t1_bak;
2ce78f3
+		      wc1 = wc1_bak;
2ce78f3
+		      state1 = state1_bak;
2ce78f3
+		      convfail1 = convfail1_bak;
2ce78f3
+		      continue;
2ce78f3
+		    }
2ce78f3
+		  if (wc1 == L' ' && wc2 != L'\n'
2ce78f3
+		      && t2 > s2
2ce78f3
+		      && !convfail2_bak && iswspace (wc2_bak))
2ce78f3
+		    {
2ce78f3
+		      t2 = t2_bak;
2ce78f3
+		      wc2 = wc2_bak;
2ce78f3
+		      state2 = state2_bak;
2ce78f3
+		      convfail2 = convfail2_bak;
2ce78f3
+		      continue;
2ce78f3
+		    }
2ce78f3
+		}
2ce78f3
+
2ce78f3
+	      t1_bak = t1;		  t2_bak = t2;
2ce78f3
+	      wc1_bak = wc1;		  wc2_bak = wc2;
2ce78f3
+	      state1_bak = state1;	  state2_bak = state2;
2ce78f3
+	      convfail1_bak = convfail1;  convfail2_bak = convfail2;
2ce78f3
+
2ce78f3
+	      if (wc1 == L'\n')
2ce78f3
+		wc1 = L' ';
2ce78f3
+	      else
2ce78f3
+		t1 += mblen1;
2ce78f3
+
2ce78f3
+	      if (wc2 == L'\n')
2ce78f3
+		wc2 = L' ';
2ce78f3
+	      else
2ce78f3
+		t2 += mblen2;
2ce78f3
+
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    case IGNORE_TRAILING_SPACE:
2ce78f3
+	    case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
2ce78f3
+	      if (iswspace (wc1) && iswspace (wc2))
2ce78f3
+		{
2ce78f3
+		  char const *p;
2ce78f3
+		  wchar_t wc;
2ce78f3
+		  size_t mblength;
2ce78f3
+		  int convfail;
2ce78f3
+		  mbstate_t state;
2ce78f3
+		  bool just_whitespace_left = 1;
2ce78f3
+		  if (wc1 != L'\n')
2ce78f3
+		    {
2ce78f3
+		      mblength = mblen1;
2ce78f3
+		      p = t1;
2ce78f3
+		      memset (&state, '\0', sizeof(mbstate_t));
2ce78f3
+		      while (p < end1)
2ce78f3
+			{
2ce78f3
+			  if (*p == '\n')
2ce78f3
+			    break;
2ce78f3
+
2ce78f3
+			  p += mblength;
2ce78f3
+			  MBC2WC (p, end1, mblength, wc, state, convfail);
2ce78f3
+			  if (convfail || !iswspace (wc))
2ce78f3
+			    {
2ce78f3
+			      just_whitespace_left = 0;
2ce78f3
+			      break;
2ce78f3
+			    }
2ce78f3
+			}
2ce78f3
+		    }
2ce78f3
+		  if (just_whitespace_left && wc2 != L'\n')
2ce78f3
+		    {
2ce78f3
+		      mblength = mblen2;
2ce78f3
+		      p = t2;
2ce78f3
+		      memset (&state, '\0', sizeof(mbstate_t));
2ce78f3
+		      while (p < end2)
2ce78f3
+			{
2ce78f3
+			  if (*p == '\n')
2ce78f3
+			    break;
2ce78f3
+
2ce78f3
+			  p += mblength;
2ce78f3
+			  MBC2WC (p, end2, mblength, wc, state, convfail);
2ce78f3
+			  if (convfail || !iswspace (wc))
2ce78f3
+			    {
2ce78f3
+			      just_whitespace_left = 0;
2ce78f3
+			      break;
2ce78f3
+			    }
2ce78f3
+			}
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  if (just_whitespace_left)
2ce78f3
+		    /* Both lines have nothing but whitespace left.  */
2ce78f3
+		    return false;
2ce78f3
+		}
2ce78f3
+
2ce78f3
+	      if (ignore_white_space == IGNORE_TRAILING_SPACE)
2ce78f3
+		break;
2ce78f3
+	      /* Fall through.  */
2ce78f3
+	    case IGNORE_TAB_EXPANSION:
2ce78f3
+	      if ((wc1 == L' ' && wc2 == L'\t')
2ce78f3
+		  || (wc1 == L'\t' && wc2 == L' '))
2ce78f3
+		{
2ce78f3
+		  size_t column2 = column;
2ce78f3
+
2ce78f3
+		  while (1)
2ce78f3
+		    {
2ce78f3
+		      if (convfail1)
2ce78f3
+			{
2ce78f3
+			  ++t1;
2ce78f3
+			  break;
2ce78f3
+			}
2ce78f3
+		      else if (wc1 == L' ')
2ce78f3
+			column++;
2ce78f3
+		      else if (wc1 == L'\t')
2ce78f3
+			column += tabsize - column % tabsize;
2ce78f3
+		      else
2ce78f3
+			{
2ce78f3
+			  t1 += mblen1;
2ce78f3
+			  break;
2ce78f3
+			}
2ce78f3
+
2ce78f3
+		      t1 += mblen1;
2ce78f3
+		      c1 = *t1;
2ce78f3
+		      MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  while (1)
2ce78f3
+		    {
2ce78f3
+		      if (convfail2)
2ce78f3
+			{
2ce78f3
+			  ++t2;
2ce78f3
+			  break;
2ce78f3
+			}
2ce78f3
+		      else if (wc2 == L' ')
2ce78f3
+			column2++;
2ce78f3
+		      else if (wc2 == L'\t')
2ce78f3
+			column2 += tabsize - column2 % tabsize;
2ce78f3
+		      else
2ce78f3
+			{
2ce78f3
+			  t2 += mblen2;
2ce78f3
+			  break;
2ce78f3
+			}
2ce78f3
+
2ce78f3
+		      t2 += mblen2;
2ce78f3
+		      c2 = *t2;
2ce78f3
+		      MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
2ce78f3
+		    }
2ce78f3
+
2ce78f3
+		  if (column != column2)
2ce78f3
+		    return 1;
2ce78f3
+		}
2ce78f3
+	      else
2ce78f3
+		{
2ce78f3
+		  t1 += mblen1;
2ce78f3
+		  t2 += mblen2;
2ce78f3
+		}
2ce78f3
+	      break;
2ce78f3
+
2ce78f3
+	    case IGNORE_NO_WHITE_SPACE:
2ce78f3
+	      t1 += mblen1;
2ce78f3
+	      t2 += mblen2;
2ce78f3
+	      break;
2ce78f3
+	    }
2ce78f3
+
2ce78f3
+	  /* Lowercase all letters if -i is specified.  */
2ce78f3
+	  if (ignore_case)
2ce78f3
+	    {
2ce78f3
+	      if (!convfail1)
2ce78f3
+		wc1 = towlower (wc1);
2ce78f3
+	      if (!convfail2)
2ce78f3
+		wc2 = towlower (wc2);
2ce78f3
+	    }
2ce78f3
+
2ce78f3
+	  if (convfail1 ^ convfail2)
2ce78f3
+	    break;
2ce78f3
+	  else if (convfail1 && convfail2 && c1 != c2)
2ce78f3
+	    break;
2ce78f3
+	  else if (!convfail1 && !convfail2 && wc1 != wc2)
2ce78f3
+	    break;
2ce78f3
+	}
2ce78f3
+      else
2ce78f3
+	{
2ce78f3
+	  t1_bak = t1;			t2_bak = t2;
2ce78f3
+	  wc1_bak = wc1;		wc2_bak = wc2;
2ce78f3
+	  state1_bak = state1;		state2_bak = state2;
2ce78f3
+	  convfail1_bak = convfail1;	convfail2_bak = convfail2;
2ce78f3
+
2ce78f3
+	  t1 += mblen1;			t2 += mblen2;
2ce78f3
+	}
2ce78f3
+      
2ce78f3
+      if (!convfail1 && wc1 == L'\n')
2ce78f3
+	return 0;
2ce78f3
+
2ce78f3
+      column += convfail1 ? 1 :
2ce78f3
+	(wc1 == L'\t') ? tabsize - column % tabsize : wcwidth (wc1);
2ce78f3
+    }
2ce78f3
+
2ce78f3
+  return 1;
2ce78f3
+}
2ce78f3
+#endif
2ce78f3
 
2ce78f3
 /* Find the consecutive changes at the start of the script START.
2ce78f3
    Return the last link before the first gap.  */