summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--posix/Makefile9
-rw-r--r--posix/regex.c276
3 files changed, 231 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 4c26c733b9..4577994676 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
2001-06-27 Ulrich Drepper <drepper@redhat.com>
+ * posix/Makefile: Add rules to build and run tst-regex.
+
+2001-06-20 Isamu Hasegawa <isamu@yamato.ibm.com>
+
+ * posix/regex.c (FREE_WCS_BUFFERS): New macro to free buffers.
+ (re_search_2): invoke convert_mbs_to_wcs and FREE_WCS_BUFFERS.
+ (wcs_re_match_2_internal): Check whether the wcs buffers need
+ seting up or not, and skip seting up routin if not needed.
+
+2001-06-26 Isamu Hasegawa <isamu@yamato.ibm.com>
+
+ * posix/regex.c (count_mbs_length): Use binary search for
+ optimization.
+
+2001-06-27 Ulrich Drepper <drepper@redhat.com>
+
* posix/tst-regex.c: Fix several bugs. Add more tests.
2001-06-26 Mark Kettenis <kettenis@gnu.org>
diff --git a/posix/Makefile b/posix/Makefile
index dab29f8cab..6dd8c4427e 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -70,7 +70,7 @@ tests := tstgetopt testfnm runtests runptests \
tst-getlogin tst-mmap tst-getaddrinfo tst-truncate \
tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
- tst-gnuglob
+ tst-gnuglob tst-regex
ifeq (yes,$(build-shared))
test-srcs := globtest
tests += wordexp-test tst-exec tst-spawn
@@ -122,6 +122,7 @@ tst-chmod-ARGS = `pwd`
tst-fnmatch-ENV = LOCPATH=$(common-objpfx)localedata
tst-regexloc-ENV = LOCPATH=$(common-objpfx)localedata
bug-regex1-ENV = LOCPATH=$(common-objpfx)localedata
+tst-regex-ENV = LOCPATH=$(common-objpfx)localedata
testcases.h: TESTS TESTS2C.sed
sed -f TESTS2C.sed < $< > $@T
@@ -158,3 +159,9 @@ $(objpfx)bug-regex2-mem: $(objpfx)bug-regex2.out
$(objpfx)tst-getconf.out: tst-getconf.sh $(objpfx)getconf
$(SHELL) -e $< $(common-objpfx) $(elf-objpfx) $(rtld-installed-name)
+
+ifeq (yes,$(build-shared))
+$(objpfx)tst-regex: $(common-objpfx)rt/librt.so
+else
+$(objpfx)tst-regex: $(common-objpfx)rt/librt.a
+endif
diff --git a/posix/regex.c b/posix/regex.c
index aedabc6f93..a2f20103cc 100644
--- a/posix/regex.c
+++ b/posix/regex.c
@@ -416,11 +416,14 @@ static int byte_re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
struct re_registers *regs,
int stop));
static int wcs_re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
- const char *string1, int size1,
- const char *string2, int size2,
+ const char *cstring1, int csize1,
+ const char *cstring2, int csize2,
int pos,
struct re_registers *regs,
- int stop));
+ int stop,
+ wchar_t *string1, int size1,
+ wchar_t *string2, int size2,
+ int *mbs_offset1, int *mbs_offset2));
static int byte_re_search_2 PARAMS ((struct re_pattern_buffer *bufp,
const char *string1, int size1,
const char *string2, int size2,
@@ -1253,7 +1256,7 @@ convert_mbs_to_wcs (dest, src, len, offset_buffer, is_binary)
size_t wc_count = 0;
mbstate_t mbs;
- int consumed;
+ int i, consumed;
size_t mb_remain = len;
size_t mb_count = 0;
@@ -1286,6 +1289,10 @@ convert_mbs_to_wcs (dest, src, len, offset_buffer, is_binary)
offset_buffer[wc_count + 1] = mb_count += consumed;
}
+ /* Fill remain of the buffer with sentinel. */
+ for (i = wc_count + 1 ; i <= len ; i++)
+ offset_buffer[i] = mb_count + 1;
+
return wc_count;
}
@@ -5047,6 +5054,23 @@ weak_alias (__re_search_2, re_search_2)
#ifdef INSIDE_RECURSION
+#ifdef MATCH_MAY_ALLOCATE
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+#else
+# define FREE_VAR(var) if (var) free (var); var = NULL
+#endif
+
+#ifdef WCHAR
+# define FREE_WCS_BUFFERS() \
+ do { \
+ FREE_VAR (string1); \
+ FREE_VAR (string2); \
+ FREE_VAR (mbs_offset1); \
+ FREE_VAR (mbs_offset2); \
+ } while (0)
+
+#endif
+
static int
PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
regs, stop)
@@ -5063,6 +5087,16 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
register RE_TRANSLATE_TYPE translate = bufp->translate;
int total_size = size1 + size2;
int endpos = startpos + range;
+#ifdef WCHAR
+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */
+ wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL;
+ /* We need the size of wchar_t buffers correspond to csize1, csize2. */
+ int wcs_size1 = 0, wcs_size2 = 0;
+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */
+ int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
+ /* They hold whether each wchar_t is binary data or not. */
+ char *is_binary = NULL;
+#endif /* WCHAR */
/* Check for out-of-range STARTPOS. */
if (startpos < 0 || startpos > total_size)
@@ -5106,6 +5140,45 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
if (re_compile_fastmap (bufp) == -2)
return -2;
+#ifdef WCHAR
+ /* Allocate wchar_t array for wcs_string1 and wcs_string2 and
+ fill them with converted string. */
+ if (size1 != 0)
+ {
+ wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T);
+ mbs_offset1 = REGEX_TALLOC (size1 + 1, int);
+ is_binary = REGEX_TALLOC (size1 + 1, char);
+ if (!wcs_string1 || !mbs_offset1 || !is_binary)
+ {
+ FREE_VAR (wcs_string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1,
+ mbs_offset1, is_binary);
+ wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */
+ FREE_VAR (is_binary);
+ }
+ if (size2 != 0)
+ {
+ wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T);
+ mbs_offset2 = REGEX_TALLOC (size2 + 1, int);
+ is_binary = REGEX_TALLOC (size2 + 1, char);
+ if (!wcs_string2 || !mbs_offset2 || !is_binary)
+ {
+ FREE_WCS_BUFFERS ();
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2,
+ mbs_offset2, is_binary);
+ wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */
+ FREE_VAR (is_binary);
+ }
+#endif /* WCHAR */
+
+
/* Loop through the string, looking for a place to start matching. */
for (;;)
{
@@ -5153,10 +5226,24 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
/* If can't match the null string, and that's all we have left, fail. */
if (range >= 0 && startpos == total_size && fastmap
&& !bufp->can_be_null)
- return -1;
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return -1;
+ }
+
+#ifdef WCHAR
+ val = wcs_re_match_2_internal (bufp, string1, size1, string2,
+ size2, startpos, regs, stop,
+ wcs_string1, wcs_size1,
+ wcs_string2, wcs_size2,
+ mbs_offset1, mbs_offset2);
+#else /* BYTE */
+ val = byte_re_match_2_internal (bufp, string1, size1, string2,
+ size2, startpos, regs, stop);
+#endif /* BYTE */
- val = PREFIX(re_match_2_internal) (bufp, string1, size1, string2,
- size2, startpos, regs, stop);
#ifndef REGEX_MALLOC
# ifdef C_ALLOCA
alloca (0);
@@ -5164,10 +5251,20 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
#endif
if (val >= 0)
- return startpos;
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return startpos;
+ }
if (val == -2)
- return -2;
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return -2;
+ }
advance:
if (!range)
@@ -5183,6 +5280,9 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
startpos--;
}
}
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
return -1;
}
@@ -5255,7 +5355,6 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
/* Free everything we malloc. */
#ifdef MATCH_MAY_ALLOCATE
-# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
# ifdef WCHAR
# define FREE_VARIABLES() \
do { \
@@ -5269,10 +5368,13 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
FREE_VAR (reg_info); \
FREE_VAR (reg_dummy); \
FREE_VAR (reg_info_dummy); \
- FREE_VAR (string1); \
- FREE_VAR (string2); \
- FREE_VAR (mbs_offset1); \
- FREE_VAR (mbs_offset2); \
+ if (!cant_free_wcs_buf) \
+ { \
+ FREE_VAR (string1); \
+ FREE_VAR (string2); \
+ FREE_VAR (mbs_offset1); \
+ FREE_VAR (mbs_offset2); \
+ } \
} while (0)
# else /* BYTE */
# define FREE_VARIABLES() \
@@ -5290,14 +5392,16 @@ PREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range,
} while (0)
# endif /* WCHAR */
#else
-# define FREE_VAR(var) if (var) free (var); var = NULL
# ifdef WCHAR
# define FREE_VARIABLES() \
do { \
- FREE_VAR (string1); \
- FREE_VAR (string2); \
- FREE_VAR (mbs_offset1); \
- FREE_VAR (mbs_offset2); \
+ if (!cant_free_wcs_buf) \
+ { \
+ FREE_VAR (string1); \
+ FREE_VAR (string2); \
+ FREE_VAR (mbs_offset1); \
+ FREE_VAR (mbs_offset2); \
+ } \
} while (0)
# else /* BYTE */
# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
@@ -5331,7 +5435,8 @@ re_match (bufp, string, size, pos, regs)
# ifdef MBS_SUPPORT
if (MB_CUR_MAX != 1)
result = wcs_re_match_2_internal (bufp, NULL, 0, string, size,
- pos, regs, size);
+ pos, regs, size,
+ NULL, 0, NULL, 0, NULL, NULL);
else
# endif
result = byte_re_match_2_internal (bufp, NULL, 0, string, size,
@@ -5390,7 +5495,8 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# ifdef MBS_SUPPORT
if (MB_CUR_MAX != 1)
result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2,
- pos, regs, stop);
+ pos, regs, stop,
+ NULL, 0, NULL, 0, NULL, NULL);
else
# endif
result = byte_re_match_2_internal (bufp, string1, size1, string2, size2,
@@ -5424,7 +5530,7 @@ count_mbs_length(offset_buffer, length)
int *offset_buffer;
int length;
{
- int wcs_size;
+ int upper, lower;
/* Check whether the size is valid. */
if (length < 0)
@@ -5433,45 +5539,73 @@ count_mbs_length(offset_buffer, length)
if (offset_buffer == NULL)
return 0;
- for (wcs_size = 0 ; offset_buffer[wcs_size] != -1 ; wcs_size++)
+ /* If there are no multibyte character, offset_buffer[i] == i.
+ Optmize for this case. */
+ if (offset_buffer[length] == length)
+ return length;
+
+ /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */
+ upper = length;
+ lower = 0;
+
+ while (true)
{
- if (offset_buffer[wcs_size] == length)
- return wcs_size;
- if (offset_buffer[wcs_size] > length)
- /* It is a fragment of a wide character. */
- return -1;
+ int middle = (lower + upper) / 2;
+ if (middle == lower || middle == upper)
+ break;
+ if (offset_buffer[middle] > length)
+ upper = middle;
+ else if (offset_buffer[middle] < length)
+ lower = middle;
+ else
+ return middle;
}
- /* We reached at the sentinel. */
return -1;
}
#endif /* WCHAR */
/* This is a separate function so that we can force an alloca cleanup
afterwards. */
+#ifdef WCHAR
static int
-PREFIX(re_match_2_internal) (bufp, ARG_PREFIX(string1), ARG_PREFIX(size1),
- ARG_PREFIX(string2), ARG_PREFIX(size2), pos,
- regs, stop)
+wcs_re_match_2_internal (bufp, cstring1, csize1, cstring2, csize2, pos,
+ regs, stop, string1, size1, string2, size2,
+ mbs_offset1, mbs_offset2)
struct re_pattern_buffer *bufp;
- const char *ARG_PREFIX(string1), *ARG_PREFIX(string2);
- int ARG_PREFIX(size1), ARG_PREFIX(size2);
+ const char *cstring1, *cstring2;
+ int csize1, csize2;
int pos;
struct re_registers *regs;
int stop;
+ /* string1 == string2 == NULL means string1/2, size1/2 and
+ mbs_offset1/2 need seting up in this function. */
+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */
+ wchar_t *string1, *string2;
+ /* We need the size of wchar_t buffers correspond to csize1, csize2. */
+ int size1, size2;
+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */
+ int *mbs_offset1, *mbs_offset2;
+#else /* BYTE */
+static int
+byte_re_match_2_internal (bufp, string1, size1,string2, size2, pos,
+ regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+#endif /* BYTE */
{
/* General temporaries. */
int mcnt;
UCHAR_T *p1;
#ifdef WCHAR
- /* We need wchar_t* buffers correspond to string1, string2. */
- CHAR_T *string1 = NULL, *string2 = NULL;
- /* We need the size of wchar_t buffers correspond to csize1, csize2. */
- int size1 = 0, size2 = 0;
- /* offset buffer for optimization. See convert_mbs_to_wc. */
- int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
/* They hold whether each wchar_t is binary data or not. */
char *is_binary = NULL;
+ /* If true, we can't free string1/2, mbs_offset1/2. */
+ int cant_free_wcs_buf = 1;
#endif /* WCHAR */
/* Just past the end of the corresponding string. */
@@ -5648,41 +5782,45 @@ PREFIX(re_match_2_internal) (bufp, ARG_PREFIX(string1), ARG_PREFIX(size1),
#ifdef WCHAR
/* Allocate wchar_t array for string1 and string2 and
fill them with converted string. */
- if (csize1 != 0)
+ if (string1 == NULL && string2 == NULL)
{
- string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
- mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
- is_binary = REGEX_TALLOC (csize1 + 1, char);
- if (!string1 || !mbs_offset1 || !is_binary)
+ /* We need seting up buffers here. */
+
+ /* We must free wcs buffers in this function. */
+ cant_free_wcs_buf = 0;
+
+ if (csize1 != 0)
{
- FREE_VAR (string1);
- FREE_VAR (mbs_offset1);
- FREE_VAR (is_binary);
- return -2;
+ string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
+ mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
+ is_binary = REGEX_TALLOC (csize1 + 1, char);
+ if (!string1 || !mbs_offset1 || !is_binary)
+ {
+ FREE_VAR (string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (is_binary);
+ return -2;
+ }
}
- size1 = convert_mbs_to_wcs(string1, cstring1, csize1,
- mbs_offset1, is_binary);
- string1[size1] = L'\0'; /* for a sentinel */
- FREE_VAR (is_binary);
- }
- if (csize2 != 0)
- {
- string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
- mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
- is_binary = REGEX_TALLOC (csize2 + 1, char);
- if (!string2 || !mbs_offset2 || !is_binary)
+ if (csize2 != 0)
{
- FREE_VAR (string1);
- FREE_VAR (mbs_offset1);
- FREE_VAR (string2);
- FREE_VAR (mbs_offset2);
+ string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
+ mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
+ is_binary = REGEX_TALLOC (csize2 + 1, char);
+ if (!string2 || !mbs_offset2 || !is_binary)
+ {
+ FREE_VAR (string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (string2);
+ FREE_VAR (mbs_offset2);
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
+ mbs_offset2, is_binary);
+ string2[size2] = L'\0'; /* for a sentinel */
FREE_VAR (is_binary);
- return -2;
}
- size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
- mbs_offset2, is_binary);
- string2[size2] = L'\0'; /* for a sentinel */
- FREE_VAR (is_binary);
}
/* We need to cast pattern to (wchar_t*), because we casted this compiled