/src/libgit2/deps/pcre2/pcre2_xclass.c
Line | Count | Source |
1 | | /************************************************* |
2 | | * Perl-Compatible Regular Expressions * |
3 | | *************************************************/ |
4 | | |
5 | | /* PCRE is a library of functions to support regular expressions whose syntax |
6 | | and semantics are as close as possible to those of the Perl 5 language. |
7 | | |
8 | | Written by Philip Hazel |
9 | | Original API code Copyright (c) 1997-2012 University of Cambridge |
10 | | New API code Copyright (c) 2016-2024 University of Cambridge |
11 | | |
12 | | ----------------------------------------------------------------------------- |
13 | | Redistribution and use in source and binary forms, with or without |
14 | | modification, are permitted provided that the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the University of Cambridge nor the names of its |
24 | | contributors may be used to endorse or promote products derived from |
25 | | this software without specific prior written permission. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
28 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
29 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
30 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
31 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
33 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
34 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
35 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
36 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | | POSSIBILITY OF SUCH DAMAGE. |
38 | | ----------------------------------------------------------------------------- |
39 | | */ |
40 | | |
41 | | |
42 | | /* This module contains two internal functions that are used to match |
43 | | OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both |
44 | | pcre2_match() and pcre2_dfa_match(). */ |
45 | | |
46 | | |
47 | | #include "pcre2_internal.h" |
48 | | |
49 | | |
50 | | |
51 | | /************************************************* |
52 | | * Match character against an XCLASS * |
53 | | *************************************************/ |
54 | | |
55 | | /* This function is called to match a character against an extended class that |
56 | | might contain codepoints above 255 and/or Unicode properties. |
57 | | |
58 | | Arguments: |
59 | | c the character |
60 | | data points to the flag code unit of the XCLASS data |
61 | | utf TRUE if in UTF mode |
62 | | |
63 | | Returns: TRUE if character matches, else FALSE |
64 | | */ |
65 | | |
66 | | BOOL |
67 | | PRIV(xclass)(uint32_t c, PCRE2_SPTR data, const uint8_t *char_lists_end, BOOL utf) |
68 | 53.7k | { |
69 | | /* Update PRIV(update_classbits) when this function is changed. */ |
70 | 53.7k | PCRE2_UCHAR t; |
71 | 53.7k | BOOL not_negated = (*data & XCL_NOT) == 0; |
72 | 53.7k | uint32_t type, max_index, min_index, value; |
73 | 53.7k | const uint8_t *next_char; |
74 | | |
75 | 53.7k | #if PCRE2_CODE_UNIT_WIDTH == 8 |
76 | | /* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ |
77 | 53.7k | utf = TRUE; |
78 | 53.7k | #endif |
79 | | |
80 | | /* Code points < 256 are matched against a bitmap, if one is present. */ |
81 | | |
82 | 53.7k | if ((*data++ & XCL_MAP) != 0) |
83 | 9.50k | { |
84 | 9.50k | if (c < 256) |
85 | 1.42k | return (((const uint8_t *)data)[c/8] & (1u << (c&7))) != 0; |
86 | | /* Skip bitmap. */ |
87 | 8.08k | data += 32 / sizeof(PCRE2_UCHAR); |
88 | 8.08k | } |
89 | | |
90 | | /* Match against the list of Unicode properties. We won't ever |
91 | | encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */ |
92 | 52.3k | #ifdef SUPPORT_UNICODE |
93 | 52.3k | if (*data == XCL_PROP || *data == XCL_NOTPROP) |
94 | 42.9k | { |
95 | | /* The UCD record is the same for all properties. */ |
96 | 42.9k | const ucd_record *prop = GET_UCD(c); |
97 | | |
98 | 42.9k | do |
99 | 43.9k | { |
100 | 43.9k | int chartype; |
101 | 43.9k | BOOL isprop = (*data++) == XCL_PROP; |
102 | 43.9k | BOOL ok; |
103 | | |
104 | 43.9k | switch(*data) |
105 | 43.9k | { |
106 | 1.48k | case PT_LAMP: |
107 | 1.48k | chartype = prop->chartype; |
108 | 1.48k | if ((chartype == ucp_Lu || chartype == ucp_Ll || |
109 | 722 | chartype == ucp_Lt) == isprop) return not_negated; |
110 | 764 | break; |
111 | | |
112 | 7.07k | case PT_GC: |
113 | 7.07k | if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop) |
114 | 1.71k | return not_negated; |
115 | 5.35k | break; |
116 | | |
117 | 5.35k | case PT_PC: |
118 | 869 | if ((data[1] == prop->chartype) == isprop) return not_negated; |
119 | 575 | break; |
120 | | |
121 | 575 | case PT_SC: |
122 | 328 | if ((data[1] == prop->script) == isprop) return not_negated; |
123 | 117 | break; |
124 | | |
125 | 1.13k | case PT_SCX: |
126 | 1.13k | ok = (data[1] == prop->script || |
127 | 956 | MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0); |
128 | 1.13k | if (ok == isprop) return not_negated; |
129 | 324 | break; |
130 | | |
131 | 799 | case PT_ALNUM: |
132 | 799 | chartype = prop->chartype; |
133 | 799 | if ((PRIV(ucp_gentype)[chartype] == ucp_L || |
134 | 479 | PRIV(ucp_gentype)[chartype] == ucp_N) == isprop) |
135 | 238 | return not_negated; |
136 | 561 | break; |
137 | | |
138 | | /* Perl space used to exclude VT, but from Perl 5.18 it is included, |
139 | | which means that Perl space and POSIX space are now identical. PCRE |
140 | | was changed at release 8.34. */ |
141 | | |
142 | 11.7k | case PT_SPACE: /* Perl space */ |
143 | 13.0k | case PT_PXSPACE: /* POSIX space */ |
144 | 13.0k | switch(c) |
145 | 13.0k | { |
146 | 89.3k | HSPACE_CASES: |
147 | 89.3k | VSPACE_CASES: |
148 | 71.9k | if (isprop) return not_negated; |
149 | 4.96k | break; |
150 | | |
151 | 4.96k | default: |
152 | 1.09k | if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop) |
153 | 411 | return not_negated; |
154 | 683 | break; |
155 | 13.0k | } |
156 | 5.64k | break; |
157 | | |
158 | 5.64k | case PT_WORD: |
159 | 2.26k | chartype = prop->chartype; |
160 | 2.26k | if ((PRIV(ucp_gentype)[chartype] == ucp_L || |
161 | 1.40k | PRIV(ucp_gentype)[chartype] == ucp_N || |
162 | 1.11k | chartype == ucp_Mn || chartype == ucp_Pc) == isprop) |
163 | 798 | return not_negated; |
164 | 1.47k | break; |
165 | | |
166 | 3.26k | case PT_UCNC: |
167 | 3.26k | if (c < 0xa0) |
168 | 1.19k | { |
169 | 1.19k | if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || |
170 | 218 | c == CHAR_GRAVE_ACCENT) == isprop) |
171 | 831 | return not_negated; |
172 | 1.19k | } |
173 | 2.07k | else |
174 | 2.07k | { |
175 | 2.07k | if ((c < 0xd800 || c > 0xdfff) == isprop) |
176 | 1.28k | return not_negated; |
177 | 2.07k | } |
178 | 1.14k | break; |
179 | | |
180 | 1.14k | case PT_BIDICL: |
181 | 796 | if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop) |
182 | 707 | return not_negated; |
183 | 89 | break; |
184 | | |
185 | 595 | case PT_BOOL: |
186 | 595 | ok = MAPBIT(PRIV(ucd_boolprop_sets) + |
187 | 595 | UCD_BPROPS_PROP(prop), data[1]) != 0; |
188 | 595 | if (ok == isprop) return not_negated; |
189 | 353 | break; |
190 | | |
191 | | /* The following three properties can occur only in an XCLASS, as there |
192 | | is no \p or \P coding for them. */ |
193 | | |
194 | | /* Graphic character. Implement this as not Z (space or separator) and |
195 | | not C (other), except for Cf (format) with a few exceptions. This seems |
196 | | to be what Perl does. The exceptional characters are: |
197 | | |
198 | | U+061C Arabic Letter Mark |
199 | | U+180E Mongolian Vowel Separator |
200 | | U+2066 - U+2069 Various "isolate"s |
201 | | */ |
202 | | |
203 | 2.53k | case PT_PXGRAPH: |
204 | 2.53k | chartype = prop->chartype; |
205 | 2.53k | if ((PRIV(ucp_gentype)[chartype] != ucp_Z && |
206 | 2.18k | (PRIV(ucp_gentype)[chartype] != ucp_C || |
207 | 1.41k | (chartype == ucp_Cf && |
208 | 1.22k | c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) |
209 | 2.18k | )) == isprop) |
210 | 1.73k | return not_negated; |
211 | 804 | break; |
212 | | |
213 | | /* Printable character: same as graphic, with the addition of Zs, i.e. |
214 | | not Zl and not Zp, and U+180E. */ |
215 | | |
216 | 2.21k | case PT_PXPRINT: |
217 | 2.21k | chartype = prop->chartype; |
218 | 2.21k | if ((chartype != ucp_Zl && |
219 | 1.92k | chartype != ucp_Zp && |
220 | 1.55k | (PRIV(ucp_gentype)[chartype] != ucp_C || |
221 | 1.31k | (chartype == ucp_Cf && |
222 | 533 | c != 0x061c && (c < 0x2066 || c > 0x2069)) |
223 | 1.55k | )) == isprop) |
224 | 461 | return not_negated; |
225 | 1.75k | break; |
226 | | |
227 | | /* Punctuation: all Unicode punctuation, plus ASCII characters that |
228 | | Unicode treats as symbols rather than punctuation, for Perl |
229 | | compatibility (these are $+<=>^`|~). */ |
230 | | |
231 | 1.75k | case PT_PXPUNCT: |
232 | 997 | chartype = prop->chartype; |
233 | 997 | if ((PRIV(ucp_gentype)[chartype] == ucp_P || |
234 | 653 | (c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop) |
235 | 593 | return not_negated; |
236 | 404 | break; |
237 | | |
238 | | /* Perl has two sets of hex digits */ |
239 | | |
240 | 6.56k | case PT_PXXDIGIT: |
241 | 6.56k | if (((c >= CHAR_0 && c <= CHAR_9) || |
242 | 5.55k | (c >= CHAR_A && c <= CHAR_F) || |
243 | 5.47k | (c >= CHAR_a && c <= CHAR_f) || |
244 | 5.22k | (c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */ |
245 | 4.94k | (c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */ |
246 | 3.98k | (c >= 0xff41 && c <= 0xff46)) == isprop) |
247 | 2.80k | return not_negated; |
248 | 3.76k | break; |
249 | | |
250 | | /* This should never occur, but compilers may mutter if there is no |
251 | | default. */ |
252 | | |
253 | | /* LCOV_EXCL_START */ |
254 | 3.76k | default: |
255 | 0 | PCRE2_DEBUG_UNREACHABLE(); |
256 | 0 | return FALSE; |
257 | | /* LCOV_EXCL_STOP */ |
258 | 43.9k | } |
259 | | |
260 | 23.1k | data += 2; |
261 | 23.1k | } |
262 | 42.9k | while (*data == XCL_PROP || *data == XCL_NOTPROP); |
263 | 42.9k | } |
264 | | #else |
265 | | (void)utf; /* Avoid compiler warning */ |
266 | | #endif /* SUPPORT_UNICODE */ |
267 | | |
268 | | /* Match against large chars or ranges that end with a large char. */ |
269 | 31.4k | if (*data < XCL_LIST) |
270 | 26.4k | { |
271 | 27.5k | while ((t = *data++) != XCL_END) |
272 | 5.31k | { |
273 | 5.31k | uint32_t x, y; |
274 | | |
275 | 5.31k | #ifdef SUPPORT_UNICODE |
276 | 5.31k | if (utf) |
277 | 5.31k | { |
278 | 5.31k | GETCHARINC(x, data); /* macro generates multiple statements */ |
279 | 5.31k | } |
280 | 0 | else |
281 | 0 | #endif |
282 | 0 | x = *data++; |
283 | | |
284 | 5.31k | if (t == XCL_SINGLE) |
285 | 2.62k | { |
286 | | /* Since character ranges follow the properties, and they are |
287 | | sorted, early return is possible for all characters <= x. */ |
288 | 2.62k | if (c <= x) return (c == x) ? not_negated : !not_negated; |
289 | 638 | continue; |
290 | 2.62k | } |
291 | | |
292 | 2.68k | PCRE2_ASSERT(t == XCL_RANGE); |
293 | 2.68k | #ifdef SUPPORT_UNICODE |
294 | 2.68k | if (utf) |
295 | 2.68k | { |
296 | 2.68k | GETCHARINC(y, data); /* macro generates multiple statements */ |
297 | 2.68k | } |
298 | 0 | else |
299 | 0 | #endif |
300 | 0 | y = *data++; |
301 | | |
302 | | /* Since character ranges follow the properties, and they are |
303 | | sorted, early return is possible for all characters <= y. */ |
304 | 2.68k | if (c <= y) return (c >= x) ? not_negated : !not_negated; |
305 | 2.68k | } |
306 | | |
307 | 22.2k | return !not_negated; /* char did not match */ |
308 | 26.4k | } |
309 | | |
310 | 5.03k | #if PCRE2_CODE_UNIT_WIDTH == 8 |
311 | 5.03k | type = (uint32_t)(data[0] << 8) | data[1]; |
312 | 5.03k | data += 2; |
313 | | #else |
314 | | type = data[0]; |
315 | | data++; |
316 | | #endif /* CODE_UNIT_WIDTH */ |
317 | | |
318 | | /* Align characters. */ |
319 | 5.03k | next_char = char_lists_end - (GET(data, 0) << 1); |
320 | 5.03k | type &= XCL_TYPE_MASK; |
321 | | |
322 | | /* Alignment check. */ |
323 | 5.03k | PCRE2_ASSERT(((uintptr_t)next_char & 0x1) == 0); |
324 | | |
325 | 5.03k | if (c >= XCL_CHAR_LIST_HIGH_16_START) |
326 | 2.80k | { |
327 | 2.80k | max_index = type & XCL_ITEM_COUNT_MASK; |
328 | 2.80k | if (max_index == XCL_ITEM_COUNT_MASK) |
329 | 2.66k | { |
330 | 2.66k | max_index = *(const uint16_t*)next_char; |
331 | 2.66k | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
332 | 2.66k | next_char += 2; |
333 | 2.66k | } |
334 | | |
335 | 2.80k | next_char += max_index << 1; |
336 | 2.80k | type >>= XCL_TYPE_BIT_LEN; |
337 | 2.80k | } |
338 | | |
339 | 5.03k | if (c < XCL_CHAR_LIST_LOW_32_START) |
340 | 2.62k | { |
341 | 2.62k | max_index = type & XCL_ITEM_COUNT_MASK; |
342 | | |
343 | 2.62k | c = (uint16_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); |
344 | | |
345 | 2.62k | if (max_index == XCL_ITEM_COUNT_MASK) |
346 | 2.37k | { |
347 | 2.37k | max_index = *(const uint16_t*)next_char; |
348 | 2.37k | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
349 | 2.37k | next_char += 2; |
350 | 2.37k | } |
351 | | |
352 | 2.62k | if (max_index == 0 || c < *(const uint16_t*)next_char) |
353 | 712 | return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; |
354 | | |
355 | 1.90k | min_index = 0; |
356 | 1.90k | value = ((const uint16_t*)next_char)[--max_index]; |
357 | 1.90k | if (c >= value) |
358 | 1.04k | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
359 | | |
360 | 861 | max_index--; |
361 | | |
362 | | /* Binary search of a range. */ |
363 | 2.67k | while (TRUE) |
364 | 2.67k | { |
365 | 2.67k | uint32_t mid_index = (min_index + max_index) >> 1; |
366 | 2.67k | value = ((const uint16_t*)next_char)[mid_index]; |
367 | | |
368 | 2.67k | if (c < value) |
369 | 386 | max_index = mid_index - 1; |
370 | 2.28k | else if (((const uint16_t*)next_char)[mid_index + 1] <= c) |
371 | 1.42k | min_index = mid_index + 1; |
372 | 861 | else |
373 | 861 | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
374 | 2.67k | } |
375 | 861 | } |
376 | | |
377 | | /* Skip the 16 bit ranges. */ |
378 | 2.41k | max_index = type & XCL_ITEM_COUNT_MASK; |
379 | 2.41k | if (max_index == XCL_ITEM_COUNT_MASK) |
380 | 355 | { |
381 | 355 | max_index = *(const uint16_t*)next_char; |
382 | 355 | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
383 | 355 | next_char += 2; |
384 | 355 | } |
385 | | |
386 | 2.41k | next_char += (max_index << 1); |
387 | 2.41k | type >>= XCL_TYPE_BIT_LEN; |
388 | | |
389 | | /* Alignment check. */ |
390 | 2.41k | PCRE2_ASSERT(((uintptr_t)next_char & 0x3) == 0); |
391 | | |
392 | 2.41k | max_index = type & XCL_ITEM_COUNT_MASK; |
393 | | |
394 | | #if PCRE2_CODE_UNIT_WIDTH == 32 |
395 | | if (c >= XCL_CHAR_LIST_HIGH_32_START) |
396 | | { |
397 | | if (max_index == XCL_ITEM_COUNT_MASK) |
398 | | { |
399 | | max_index = *(const uint32_t*)next_char; |
400 | | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
401 | | next_char += 4; |
402 | | } |
403 | | |
404 | | next_char += max_index << 2; |
405 | | type >>= XCL_TYPE_BIT_LEN; |
406 | | max_index = type & XCL_ITEM_COUNT_MASK; |
407 | | } |
408 | | #endif |
409 | | |
410 | 2.41k | c = (uint32_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); |
411 | | |
412 | 2.41k | if (max_index == XCL_ITEM_COUNT_MASK) |
413 | 406 | { |
414 | 406 | max_index = *(const uint32_t*)next_char; |
415 | 406 | next_char += 4; |
416 | 406 | } |
417 | | |
418 | 2.41k | if (max_index == 0 || c < *(const uint32_t*)next_char) |
419 | 867 | return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; |
420 | | |
421 | 1.54k | min_index = 0; |
422 | 1.54k | value = ((const uint32_t*)next_char)[--max_index]; |
423 | 1.54k | if (c >= value) |
424 | 744 | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
425 | | |
426 | 805 | max_index--; |
427 | | |
428 | | /* Binary search of a range. */ |
429 | 1.32k | while (TRUE) |
430 | 1.32k | { |
431 | 1.32k | uint32_t mid_index = (min_index + max_index) >> 1; |
432 | 1.32k | value = ((const uint32_t*)next_char)[mid_index]; |
433 | | |
434 | 1.32k | if (c < value) |
435 | 264 | max_index = mid_index - 1; |
436 | 1.05k | else if (((const uint32_t*)next_char)[mid_index + 1] <= c) |
437 | 254 | min_index = mid_index + 1; |
438 | 805 | else |
439 | 805 | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
440 | 1.32k | } |
441 | 805 | } |
442 | | |
443 | | |
444 | | |
445 | | /************************************************* |
446 | | * Match character against an ECLASS * |
447 | | *************************************************/ |
448 | | |
449 | | /* This function is called to match a character against an extended class |
450 | | used for describing characters using boolean operations on sets. |
451 | | |
452 | | Arguments: |
453 | | c the character |
454 | | data_start points to the start of the ECLASS data |
455 | | data_end points one-past-the-last of the ECLASS data |
456 | | utf TRUE if in UTF mode |
457 | | |
458 | | Returns: TRUE if character matches, else FALSE |
459 | | */ |
460 | | |
461 | | BOOL |
462 | | PRIV(eclass)(uint32_t c, PCRE2_SPTR data_start, PCRE2_SPTR data_end, |
463 | | const uint8_t *char_lists_end, BOOL utf) |
464 | 3.15k | { |
465 | 3.15k | PCRE2_SPTR ptr = data_start; |
466 | 3.15k | PCRE2_UCHAR flags; |
467 | 3.15k | uint32_t stack = 0; |
468 | 3.15k | int stack_depth = 0; |
469 | | |
470 | 3.15k | PCRE2_ASSERT(data_start < data_end); |
471 | 3.15k | flags = *ptr++; |
472 | 3.15k | PCRE2_ASSERT((flags & ECL_MAP) == 0 || |
473 | 3.15k | (data_end - ptr) >= 32 / (int)sizeof(PCRE2_UCHAR)); |
474 | | |
475 | | /* Code points < 256 are matched against a bitmap, if one is present. |
476 | | Otherwise all codepoints are checked later. */ |
477 | | |
478 | 3.15k | if ((flags & ECL_MAP) != 0) |
479 | 686 | { |
480 | 686 | if (c < 256) |
481 | 544 | return (((const uint8_t *)ptr)[c/8] & (1u << (c&7))) != 0; |
482 | | |
483 | | /* Skip the bitmap. */ |
484 | 142 | ptr += 32 / sizeof(PCRE2_UCHAR); |
485 | 142 | } |
486 | | |
487 | | /* Do a little loop, until we reach the end of the ECLASS. */ |
488 | 11.4k | while (ptr < data_end) |
489 | 8.80k | { |
490 | 8.80k | switch (*ptr) |
491 | 8.80k | { |
492 | 635 | case ECL_AND: |
493 | 635 | ++ptr; |
494 | 635 | stack = (stack >> 1) & (stack | ~(uint32_t)1u); |
495 | 635 | PCRE2_ASSERT(stack_depth >= 2); |
496 | 635 | --stack_depth; |
497 | 635 | break; |
498 | | |
499 | 999 | case ECL_OR: |
500 | 999 | ++ptr; |
501 | 999 | stack = (stack >> 1) | (stack & (uint32_t)1u); |
502 | 999 | PCRE2_ASSERT(stack_depth >= 2); |
503 | 999 | --stack_depth; |
504 | 999 | break; |
505 | | |
506 | 1.06k | case ECL_XOR: |
507 | 1.06k | ++ptr; |
508 | 1.06k | stack = (stack >> 1) ^ (stack & (uint32_t)1u); |
509 | 1.06k | PCRE2_ASSERT(stack_depth >= 2); |
510 | 1.06k | --stack_depth; |
511 | 1.06k | break; |
512 | | |
513 | 787 | case ECL_NOT: |
514 | 787 | ++ptr; |
515 | 787 | stack ^= (uint32_t)1u; |
516 | 787 | PCRE2_ASSERT(stack_depth >= 1); |
517 | 787 | break; |
518 | | |
519 | 5.31k | case ECL_XCLASS: |
520 | 5.31k | { |
521 | 5.31k | uint32_t matched = PRIV(xclass)(c, ptr + 1 + LINK_SIZE, char_lists_end, utf); |
522 | | |
523 | 5.31k | ptr += GET(ptr, 1); |
524 | 5.31k | stack = (stack << 1) | matched; |
525 | 5.31k | ++stack_depth; |
526 | 5.31k | break; |
527 | 0 | } |
528 | | |
529 | | /* This should never occur, but compilers may mutter if there is no |
530 | | default. */ |
531 | | |
532 | | /* LCOV_EXCL_START */ |
533 | 0 | default: |
534 | 0 | PCRE2_DEBUG_UNREACHABLE(); |
535 | 0 | return FALSE; |
536 | | /* LCOV_EXCL_STOP */ |
537 | 8.80k | } |
538 | 8.80k | } |
539 | | |
540 | 2.61k | PCRE2_ASSERT(stack_depth == 1); |
541 | 2.61k | (void)stack_depth; /* Ignore unused variable, if assertions are disabled. */ |
542 | | |
543 | | /* The final bit left on the stack now holds the match result. */ |
544 | 2.61k | return (stack & 1u) != 0; |
545 | 2.61k | } |
546 | | |
547 | | /* End of pcre2_xclass.c */ |