diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2001-02-02 08:47:28 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2001-02-02 08:47:28 +0000 |
| commit | e4c785c8d771f50c4c7a059b545976301bd2508c (patch) | |
| tree | ef058109dcbcefdf4d75c08d6661f1e5874deadc | |
| parent | 4b1fef8482da6863711fdb64f06413f06424dad7 (diff) | |
| download | glibc-e4c785c8d771f50c4c7a059b545976301bd2508c.tar.xz glibc-e4c785c8d771f50c4c7a059b545976301bd2508c.zip | |
Update.
* posix/regex.c: Implement multibyte character handling.
Patch by Isamu Hasegawa <isamu@yamato.ibm.co.jp>.
| -rw-r--r-- | ChangeLog | 3 | ||||
| -rw-r--r-- | linuxthreads/ChangeLog | 4 | ||||
| -rw-r--r-- | linuxthreads/Versions | 3 | ||||
| -rw-r--r-- | posix/regex.c | 2115 |
4 files changed, 1857 insertions, 268 deletions
@@ -1,5 +1,8 @@ 2001-02-02 Ulrich Drepper <drepper@redhat.com> + * posix/regex.c: Implement multibyte character handling. + Patch by Isamu Hasegawa <isamu@yamato.ibm.co.jp>. + * string/tst-svc.input: Add two more test cases. * string/tst-svc.expect: Modify to reflect new test cases. diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index e4739ca60e..3e5e7b09d3 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,7 @@ +2001-02-02 Ulrich Drepper <drepper@redhat.com> + + * Versions: Remove __pthread_initialize_minimal. + 2001-02-01 Ulrich Drepper <drepper@redhat.com> * Makefile: Add rules to build crti.o and make it being used in diff --git a/linuxthreads/Versions b/linuxthreads/Versions index 8f38b9b604..3541002ad5 100644 --- a/linuxthreads/Versions +++ b/linuxthreads/Versions @@ -151,8 +151,5 @@ libpthread { # Extensions. pthread_yield; - - # New internal function. - __pthread_initialize_minimal; } } diff --git a/posix/regex.c b/posix/regex.c index 440194a201..6a8c899e97 100644 --- a/posix/regex.c +++ b/posix/regex.c @@ -2,7 +2,7 @@ version 0.12. (Implements POSIX draft P1003.2/D11.2, except for some of the internationalization features.) - Copyright (C) 1993-1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1993-1999, 2000, 2001 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -56,6 +56,23 @@ # include <wctype.h> #endif +/* This is for multi byte string support. */ +#ifdef MBS_SUPPORT +# define CHAR_TYPE wchar_t +# define US_CHAR_TYPE wchar_t/* unsigned character type */ +# define COMPILED_BUFFER_VAR wc_buffer +# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ +# define PUT_CHAR(c) printf ("%C", c) /* Should we use wide stream?? */ +# define TRUE 1 +# define FALSE 0 +#else +# define CHAR_TYPE char +# define US_CHAR_TYPE unsigned char /* unsigned character type */ +# define COMPILED_BUFFER_VAR bufp->buffer +# define OFFSET_ADDRESS_SIZE 2 +# define PUT_CHAR(c) putchar (c) +#endif /* MBS_SUPPORT */ + #ifdef _LIBC /* We have to keep the namespace clean. */ # define regfree(preg) __regfree (preg) @@ -84,6 +101,7 @@ # include <locale/localeinfo.h> # include <locale/elem-hash.h> # include <langinfo.h> +# include <locale/coll-lookup.h> #endif /* This is for other GNU distributions with internationalized messages. */ @@ -414,6 +432,11 @@ typedef enum /* Followed by one byte giving n, then by n literal bytes. */ exactn, +#ifdef MBS_SUPPORT + /* Same as exactn, but contains binary data. */ + exactn_bin, +#endif + /* Matches any (more or less) character. */ anychar, @@ -423,6 +446,13 @@ typedef enum are ordered low-bit-first. A character is in the set if its bit is 1. A character too large to have a bit in the map is automatically not in the set. */ + /* ifdef MBS_SUPPORT, following element is length of character + classes, length of collating symbols, length of equivalence + classes, length of character ranges, and length of characters. + Next, character class element, collating symbols elements, + equivalence class elements, range elements, and character + elements follow. + See regex_compile function. */ charset, /* Same parameters as charset, but match any character that is @@ -472,6 +502,7 @@ typedef enum /* Followed by two-byte relative address of place to resume at in case of failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ on_failure_jump, /* Like on_failure_jump, but pushes a placeholder instead of the @@ -480,6 +511,7 @@ typedef enum /* Throw away latest failure point and then jump to following two-byte relative address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ pop_failure_jump, /* Change to pop_failure_jump if know won't have to backtrack to @@ -489,6 +521,7 @@ typedef enum sure that there is no use backtracking out of repetitions already matched, then we change it to a pop_failure_jump. Followed by two-byte address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ maybe_pop_jump, /* Jump to following two-byte address, and push a dummy failure @@ -496,6 +529,7 @@ typedef enum is made to use it for a failure. A `+' construct makes this before the first repeat. Also used as an intermediary kind of jump when compiling an alternative. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ dummy_failure_jump, /* Push a dummy failure point and continue. Used at the end of @@ -504,15 +538,18 @@ typedef enum /* Followed by two-byte relative address and two-byte number n. After matching N times, jump to the address upon failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ succeed_n, /* Followed by two-byte relative address, and two-byte number n. Jump to the address N times, then fail. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ jump_n, /* Set the following two-byte relative address to the subsequent two-byte number. The address *includes* the two bytes of number. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ set_number_at, wordchar, /* Matches any word-constituent character. */ @@ -541,42 +578,63 @@ typedef enum /* Common operations on the compiled pattern. */ /* Store NUMBER in two contiguous bytes starting at DESTINATION. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -#define STORE_NUMBER(destination, number) \ +#ifdef MBS_SUPPORT +# define STORE_NUMBER(destination, number) \ + do { \ + *(destination) = (US_CHAR_TYPE)(number); \ + } while (0) +#else +# define STORE_NUMBER(destination, number) \ do { \ (destination)[0] = (number) & 0377; \ (destination)[1] = (number) >> 8; \ } while (0) +#endif /* MBS_SUPPORT */ /* Same as STORE_NUMBER, except increment DESTINATION to the byte after where the number is stored. Therefore, DESTINATION must be an lvalue. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ #define STORE_NUMBER_AND_INCR(destination, number) \ do { \ STORE_NUMBER (destination, number); \ - (destination) += 2; \ + (destination) += OFFSET_ADDRESS_SIZE; \ } while (0) /* Put into DESTINATION a number stored in two contiguous bytes starting at SOURCE. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ -#define EXTRACT_NUMBER(destination, source) \ +#ifdef MBS_SUPPORT +# define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source); \ + } while (0) +#else +# define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source) & 0377; \ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ } while (0) +#endif #ifdef DEBUG -static void extract_number _RE_ARGS ((int *dest, unsigned char *source)); +static void extract_number _RE_ARGS ((int *dest, US_CHAR_TYPE *source)); static void extract_number (dest, source) int *dest; - unsigned char *source; + US_CHAR_TYPE *source; { +#ifdef MBS_SUPPORT + *dest = *source; +#else int temp = SIGN_EXTEND_CHAR (*(source + 1)); *dest = *source & 0377; *dest += temp << 8; +#endif } # ifndef EXTRACT_MACROS /* To debug the macros. */ @@ -592,19 +650,19 @@ extract_number (dest, source) #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ - (source) += 2; \ + (source) += OFFSET_ADDRESS_SIZE; \ } while (0) #ifdef DEBUG static void extract_number_and_incr _RE_ARGS ((int *destination, - unsigned char **source)); + US_CHAR_TYPE **source)); static void extract_number_and_incr (destination, source) int *destination; - unsigned char **source; + US_CHAR_TYPE **source; { extract_number (destination, *source); - *source += 2; + *source += OFFSET_ADDRESS_SIZE; } # ifndef EXTRACT_MACROS @@ -678,13 +736,13 @@ print_fastmap (fastmap) void print_partial_compiled_pattern (start, end) - unsigned char *start; - unsigned char *end; + US_CHAR_TYPE *start; + US_CHAR_TYPE *end; { int mcnt, mcnt2; - unsigned char *p1; - unsigned char *p = start; - unsigned char *pend = end; + US_CHAR_TYPE *p1; + US_CHAR_TYPE *p = start; + US_CHAR_TYPE *pend = end; if (start == NULL) { @@ -713,11 +771,23 @@ print_partial_compiled_pattern (start, end) do { putchar ('/'); - putchar (*p++); + PUT_CHAR (*p++); } while (--mcnt); break; +#ifdef MBS_SUPPORT + case exactn_bin: + mcnt = *p++; + printf ("/exactn_bin/%d", mcnt); + do + { + printf("/%x", *p++); + } + while (--mcnt); + break; +#endif /* MBS_SUPPORT */ + case start_memory: mcnt = *p++; printf ("/start_memory/%d/%d", mcnt, *p++); @@ -739,6 +809,45 @@ print_partial_compiled_pattern (start, end) case charset: case charset_not: { +#ifdef MBS_SUPPORT + int i, length; + wchar_t *workp = p; + printf ("/charset [%s", + (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); + p += 5; + length = *workp++; /* the length of char_classes */ + for (i=0 ; i<length ; i++) + printf("[:%x:]", *p++); + length = *workp++; /* the length of collating_symbol */ + for (i=0 ; i<length ;) + { + printf("[."); + while(*p != 0) + PUT_CHAR((i++,*p++)); + i++,p++; + printf(".]"); + } + length = *workp++; /* the length of equivalence_class */ + for (i=0 ; i<length ;) + { + printf("[="); + while(*p != 0) + PUT_CHAR((i++,*p++)); + i++,p++; + printf("=]"); + } + length = *workp++; /* the length of char_range */ + for (i=0 ; i<length ; i++) + { + wchar_t range_start = *p++; + wchar_t range_end = *p++; + printf("%C-%C", range_start, range_end); + } + length = *workp++; /* the length of char */ + for (i=0 ; i<length ; i++) + printf("%C", *p++); + putchar (']'); +#else register int c, last = -100; register int in_range = 0; @@ -776,6 +885,7 @@ print_partial_compiled_pattern (start, end) putchar (']'); p += 1 + *p; +#endif /* MBS_SUPPORT */ } break; @@ -900,6 +1010,7 @@ print_partial_compiled_pattern (start, end) case wordend: printf ("/wordend"); + break; # ifdef emacs case before_dot: @@ -962,9 +1073,10 @@ void print_compiled_pattern (bufp) struct re_pattern_buffer *bufp; { - unsigned char *buffer = bufp->buffer; + US_CHAR_TYPE *buffer = (US_CHAR_TYPE*) bufp->buffer; - print_partial_compiled_pattern (buffer, buffer + bufp->used); + print_partial_compiled_pattern (buffer, buffer + + bufp->used / sizeof(US_CHAR_TYPE)); printf ("%ld bytes used/%ld bytes allocated.\n", bufp->used, bufp->allocated); @@ -992,9 +1104,9 @@ print_compiled_pattern (bufp) void print_double_string (where, string1, size1, string2, size2) - const char *where; - const char *string1; - const char *string2; + const CHAR_TYPE *where; + const CHAR_TYPE *string1; + const CHAR_TYPE *string2; int size1; int size2; { @@ -1007,13 +1119,13 @@ print_double_string (where, string1, size1, string2, size2) if (FIRST_STRING_P (where)) { for (this_char = where - string1; this_char < size1; this_char++) - putchar (string1[this_char]); + PUT_CHAR (string1[this_char]); where = string2; } for (this_char = where - string2; this_char < size2; this_char++) - putchar (string2[this_char]); + PUT_CHAR (string2[this_char]); } } @@ -1039,6 +1151,88 @@ printchar (c) #endif /* not DEBUG */ +#ifdef MBS_SUPPORT +/* This convert a multibyte string to a wide character string. + And write their correspondances to offset_buffer(see below) + and write whether each wchar_t is binary data to is_binary. + This assume invalid multibyte sequences as binary data. + We assume offset_buffer and is_binary is already allocated + enough space. */ +size_t +convert_mbs_to_wcs (dest, src, len, offset_buffer, is_binary) + CHAR_TYPE *dest; + const unsigned char* src; + size_t len; /* the length of multibyte string. */ + + /* It hold correspondances between src(char string) and + dest(wchar_t string) for optimization. + e.g. src = "xxxyzz" + dest = {'X', 'Y', 'Z'} + (each "xxx", "y" and "zz" represent one multibyte character + corresponding to 'X', 'Y' and 'Z'.) + offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} + = {0, 3, 4, 6} + */ + int *offset_buffer; + int *is_binary; +{ + wchar_t *pdest = dest; + const unsigned char *psrc = src; + size_t wc_count = 0; + + if (MB_CUR_MAX == 1) + { /* We don't need conversion. */ + for ( ; wc_count < len ; ++wc_count) + { + *pdest++ = *psrc++; + is_binary[wc_count] = FALSE; + offset_buffer[wc_count] = wc_count; + } + offset_buffer[wc_count] = wc_count; + } + else + { + /* We need conversion. */ + mbstate_t mbs; + int consumed; + size_t mb_remain = len; + size_t mb_count = 0; + + /* Initialize the conversion state. */ + memset (&mbs, 0, sizeof (mbstate_t)); + + offset_buffer[0] = 0; + for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, + psrc += consumed) + { + consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); + + if (consumed <= 0) + /* failed to convert. maybe src contains binary data. + So we consume 1 byte manualy. */ + { + *pdest = *psrc; + consumed = 1; + is_binary[wc_count] = TRUE; + } + else + is_binary[wc_count] = FALSE; + /* In sjis encoding, we use yen sign as escape character in + place of reverse solidus. So we convert 0x5c(yen sign in + sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse + solidus in UCS2). */ + if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) + *pdest = (wchar_t) *psrc; + + offset_buffer[wc_count + 1] = mb_count += consumed; + } + } + + return wc_count; +} + +#endif /* MBS_SUPPORT */ + /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ @@ -1220,7 +1414,7 @@ long int re_max_failures = 2000; union fail_stack_elt { - unsigned char *pointer; + US_CHAR_TYPE *pointer; long int integer; }; @@ -1245,7 +1439,7 @@ int re_max_failures = 2000; union fail_stack_elt { - unsigned char *pointer; + US_CHAR_TYPE *pointer; int integer; }; @@ -1327,7 +1521,7 @@ typedef struct Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_POINTER(item) \ - fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item) + fail_stack.stack[fail_stack.avail++].pointer = (US_CHAR_TYPE *) (item) /* This pushes an integer-valued item onto the failure stack. Assumes the variable `fail_stack'. Probably should only @@ -1484,12 +1678,11 @@ typedef struct Also assumes the variables `fail_stack' and (if debugging), `bufp', `pend', `string1', `size1', `string2', and `size2'. */ - #define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ { \ DEBUG_STATEMENT (unsigned failure_id;) \ active_reg_t this_reg; \ - const unsigned char *string_temp; \ + const US_CHAR_TYPE *string_temp; \ \ assert (!FAIL_STACK_EMPTY ()); \ \ @@ -1508,13 +1701,13 @@ typedef struct saved NULL, thus retaining our current position in the string. */ \ string_temp = POP_FAILURE_POINTER (); \ if (string_temp != NULL) \ - str = (const char *) string_temp; \ + str = (const CHAR_TYPE *) string_temp; \ \ DEBUG_PRINT2 (" Popping string %p: `", str); \ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ DEBUG_PRINT1 ("'\n"); \ \ - pat = (unsigned char *) POP_FAILURE_POINTER (); \ + pat = (US_CHAR_TYPE *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ \ @@ -1534,10 +1727,10 @@ typedef struct DEBUG_PRINT2 (" info: %p\n", \ reg_info[this_reg].word.pointer); \ \ - regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \ + regend[this_reg] = (const CHAR_TYPE *) POP_FAILURE_POINTER (); \ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ \ - regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \ + regstart[this_reg] = (const CHAR_TYPE *) POP_FAILURE_POINTER ();\ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ } \ else \ @@ -1555,7 +1748,6 @@ typedef struct DEBUG_STATEMENT (nfailure_points_popped++); \ } /* POP_FAILURE_POINT */ - /* Structure for per-register (a.k.a. per-group) information. Other register information, such as the @@ -1613,7 +1805,7 @@ typedef union while (0) /* Registers are set to a sentinel when they haven't yet matched. */ -static char reg_unset_dummy; +static CHAR_TYPE reg_unset_dummy; #define REG_UNSET_VALUE (®_unset_dummy) #define REG_UNSET(e) ((e) == REG_UNSET_VALUE) @@ -1622,41 +1814,65 @@ static char reg_unset_dummy; static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size, reg_syntax_t syntax, struct re_pattern_buffer *bufp)); -static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg)); -static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, +static void store_op1 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, int arg)); +static void store_op2 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, int arg1, int arg2)); -static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg, unsigned char *end)); -static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg1, int arg2, unsigned char *end)); -static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p, +static void insert_op1 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, + int arg, US_CHAR_TYPE *end)); +static void insert_op2 _RE_ARGS ((re_opcode_t op, US_CHAR_TYPE *loc, + int arg1, int arg2, US_CHAR_TYPE *end)); +static boolean at_begline_loc_p _RE_ARGS ((const CHAR_TYPE *pattern, + const CHAR_TYPE *p, reg_syntax_t syntax)); -static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend, +static boolean at_endline_loc_p _RE_ARGS ((const CHAR_TYPE *p, + const CHAR_TYPE *pend, reg_syntax_t syntax)); +#ifdef MBS_SUPPORT +static reg_errcode_t compile_range _RE_ARGS ((CHAR_TYPE range_start, + const CHAR_TYPE **p_ptr, + const CHAR_TYPE *pend, + char *translate, + reg_syntax_t syntax, + US_CHAR_TYPE *b, + CHAR_TYPE *char_set)); +static void insert_space _RE_ARGS ((int num, CHAR_TYPE *loc, CHAR_TYPE *end)); +#else static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, - const char **p_ptr, - const char *pend, + const CHAR_TYPE **p_ptr, + const CHAR_TYPE *pend, char *translate, reg_syntax_t syntax, - unsigned char *b)); + US_CHAR_TYPE *b)); +#endif /* MBS_SUPPORT */ /* Fetch the next character in the uncompiled pattern---translating it if necessary. Also cast from a signed character in the constant string passed to us by the user to an unsigned char that we can use as an array index (in, e.g., `translate'). */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ #ifndef PATFETCH -# define PATFETCH(c) \ +# ifdef MBS_SUPPORT +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (US_CHAR_TYPE) *p++; \ + if (translate && (c <= 0xff)) c = (US_CHAR_TYPE) translate[c]; \ + } while (0) +# else +# define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ if (translate) c = (unsigned char) translate[c]; \ } while (0) +# endif /* MBS_SUPPORT */ #endif /* Fetch the next character in the uncompiled pattern, with no translation. */ #define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ + c = (US_CHAR_TYPE) *p++; \ } while (0) /* Go backwards one character in the pattern. */ @@ -1667,27 +1883,42 @@ static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start, cast the subscript to translate because some data is declared as `char *', to avoid warnings when a string constant is passed. But when we use a character as a subscript we must make it unsigned. */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ #ifndef TRANSLATE -# define TRANSLATE(d) \ +# ifdef MBS_SUPPORT +# define TRANSLATE(d) \ + (translate && (sizeof(d) <= 1)? (char) translate[(unsigned char) (d)] : (d)) +#else +# define TRANSLATE(d) \ (translate ? (char) translate[(unsigned char) (d)] : (d)) +# endif /* MBS_SUPPORT */ #endif /* Macros for outputting the compiled pattern into `buffer'. */ /* If the buffer isn't allocated when it comes in, use this. */ -#define INIT_BUF_SIZE 32 +#define INIT_BUF_SIZE (32 * sizeof(US_CHAR_TYPE)) /* Make sure we have a |
