1 --- diffutils-2.9/src/diff.c 2010-02-11 10:39:17.000000000 +0100
2 +++ diffutils-2.9.mod/src/diff.c 2010-02-13 15:28:22.268208253 +0100
4 re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING);
5 excluded = new_exclude ();
7 +#ifdef HANDLE_MULTIBYTE
9 + lines_differ = lines_differ_multibyte;
12 + lines_differ = lines_differ_singlebyte;
14 /* Decode the options. */
16 while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
17 --- diffutils-2.9/src/diff.h 2010-02-11 10:05:57.000000000 +0100
18 +++ diffutils-2.9.mod/src/diff.h 2010-02-13 15:28:22.269208190 +0100
21 #include <unlocked-io.h>
23 +/* For platform which support the ISO C amendement 1 functionality we
24 + support user defined character classes. */
25 +#if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H
26 +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
29 +# if defined (HAVE_MBRTOWC)
30 +# define HANDLE_MULTIBYTE 1
36 /* What kind of changes a hunk contains. */
40 extern char const pr_program[];
41 char *concat (char const *, char const *, char const *);
42 char *dir_file_pathname (char const *, char const *);
43 -bool lines_differ (char const *, char const *);
45 +bool (*lines_differ) (char const *, char const *);
46 +bool lines_differ_singlebyte (char const *, char const *);
47 +#ifdef HANDLE_MULTIBYTE
48 +bool lines_differ_multibyte (char const *, char const *);
51 lin translate_line_number (struct file_data const *, lin);
52 struct change *find_change (struct change *);
53 struct change *find_reverse_change (struct change *);
54 --- diffutils-2.9/src/io.c 2010-02-05 09:10:15.000000000 +0100
55 +++ diffutils-2.9.mod/src/io.c 2010-02-13 15:39:59.313224273 +0100
58 #include <file-type.h>
62 /* Rotate an unsigned value to the left. */
63 #define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n)))
66 /* Split the file into lines, simultaneously computing the equivalence
67 class for each line. */
68 +#ifdef HANDLE_MULTIBYTE
69 +# define MBC2WC(P, END, MBLENGTH, WC, STATE, CONVFAIL) \
72 + mbstate_t state_bak = STATE; \
75 + MBLENGTH = mbrtowc (&WC, P, END - (char const *)P, &STATE); \
81 + STATE = state_bak; \
83 + /* Fall through. */ \
92 find_and_hash_each_line (struct file_data *current)
93 @@ -220,12 +243,282 @@
94 bool same_length_diff_contents_compare_anyway =
95 diff_length_compare_anyway | ignore_case;
97 +#ifdef HANDLE_MULTIBYTE
103 + memset (&state, '\0', sizeof (mbstate_t));
106 while (p < suffix_begin)
112 +#ifdef HANDLE_MULTIBYTE
113 + if (MB_CUR_MAX > 1)
116 + char mbc[MB_LEN_MAX];
117 + mbstate_t state_wc;
119 + /* Hash this line until we find a newline. */
120 + switch (ignore_white_space)
122 + case IGNORE_ALL_SPACE:
131 + MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
135 + else if (!iswspace (wc))
141 + lo_wc = towlower (wc);
147 + memset (&state_wc, '\0', sizeof(mbstate_t));
148 + mblength = wcrtomb (mbc, lo_wc, &state_wc);
150 + assert (mblength != (size_t)-1 &&
151 + mblength != (size_t)-2);
153 + mblength = (mblength < 1) ? 1 : mblength;
159 + for (i = 0; i < mblength; i++)
169 + for (i = 0; i < mblength; i++)
170 + h = HASH (h, mbc[i]);
174 + case IGNORE_SPACE_CHANGE:
183 + MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
185 + if (!convfail && iswspace (wc))
196 + MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
197 + if (convfail || (!convfail && !iswspace (wc)))
203 + /* WC is now the first non-space. */
212 + lo_wc = towlower (wc);
218 + memset (&state_wc, '\0', sizeof(mbstate_t));
219 + mblength = wcrtomb (mbc, lo_wc, &state_wc);
221 + assert (mblength != (size_t)-1 &&
222 + mblength != (size_t)-2);
224 + mblength = (mblength < 1) ? 1 : mblength;
230 + for (i = 0; i < mblength; i++)
235 + for (i = 0; i < mblength; i++)
236 + h = HASH (h, mbc[i]);
240 + case IGNORE_TAB_EXPANSION:
252 + MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
256 + h = HASH (h, *p++);
266 + column -= 0 < column;
267 + h = HASH (h, '\b');
275 + repetitions = TAB_WIDTH - column % TAB_WIDTH;
276 + column += repetitions;
279 + while (--repetitions != 0);
286 + h = HASH (h, '\r');
292 + column += wcwidth (wc);
295 + lo_wc = towlower (wc);
300 + memset (&state_wc, '\0', sizeof(mbstate_t));
301 + mblength = wcrtomb (mbc, lo_wc, &state_wc);
303 + assert (mblength != (size_t)-1 &&
304 + mblength != (size_t)-2);
306 + mblength = (mblength < 1) ? 1 : mblength;
312 + for (i = 0; i < mblength; i++)
316 + for (i = 0; i < mblength; i++)
317 + h = HASH (h, mbc[i]);
333 + MBC2WC (p, suffix_begin, mblength, wc, state, convfail);
343 + lo_wc = towlower (wc);
348 + memset (&state_wc, '\0', sizeof(mbstate_t));
349 + mblength = wcrtomb (mbc, lo_wc, &state_wc);
351 + assert (mblength != (size_t)-1 &&
352 + mblength != (size_t)-2);
354 + mblength = (mblength < 1) ? 1 : mblength;
360 + for (i = 0; i < mblength; i++)
365 + for (i = 0; i < mblength; i++)
366 + h = HASH (h, mbc[i]);
373 /* Hash this line until we find a newline. */
375 switch (ignore_white_space)
376 --- diffutils-2.9/src/side.c 2010-02-05 09:10:15.000000000 +0100
377 +++ diffutils-2.9.mod/src/side.c 2010-02-13 15:51:32.647221551 +0100
379 register char const *text_limit = line[1];
380 mbstate_t mbstate = { 0 };
382 +#if defined HAVE_WCHAR_H && defined HAVE_WCTYPE_H
383 + unsigned char mbc[MB_LEN_MAX];
385 + mbstate_t state, state_bak;
386 + size_t mbc_pos, mblength;
387 + int mbc_loading_flag = 0;
390 + memset (&state, '\0', sizeof (mbstate_t));
393 while (text_pointer < text_limit)
395 char const *tp0 = text_pointer;
396 register char c = *text_pointer++;
398 +#if defined HAVE_WCHAR_H && defined HAVE_WCTYPE_H
399 + if (MB_CUR_MAX > 1 && mbc_loading_flag)
401 + mbc_loading_flag = 0;
403 + mbc[mbc_pos++] = c;
406 + mblength = mbrtowc (&wc, mbc, mbc_pos, &state);
410 + case (size_t)-2: /* Incomplete multibyte character. */
411 + mbc_loading_flag = 1;
415 + case (size_t)-1: /* Invalid as a multibyte character. */
416 + if (in_position++ < out_bound)
418 + out_position = in_position;
419 + putc (mbc[0], out);
421 + memmove (mbc, mbc + 1, --mbc_pos);
424 + mbc[mbc_pos] = '\0';
430 + wc_width = wcwidth (wc);
431 + if (wc_width < 1) /* Unprintable multibyte character. */
433 + if (in_position <= out_bound)
434 + fprintf (out, "%lc", (wint_t)wc);
436 + else /* Printable multibyte character. */
438 + in_position += wc_width;
439 + if (in_position <= out_bound)
441 + out_position = in_position;
442 + fprintf (out, "%lc", (wint_t)wc);
453 --- diffutils-2.9/src/util.c 2010-02-11 10:39:17.000000000 +0100
454 +++ diffutils-2.9.mod/src/util.c 2010-02-13 16:08:16.065232588 +0100
461 /* Compare two lines (typically one from each input file)
462 according to the command line options.
463 For efficiency, this is invoked only when the lines do not match exactly
465 Return nonzero if the lines differ. */
468 -lines_differ (char const *s1, char const *s2)
469 +lines_differ_singlebyte (char const *s1, char const *s2)
471 register char const *t1 = s1;
472 register char const *t2 = s2;
473 @@ -446,7 +446,294 @@
479 +#ifdef HANDLE_MULTIBYTE
480 +# define MBC2WC(T, END, MBLENGTH, WC, STATE, CONVFAIL) \
483 + mbstate_t bak = STATE; \
486 + MBLENGTH = mbrtowc (&WC, T, END - T, &STATE); \
488 + switch (MBLENGTH) \
494 + /* Fall through. */ \
502 +lines_differ_multibyte (char const *s1, char const *s2)
504 + unsigned char const *end1, *end2;
505 + unsigned char c1, c2;
506 + wchar_t wc1, wc2, wc1_bak, wc2_bak;
507 + size_t mblen1, mblen2;
508 + mbstate_t state1, state2, state1_bak, state2_bak;
509 + int convfail1, convfail2, convfail1_bak, convfail2_bak;
511 + unsigned char const *t1 = (unsigned char const *) s1;
512 + unsigned char const *t2 = (unsigned char const *) s2;
513 + unsigned char const *t1_bak, *t2_bak;
516 + if (ignore_white_space == IGNORE_NO_WHITE_SPACE && !ignore_case)
518 + while (*t1 != '\n')
519 + if (*t1++ != * t2++)
524 + memset (&state1, '\0', sizeof (mbstate_t));
525 + memset (&state2, '\0', sizeof (mbstate_t));
527 + end1 = s1 + strlen (s1);
528 + end2 = s2 + strlen (s2);
534 + MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
535 + MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
537 + /* Test for exact char equality first, since it's a common case. */
538 + if (convfail1 ^ convfail2)
540 + else if (convfail1 && convfail2 && c1 != c2)
542 + else if (!convfail1 && !convfail2 && wc1 != wc2)
544 + switch (ignore_white_space)
546 + case IGNORE_ALL_SPACE:
547 + /* For -w, just skip past any white space. */
552 + else if (wc1 == L'\n' || !iswspace (wc1))
557 + MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
564 + else if (wc2 == L'\n' || !iswspace (wc2))
569 + MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
575 + case IGNORE_SPACE_CHANGE:
576 + /* For -b, advance past any sequence of white space in
577 + line 1 and consider it just one space, or nothing at
578 + all if it is at the end of the line. */
579 + if (wc1 != L'\n' && iswspace (wc1))
582 + mbstate_t state_bak;
587 + mblen_bak = mblen1;
588 + state_bak = state1;
589 + MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
591 + while (!convfail1 && (wc1 != L'\n' && iswspace (wc1)));
593 + state1 = state_bak;
594 + mblen1 = mblen_bak;
600 + /* Likewise for line 2. */
601 + if (wc2 != L'\n' && iswspace (wc2))
604 + mbstate_t state_bak;
609 + mblen_bak = mblen2;
610 + state_bak = state2;
611 + MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
613 + while (!convfail2 && (wc2 != L'\n' && iswspace (wc2)));
615 + state2 = state_bak;
616 + mblen2 = mblen_bak;
624 + if (wc2 == L' ' && wc1 != L'\n' &&
625 + t1 > (unsigned char const *)s1 &&
626 + !convfail1_bak && iswspace (wc1_bak))
630 + state1 = state1_bak;
631 + convfail1 = convfail1_bak;
634 + if (wc1 == L' ' && wc2 != L'\n'
635 + && t2 > (unsigned char const *)s2
636 + && !convfail2_bak && iswspace (wc2_bak))
640 + state2 = state2_bak;
641 + convfail2 = convfail2_bak;
646 + t1_bak = t1; t2_bak = t2;
647 + wc1_bak = wc1; wc2_bak = wc2;
648 + state1_bak = state1; state2_bak = state2;
649 + convfail1_bak = convfail1; convfail2_bak = convfail2;
663 + case IGNORE_TAB_EXPANSION:
664 + if ((wc1 == L' ' && wc2 == L'\t')
665 + || (wc1 == L'\t' && wc2 == L' '))
667 + size_t column2 = column;
676 + else if (wc1 == L' ')
678 + else if (wc1 == L'\t')
679 + column += TAB_WIDTH - column % TAB_WIDTH;
688 + MBC2WC (t1, end1, mblen1, wc1, state1, convfail1);
698 + else if (wc2 == L' ')
700 + else if (wc2 == L'\t')
701 + column2 += TAB_WIDTH - column2 % TAB_WIDTH;
710 + MBC2WC (t2, end2, mblen2, wc2, state2, convfail2);
713 + if (column != column2)
723 + case IGNORE_NO_WHITE_SPACE:
729 + /* Lowercase all letters if -i is specified. */
733 + wc1 = towlower (wc1);
735 + wc2 = towlower (wc2);
738 + if (convfail1 ^ convfail2)
740 + else if (convfail1 && convfail2 && c1 != c2)
742 + else if (!convfail1 && !convfail2 && wc1 != wc2)
747 + t1_bak = t1; t2_bak = t2;
748 + wc1_bak = wc1; wc2_bak = wc2;
749 + state1_bak = state1; state2_bak = state2;
750 + convfail1_bak = convfail1; convfail2_bak = convfail2;
752 + t1 += mblen1; t2 += mblen2;
755 + if (!convfail1 && wc1 == L'\n')
758 + column += convfail1 ? 1 :
759 + (wc1 == L'\t') ? TAB_WIDTH - column % TAB_WIDTH : wcwidth (wc1);
766 /* Find the consecutive changes at the start of the script START.
767 Return the last link before the first gap. */