/src/r-source/src/extra/tre/regcomp.c
Line | Count | Source |
1 | | /* |
2 | | tre_regcomp.c - TRE POSIX compatible regex compilation functions. |
3 | | |
4 | | This software is released under a BSD-style license. |
5 | | See the file LICENSE for details and copyright. |
6 | | |
7 | | */ |
8 | | |
9 | | #ifdef HAVE_CONFIG_H |
10 | | #include <config.h> |
11 | | #endif /* HAVE_CONFIG_H */ |
12 | | |
13 | | #include <string.h> |
14 | | #include <errno.h> |
15 | | #include <stdlib.h> |
16 | | |
17 | | #include "tre.h" |
18 | | #include "tre-internal.h" |
19 | | #include "xmalloc.h" |
20 | | |
21 | | int |
22 | | tre_regncomp(regex_t *preg, const char *regex, size_t n, int cflags) |
23 | 336 | { |
24 | 336 | int ret; |
25 | 336 | #if TRE_WCHAR |
26 | 336 | tre_char_t *wregex; |
27 | 336 | size_t wlen; |
28 | | |
29 | 336 | wregex = xmalloc(sizeof(tre_char_t) * (n + 1)); |
30 | 336 | if (wregex == NULL) |
31 | 0 | return REG_ESPACE; |
32 | | |
33 | | /* If the current locale uses the standard single byte encoding of |
34 | | characters, we don't do a multibyte string conversion. If we did, |
35 | | many applications which use the default locale would break since |
36 | | the default "C" locale uses the 7-bit ASCII character set, and |
37 | | all characters with the eighth bit set would be considered invalid. */ |
38 | 336 | #if TRE_MULTIBYTE |
39 | 336 | if (TRE_MB_CUR_MAX == 1) |
40 | 336 | #endif /* TRE_MULTIBYTE */ |
41 | 336 | { |
42 | 336 | size_t i; |
43 | 336 | const unsigned char *str = (const unsigned char *)regex; |
44 | 336 | tre_char_t *wstr = wregex; |
45 | | |
46 | 672 | for (i = 0; i < n; i++) |
47 | 336 | *(wstr++) = *(str++); |
48 | 336 | wlen = n; |
49 | 336 | } |
50 | 0 | #if TRE_MULTIBYTE |
51 | 0 | else |
52 | 0 | { |
53 | 0 | size_t consumed; |
54 | 0 | tre_char_t *wcptr = wregex; |
55 | 0 | #ifdef HAVE_MBSTATE_T |
56 | 0 | mbstate_t state; |
57 | 0 | memset(&state, '\0', sizeof(state)); |
58 | 0 | #endif /* HAVE_MBSTATE_T */ |
59 | 0 | while (n > 0) |
60 | 0 | { |
61 | 0 | consumed = tre_mbrtowc(wcptr, regex, n, &state); |
62 | |
|
63 | 0 | switch (consumed) |
64 | 0 | { |
65 | 0 | case 0: |
66 | 0 | if (*regex == '\0') |
67 | 0 | consumed = 1; |
68 | 0 | else |
69 | 0 | { |
70 | 0 | xfree(wregex); |
71 | 0 | return REG_BADPAT; |
72 | 0 | } |
73 | 0 | break; |
74 | 0 | case (size_t)-1: |
75 | 0 | DPRINT(("mbrtowc: error %d: %s.\n", errno, strerror(errno))); |
76 | 0 | xfree(wregex); |
77 | 0 | return REG_BADPAT; |
78 | 0 | case (size_t)-2: |
79 | | /* The last character wasn't complete. Let's not call it a |
80 | | fatal error. */ |
81 | 0 | consumed = n; |
82 | 0 | break; |
83 | 0 | } |
84 | 0 | regex += consumed; |
85 | 0 | n -= consumed; |
86 | 0 | wcptr++; |
87 | 0 | } |
88 | 0 | wlen = wcptr - wregex; |
89 | 0 | } |
90 | 336 | #endif /* TRE_MULTIBYTE */ |
91 | | |
92 | 336 | wregex[wlen] = L'\0'; |
93 | 336 | ret = tre_compile(preg, wregex, wlen, cflags); |
94 | 336 | xfree(wregex); |
95 | | #else /* !TRE_WCHAR */ |
96 | | ret = tre_compile(preg, (const tre_char_t *)regex, n, cflags); |
97 | | #endif /* !TRE_WCHAR */ |
98 | | |
99 | 336 | return ret; |
100 | 336 | } |
101 | | |
102 | | /* this version takes bytes literally, to be used with raw vectors */ |
103 | | int |
104 | | tre_regncompb(regex_t *preg, const char *regex, size_t n, int cflags) |
105 | 0 | { |
106 | 0 | int ret; |
107 | | #if TRE_WCHAR /* wide chars = we need to convert it all to the wide format */ |
108 | 0 | tre_char_t *wregex; |
109 | 0 | size_t i; |
110 | |
|
111 | 0 | wregex = xmalloc(sizeof(tre_char_t) * n); |
112 | 0 | if (wregex == NULL) |
113 | 0 | return REG_ESPACE; |
114 | | |
115 | 0 | for (i = 0; i < n; i++) |
116 | 0 | wregex[i] = (tre_char_t) ((unsigned char) regex[i]); |
117 | |
|
118 | 0 | ret = tre_compile(preg, wregex, n, cflags | REG_USEBYTES); |
119 | 0 | xfree(wregex); |
120 | | #else /* !TRE_WCHAR */ |
121 | | ret = tre_compile(preg, (const tre_char_t *)regex, n, cflags | REG_USEBYTES); |
122 | | #endif /* !TRE_WCHAR */ |
123 | |
|
124 | 0 | return ret; |
125 | 0 | } |
126 | | |
127 | | int |
128 | | tre_regcomp(regex_t *preg, const char *regex, int cflags) |
129 | 336 | { |
130 | 336 | return tre_regncomp(preg, regex, regex ? strlen(regex) : 0, cflags); |
131 | 336 | } |
132 | | |
133 | | int |
134 | | tre_regcompb(regex_t *preg, const char *regex, int cflags) |
135 | 844k | { |
136 | 844k | int ret; |
137 | 844k | tre_char_t *wregex; |
138 | 844k | size_t wlen, n = strlen(regex); |
139 | 844k | unsigned int i; |
140 | 844k | const unsigned char *str = (const unsigned char *)regex; |
141 | 844k | tre_char_t *wstr; |
142 | | |
143 | 844k | wregex = xmalloc(sizeof(tre_char_t) * (n + 1)); |
144 | 844k | if (wregex == NULL) return REG_ESPACE; |
145 | 844k | wstr = wregex; |
146 | | |
147 | 8.02M | for (i = 0; i < n; i++) *(wstr++) = *(str++); |
148 | 844k | wlen = n; |
149 | 844k | wregex[wlen] = L'\0'; |
150 | 844k | ret = tre_compile(preg, wregex, wlen, cflags | REG_USEBYTES); |
151 | 844k | xfree(wregex); |
152 | 844k | return ret; |
153 | 844k | } |
154 | | |
155 | | |
156 | | #ifdef TRE_WCHAR |
157 | | int |
158 | | tre_regwncomp(regex_t *preg, const wchar_t *regex, size_t n, int cflags) |
159 | 0 | { |
160 | 0 | return tre_compile(preg, regex, n, cflags); |
161 | 0 | } |
162 | | |
163 | | int |
164 | | tre_regwcomp(regex_t *preg, const wchar_t *regex, int cflags) |
165 | 1.96k | { |
166 | 1.96k | return tre_compile(preg, regex, regex ? wcslen(regex) : 0, cflags); |
167 | 1.96k | } |
168 | | #endif /* TRE_WCHAR */ |
169 | | |
170 | | void |
171 | | tre_regfree(regex_t *preg) |
172 | 847k | { |
173 | 847k | tre_free(preg); |
174 | 847k | } |
175 | | |
176 | | /* EOF */ |