Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: invalid characters and multi-byte [x-y] ranges
On Thu, 3 Sep 2015 11:09:44 +0100
Stephane Chazelas <stephane.chazelas@xxxxxxxxx> wrote:
> A discussed approach there was to internally represent bytes not
> forming part of a valid character as code points in the range
> D800-DFFF (specifically DC80 DCFF for bytes 0x80 to 0xff)
That's easy if wchar_t is actually Unicode.
I'm not sure how to do it otherwise. We could treat it identically to
the Unicode conversion of 0xdC00 + STOUCH(ch) to wchar_t, e.g. iconv
UCS-4 to WCHAR_T, but is that guranteed to work? This needs to be a
robust fallback and it's not clear relying on iconv is the right thing
to do.
The safe option would be only to use this if #ifdef __STDC_ISO_10646__.
On the other hand, it's probably not going to be worse than the previous
code...
pws
diff --git a/Src/pattern.c b/Src/pattern.c
index 7d38988..7457cbd 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -224,6 +224,22 @@ typedef zlong zrange_t;
typedef unsigned long zrange_t;
#endif
+#ifdef MULTIBYTE_SUPPORT
+/*
+ * Handle a byte that's not part of a valid character.
+ *
+ * This range in Unicode is recommended for purposes of this
+ * kind as it corresponds to invalid characters.
+ *
+ * Note that this strictly only works if wchar_t represents
+ * Unicode code points, which isn't necessarily true; however,
+ * converting an invalid character into an unknown format is
+ * a bit tricky...
+ */
+#define WCHAR_INVALID(ch) \
+ ((wchar_t) (0xDC00 + STOUC(ch)))
+#endif /* MULTIBYTE_SUPPORT */
+
/*
* Array of characters corresponding to zpc_chars enum, which it must match.
*/
@@ -353,10 +369,10 @@ metacharinc(char **x)
return wc;
}
- /* Error. Treat as single byte. */
+ /* Error. */
/* Reset the shift state for next time. */
memset(&shiftstate, 0, sizeof(shiftstate));
- return (wchar_t) STOUC(*(*x)++);
+ return WCHAR_INVALID(*(*x)++);
}
#else
@@ -1867,10 +1883,10 @@ charref(char *x, char *y)
ret = mbrtowc(&wc, x, y-x, &shiftstate);
if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- /* Error. Treat as single byte. */
+ /* Error. */
/* Reset the shift state for next time. */
memset(&shiftstate, 0, sizeof(shiftstate));
- return (wchar_t) STOUC(*x);
+ return WCHAR_INVALID(*x);
}
return wc;
@@ -1913,7 +1929,7 @@ charrefinc(char **x, char *y, int *z)
size_t ret;
if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(**x) & 0x80))
- return (wchar_t) STOUC(*(*x)++);
+ return WCHAR_INVALID(*(*x)++);
ret = mbrtowc(&wc, *x, y-*x, &shiftstate);
@@ -1922,7 +1938,7 @@ charrefinc(char **x, char *y, int *z)
*z = 1;
/* Reset the shift state for next time. */
memset(&shiftstate, 0, sizeof(shiftstate));
- return (wchar_t) STOUC(*(*x)++);
+ return WCHAR_INVALID(*(*x)++);
}
/* Nulls here are normal characters */
diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst
index 0e3e98d..3fadd80 100644
--- a/Test/D07multibyte.ztst
+++ b/Test/D07multibyte.ztst
@@ -508,3 +508,20 @@
cd ..
}
0:cd with special characters
+
+ test_array=(
+ '[[ \xcc = \xcc ]]'
+ '[[ \xcc != \xcd ]]'
+ '[[ \xcc != \ucc ]]'
+ '[[ \ucc = \ucc ]]'
+ '[[ \ucc = [\ucc] ]]'
+ '[[ \xcc != [\ucc] ]]'
+ # Not clear how useful the following is...
+ '[[ \xcc = [\xcc] ]]'
+ )
+ for test in $test_array; do
+ if ! eval ${(g::)test} ; then
+ print -rl "Test $test failed" >&2
+ fi
+ done
+0:Invalid characters in pattern matching
Messages sorted by:
Reverse Date,
Date,
Thread,
Author