Raw
1 /* Extended regular expression matching and search library.
2 Copyright (C) 2002-2006, 2010 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20 static void re_string_construct_common (const char *str, int len,
21 re_string_t *pstr,
22 RE_TRANSLATE_TYPE trans, int icase,
23 const re_dfa_t *dfa) internal_function;
24 static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
25 const re_node_set *nodes,
26 unsigned int hash) internal_function;
27 static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
28 const re_node_set *nodes,
29 unsigned int context,
30 unsigned int hash) internal_function;
31
32 #ifdef GAWK
33 #undef MAX /* safety */
34 static int
35 MAX(size_t a, size_t b)
36 {
37 return (a > b ? a : b);
38 }
39 #endif
40
41 /* Functions for string operation. */
42
43 /* This function allocate the buffers. It is necessary to call
44 re_string_reconstruct before using the object. */
45
46 static reg_errcode_t
47 internal_function
48 re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
49 RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
50 {
51 reg_errcode_t ret;
52 int init_buf_len;
53
54 /* Ensure at least one character fits into the buffers. */
55 if (init_len < dfa->mb_cur_max)
56 init_len = dfa->mb_cur_max;
57 init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
58 re_string_construct_common (str, len, pstr, trans, icase, dfa);
59
60 ret = re_string_realloc_buffers (pstr, init_buf_len);
61 if (BE (ret != REG_NOERROR, 0))
62 return ret;
63
64 pstr->word_char = dfa->word_char;
65 pstr->word_ops_used = dfa->word_ops_used;
66 pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
67 pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
68 pstr->valid_raw_len = pstr->valid_len;
69 return REG_NOERROR;
70 }
71
72 /* This function allocate the buffers, and initialize them. */
73
74 static reg_errcode_t
75 internal_function
76 re_string_construct (re_string_t *pstr, const char *str, int len,
77 RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
78 {
79 reg_errcode_t ret;
80 memset (pstr, '\0', sizeof (re_string_t));
81 re_string_construct_common (str, len, pstr, trans, icase, dfa);
82
83 if (len > 0)
84 {
85 ret = re_string_realloc_buffers (pstr, len + 1);
86 if (BE (ret != REG_NOERROR, 0))
87 return ret;
88 }
89 pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
90
91 if (icase)
92 {
93 #ifdef RE_ENABLE_I18N
94 if (dfa->mb_cur_max > 1)
95 {
96 while (1)
97 {
98 ret = build_wcs_upper_buffer (pstr);
99 if (BE (ret != REG_NOERROR, 0))
100 return ret;
101 if (pstr->valid_raw_len >= len)
102 break;
103 if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
104 break;
105 ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
106 if (BE (ret != REG_NOERROR, 0))
107 return ret;
108 }
109 }
110 else
111 #endif /* RE_ENABLE_I18N */
112 build_upper_buffer (pstr);
113 }
114 else
115 {
116 #ifdef RE_ENABLE_I18N
117 if (dfa->mb_cur_max > 1)
118 build_wcs_buffer (pstr);
119 else
120 #endif /* RE_ENABLE_I18N */
121 {
122 if (trans != NULL)
123 re_string_translate_buffer (pstr);
124 else
125 {
126 pstr->valid_len = pstr->bufs_len;
127 pstr->valid_raw_len = pstr->bufs_len;
128 }
129 }
130 }
131
132 return REG_NOERROR;
133 }
134
135 /* Helper functions for re_string_allocate, and re_string_construct. */
136
137 static reg_errcode_t
138 internal_function
139 re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
140 {
141 #ifdef RE_ENABLE_I18N
142 if (pstr->mb_cur_max > 1)
143 {
144 wint_t *new_wcs;
145
146 /* Avoid overflow in realloc. */
147 const size_t max_object_size = MAX (sizeof (wint_t), sizeof (int));
148 if (BE (SIZE_MAX / max_object_size < new_buf_len, 0))
149 return REG_ESPACE;
150
151 new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
152 if (BE (new_wcs == NULL, 0))
153 return REG_ESPACE;
154 pstr->wcs = new_wcs;
155 if (pstr->offsets != NULL)
156 {
157 int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
158 if (BE (new_offsets == NULL, 0))
159 return REG_ESPACE;
160 pstr->offsets = new_offsets;
161 }
162 }
163 #endif /* RE_ENABLE_I18N */
164 if (pstr->mbs_allocated)
165 {
166 unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
167 new_buf_len);
168 if (BE (new_mbs == NULL, 0))
169 return REG_ESPACE;
170 pstr->mbs = new_mbs;
171 }
172 pstr->bufs_len = new_buf_len;
173 return REG_NOERROR;
174 }
175
176
177 static void
178 internal_function
179 re_string_construct_common (const char *str, int len, re_string_t *pstr,
180 RE_TRANSLATE_TYPE trans, int icase,
181 const re_dfa_t *dfa)
182 {
183 pstr->raw_mbs = (const unsigned char *) str;
184 pstr->len = len;
185 pstr->raw_len = len;
186 pstr->trans = trans;
187 pstr->icase = icase ? 1 : 0;
188 pstr->mbs_allocated = (trans != NULL || icase);
189 pstr->mb_cur_max = dfa->mb_cur_max;
190 pstr->is_utf8 = dfa->is_utf8;
191 pstr->map_notascii = dfa->map_notascii;
192 pstr->stop = pstr->len;
193 pstr->raw_stop = pstr->stop;
194 }
195
196 #ifdef RE_ENABLE_I18N
197
198 /* Build wide character buffer PSTR->WCS.
199 If the byte sequence of the string are:
200 <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
201 Then wide character buffer will be:
202 <wc1> , WEOF , <wc2> , WEOF , <wc3>
203 We use WEOF for padding, they indicate that the position isn't
204 a first byte of a multibyte character.
205
206 Note that this function assumes PSTR->VALID_LEN elements are already
207 built and starts from PSTR->VALID_LEN. */
208
209 static void
210 internal_function
211 build_wcs_buffer (re_string_t *pstr)
212 {
213 #ifdef _LIBC
214 unsigned char buf[MB_LEN_MAX];
215 assert (MB_LEN_MAX >= pstr->mb_cur_max);
216 #else
217 unsigned char buf[64];
218 #endif
219 mbstate_t prev_st;
220 int byte_idx, end_idx, remain_len;
221 size_t mbclen;
222
223 /* Build the buffers from pstr->valid_len to either pstr->len or
224 pstr->bufs_len. */
225 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
226 for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
227 {
228 wchar_t wc;
229 const char *p;
230
231 remain_len = end_idx - byte_idx;
232 prev_st = pstr->cur_state;
233 /* Apply the translation if we need. */
234 if (BE (pstr->trans != NULL, 0))
235 {
236 int i, ch;
237
238 for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
239 {
240 ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
241 buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
242 }
243 p = (const char *) buf;
244 }
245 else
246 p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
247 mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
248 if (BE (mbclen == (size_t) -2, 0))
249 {
250 /* The buffer doesn't have enough space, finish to build. */
251 pstr->cur_state = prev_st;
252 break;
253 }
254 else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
255 {
256 /* We treat these cases as a singlebyte character. */
257 mbclen = 1;
258 wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
259 if (BE (pstr->trans != NULL, 0))
260 wc = pstr->trans[wc];
261 pstr->cur_state = prev_st;
262 }
263
264 /* Write wide character and padding. */
265 pstr->wcs[byte_idx++] = wc;
266 /* Write paddings. */
267 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
268 pstr->wcs[byte_idx++] = WEOF;
269 }
270 pstr->valid_len = byte_idx;
271 pstr->valid_raw_len = byte_idx;
272 }
273
274 /* Build wide character buffer PSTR->WCS like build_wcs_buffer,
275 but for REG_ICASE. */
276
277 static reg_errcode_t
278 internal_function
279 build_wcs_upper_buffer (re_string_t *pstr)
280 {
281 mbstate_t prev_st;
282 int src_idx, byte_idx, end_idx, remain_len;
283 size_t mbclen;
284 #ifdef _LIBC
285 char buf[MB_LEN_MAX];
286 assert (MB_LEN_MAX >= pstr->mb_cur_max);
287 #else
288 char buf[64];
289 #endif
290
291 byte_idx = pstr->valid_len;
292 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
293
294 /* The following optimization assumes that ASCII characters can be
295 mapped to wide characters with a simple cast. */
296 if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
297 {
298 while (byte_idx < end_idx)
299 {
300 wchar_t wc;
301
302 if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
303 && mbsinit (&pstr->cur_state))
304 {
305 /* In case of a singlebyte character. */
306 pstr->mbs[byte_idx]
307 = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
308 /* The next step uses the assumption that wchar_t is encoded
309 ASCII-safe: all ASCII values can be converted like this. */
310 pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
311 ++byte_idx;
312 continue;
313 }
314
315 remain_len = end_idx - byte_idx;
316 prev_st = pstr->cur_state;
317 mbclen = __mbrtowc (&wc,
318 ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
319 + byte_idx), remain_len, &pstr->cur_state);
320 if (BE (mbclen + 2 > 2, 1))
321 {
322 wchar_t wcu = wc;
323 if (iswlower (wc))
324 {
325 size_t mbcdlen;
326
327 wcu = towupper (wc);
328 mbcdlen = wcrtomb (buf, wcu, &prev_st);
329 if (BE (mbclen == mbcdlen, 1))
330 memcpy (pstr->mbs + byte_idx, buf, mbclen);
331 else
332 {
333 src_idx = byte_idx;
334 goto offsets_needed;
335 }
336 }
337 else
338 memcpy (pstr->mbs + byte_idx,
339 pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
340 pstr->wcs[byte_idx++] = wcu;
341 /* Write paddings. */
342 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
343 pstr->wcs[byte_idx++] = WEOF;
344 }
345 else if (mbclen == (size_t) -1 || mbclen == 0)
346 {
347 /* It is an invalid character or '\0'. Just use the byte. */
348 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
349 pstr->mbs[byte_idx] = ch;
350 /* And also cast it to wide char. */
351 pstr->wcs[byte_idx++] = (wchar_t) ch;
352 if (BE (mbclen == (size_t) -1, 0))
353 pstr->cur_state = prev_st;
354 }
355 else
356 {
357 /* The buffer doesn't have enough space, finish to build. */
358 pstr->cur_state = prev_st;
359 break;
360 }
361 }
362 pstr->valid_len = byte_idx;
363 pstr->valid_raw_len = byte_idx;
364 return REG_NOERROR;
365 }
366 else
367 for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
368 {
369 wchar_t wc;
370 const char *p;
371 offsets_needed:
372 remain_len = end_idx - byte_idx;
373 prev_st = pstr->cur_state;
374 if (BE (pstr->trans != NULL, 0))
375 {
376 int i, ch;
377
378 for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
379 {
380 ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
381 buf[i] = pstr->trans[ch];
382 }
383 p = (const char *) buf;
384 }
385 else
386 p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
387 mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
388 if (BE (mbclen + 2 > 2, 1))
389 {
390 wchar_t wcu = wc;
391 if (iswlower (wc))
392 {
393 size_t mbcdlen;
394
395 wcu = towupper (wc);
396 mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
397 if (BE (mbclen == mbcdlen, 1))
398 memcpy (pstr->mbs + byte_idx, buf, mbclen);
399 else if (mbcdlen != (size_t) -1)
400 {
401 size_t i;
402
403 if (byte_idx + mbcdlen > pstr->bufs_len)
404 {
405 pstr->cur_state = prev_st;
406 break;
407 }
408
409 if (pstr->offsets == NULL)
410 {
411 pstr->offsets = re_malloc (int, pstr->bufs_len);
412
413 if (pstr->offsets == NULL)
414 return REG_ESPACE;
415 }
416 if (!pstr->offsets_needed)
417 {
418 for (i = 0; i < (size_t) byte_idx; ++i)
419 pstr->offsets[i] = i;
420 pstr->offsets_needed = 1;
421 }
422
423 memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
424 pstr->wcs[byte_idx] = wcu;
425 pstr->offsets[byte_idx] = src_idx;
426 for (i = 1; i < mbcdlen; ++i)
427 {
428 pstr->offsets[byte_idx + i]
429 = src_idx + (i < mbclen ? i : mbclen - 1);
430 pstr->wcs[byte_idx + i] = WEOF;
431 }
432 pstr->len += mbcdlen - mbclen;
433 if (pstr->raw_stop > src_idx)
434 pstr->stop += mbcdlen - mbclen;
435 end_idx = (pstr->bufs_len > pstr->len)
436 ? pstr->len : pstr->bufs_len;
437 byte_idx += mbcdlen;
438 src_idx += mbclen;
439 continue;
440 }
441 else
442 memcpy (pstr->mbs + byte_idx, p, mbclen);
443 }
444 else
445 memcpy (pstr->mbs + byte_idx, p, mbclen);
446
447 if (BE (pstr->offsets_needed != 0, 0))
448 {
449 size_t i;
450 for (i = 0; i < mbclen; ++i)
451 pstr->offsets[byte_idx + i] = src_idx + i;
452 }
453 src_idx += mbclen;
454
455 pstr->wcs[byte_idx++] = wcu;
456 /* Write paddings. */
457 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
458 pstr->wcs[byte_idx++] = WEOF;
459 }
460 else if (mbclen == (size_t) -1 || mbclen == 0)
461 {
462 /* It is an invalid character or '\0'. Just use the byte. */
463 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
464
465 if (BE (pstr->trans != NULL, 0))
466 ch = pstr->trans [ch];
467 pstr->mbs[byte_idx] = ch;
468
469 if (BE (pstr->offsets_needed != 0, 0))
470 pstr->offsets[byte_idx] = src_idx;
471 ++src_idx;
472
473 /* And also cast it to wide char. */
474 pstr->wcs[byte_idx++] = (wchar_t) ch;
475 if (BE (mbclen == (size_t) -1, 0))
476 pstr->cur_state = prev_st;
477 }
478 else
479 {
480 /* The buffer doesn't have enough space, finish to build. */
481 pstr->cur_state = prev_st;
482 break;
483 }
484 }
485 pstr->valid_len = byte_idx;
486 pstr->valid_raw_len = src_idx;
487 return REG_NOERROR;
488 }
489
490 /* Skip characters until the index becomes greater than NEW_RAW_IDX.
491 Return the index. */
492
493 static int
494 internal_function
495 re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
496 {
497 mbstate_t prev_st;
498 int rawbuf_idx;
499 size_t mbclen;
500 wint_t wc = WEOF;
501
502 /* Skip the characters which are not necessary to check. */
503 for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
504 rawbuf_idx < new_raw_idx;)
505 {
506 wchar_t wc2;
507 int remain_len = pstr->len - rawbuf_idx;
508 prev_st = pstr->cur_state;
509 mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
510 remain_len, &pstr->cur_state);
511 if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
512 {
513 /* We treat these cases as a single byte character. */
514 if (mbclen == 0 || remain_len == 0)
515 wc = L'\0';
516 else
517 wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
518 mbclen = 1;
519 pstr->cur_state = prev_st;
520 }
521 else
522 wc = (wint_t) wc2;
523 /* Then proceed the next character. */
524 rawbuf_idx += mbclen;
525 }
526 *last_wc = (wint_t) wc;
527 return rawbuf_idx;
528 }
529 #endif /* RE_ENABLE_I18N */
530
531 /* Build the buffer PSTR->MBS, and apply the translation if we need.
532 This function is used in case of REG_ICASE. */
533
534 static void
535 internal_function
536 build_upper_buffer (re_string_t *pstr)
537 {
538 int char_idx, end_idx;
539 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
540
541 for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
542 {
543 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
544 if (BE (pstr->trans != NULL, 0))
545 ch = pstr->trans[ch];
546 if (islower (ch))
547 pstr->mbs[char_idx] = toupper (ch);
548 else
549 pstr->mbs[char_idx] = ch;
550 }
551 pstr->valid_len = char_idx;
552 pstr->valid_raw_len = char_idx;
553 }
554
555 /* Apply TRANS to the buffer in PSTR. */
556
557 static void
558 internal_function
559 re_string_translate_buffer (re_string_t *pstr)
560 {
561 int buf_idx, end_idx;
562 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
563
564 for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
565 {
566 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
567 pstr->mbs[buf_idx] = pstr->trans[ch];
568 }
569
570 pstr->valid_len = buf_idx;
571 pstr->valid_raw_len = buf_idx;
572 }
573
574 /* This function re-construct the buffers.
575 Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
576 convert to upper case in case of REG_ICASE, apply translation. */
577
578 static reg_errcode_t
579 internal_function
580 re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
581 {
582 int offset = idx - pstr->raw_mbs_idx;
583 if (BE (offset < 0, 0))
584 {
585 /* Reset buffer. */
586 #ifdef RE_ENABLE_I18N
587 if (pstr->mb_cur_max > 1)
588 memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
589 #endif /* RE_ENABLE_I18N */
590 pstr->len = pstr->raw_len;
591 pstr->stop = pstr->raw_stop;
592 pstr->valid_len = 0;
593 pstr->raw_mbs_idx = 0;
594 pstr->valid_raw_len = 0;
595 pstr->offsets_needed = 0;
596 pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
597 : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
598 if (!pstr->mbs_allocated)
599 pstr->mbs = (unsigned char *) pstr->raw_mbs;
600 offset = idx;
601 }
602
603 if (BE (offset != 0, 1))
604 {
605 /* Should the already checked characters be kept? */
606 if (BE (offset < pstr->valid_raw_len, 1))
607 {
608 /* Yes, move them to the front of the buffer. */
609 #ifdef RE_ENABLE_I18N
610 if (BE (pstr->offsets_needed, 0))
611 {
612 int low = 0, high = pstr->valid_len, mid;
613 do
614 {
615 mid = low + (high - low) / 2;
616 if (pstr->offsets[mid] > offset)
617 high = mid;
618 else if (pstr->offsets[mid] < offset)
619 low = mid + 1;
620 else
621 break;
622 }
623 while (low < high);
624 if (pstr->offsets[mid] < offset)
625 ++mid;
626 pstr->tip_context = re_string_context_at (pstr, mid - 1,
627 eflags);
628 /* This can be quite complicated, so handle specially
629 only the common and easy case where the character with
630 different length representation of lower and upper
631 case is present at or after offset. */
632 if (pstr->valid_len > offset
633 && mid == offset && pstr->offsets[mid] == offset)
634 {
635 memmove (pstr->wcs, pstr->wcs + offset,
636 (pstr->valid_len - offset) * sizeof (wint_t));
637 memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
638 pstr->valid_len -= offset;
639 pstr->valid_raw_len -= offset;
640 for (low = 0; low < pstr->valid_len; low++)
641 pstr->offsets[low] = pstr->offsets[low + offset] - offset;
642 }
643 else
644 {
645 /* Otherwise, just find out how long the partial multibyte
646 character at offset is and fill it with WEOF/255. */
647 pstr->len = pstr->raw_len - idx + offset;
648 pstr->stop = pstr->raw_stop - idx + offset;
649 pstr->offsets_needed = 0;
650 while (mid > 0 && pstr->offsets[mid - 1] == offset)
651 --mid;
652 while (mid < pstr->valid_len)
653 if (pstr->wcs[mid] != WEOF)
654 break;
655 else
656 ++mid;
657 if (mid == pstr->valid_len)
658 pstr->valid_len = 0;
659 else
660 {
661 pstr->valid_len = pstr->offsets[mid] - offset;
662 if (pstr->valid_len)
663 {
664 for (low = 0; low < pstr->valid_len; ++low)
665 pstr->wcs[low] = WEOF;
666 memset (pstr->mbs, 255, pstr->valid_len);
667 }
668 }
669 pstr->valid_raw_len = pstr->valid_len;
670 }
671 }
672 else
673 #endif
674 {
675 pstr->tip_context = re_string_context_at (pstr, offset - 1,
676 eflags);
677 #ifdef RE_ENABLE_I18N
678 if (pstr->mb_cur_max > 1)
679 memmove (pstr->wcs, pstr->wcs + offset,
680 (pstr->valid_len - offset) * sizeof (wint_t));
681 #endif /* RE_ENABLE_I18N */
682 if (BE (pstr->mbs_allocated, 0))
683 memmove (pstr->mbs, pstr->mbs + offset,
684 pstr->valid_len - offset);
685 pstr->valid_len -= offset;
686 pstr->valid_raw_len -= offset;
687 #if DEBUG
688 assert (pstr->valid_len > 0);
689 #endif
690 }
691 }
692 else
693 {
694 #ifdef RE_ENABLE_I18N
695 /* No, skip all characters until IDX. */
696 int prev_valid_len = pstr->valid_len;
697
698 if (BE (pstr->offsets_needed, 0))
699 {
700 pstr->len = pstr->raw_len - idx + offset;
701 pstr->stop = pstr->raw_stop - idx + offset;
702 pstr->offsets_needed = 0;
703 }
704 #endif
705 pstr->valid_len = 0;
706 #ifdef RE_ENABLE_I18N
707 if (pstr->mb_cur_max > 1)
708 {
709 int wcs_idx;
710 wint_t wc = WEOF;
711
712 if (pstr->is_utf8)
713 {
714 const unsigned char *raw, *p, *end;
715
716 /* Special case UTF-8. Multi-byte chars start with any
717 byte other than 0x80 - 0xbf. */
718 raw = pstr->raw_mbs + pstr->raw_mbs_idx;
719 end = raw + (offset - pstr->mb_cur_max);
720 if (end < pstr->raw_mbs)
721 end = pstr->raw_mbs;
722 p = raw + offset - 1;
723 #ifdef _LIBC
724 /* We know the wchar_t encoding is UCS4, so for the simple
725 case, ASCII characters, skip the conversion step. */
726 if (isascii (*p) && BE (pstr->trans == NULL, 1))
727 {
728 memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
729 /* pstr->valid_len = 0; */
730 wc = (wchar_t) *p;
731 }
732 else
733 #endif
734 for (; p >= end; --p)
735 if ((*p & 0xc0) != 0x80)
736 {
737 mbstate_t cur_state;
738 wchar_t wc2;
739 int mlen = raw + pstr->len - p;
740 unsigned char buf[6];
741 size_t mbclen;
742
743 if (BE (pstr->trans != NULL, 0))
744 {
745 int i = mlen < 6 ? mlen : 6;
746 while (--i >= 0)
747 buf[i] = pstr->trans[p[i]];
748 }
749 /* XXX Don't use mbrtowc, we know which conversion
750 to use (UTF-8 -> UCS4). */
751 memset (&cur_state, 0, sizeof (cur_state));
752 mbclen = __mbrtowc (&wc2, (const char *) p, mlen,
753 &cur_state);
754 if (raw + offset - p <= mbclen
755 && mbclen < (size_t) -2)
756 {
757 memset (&pstr->cur_state, '\0',
758 sizeof (mbstate_t));
759 pstr->valid_len = mbclen - (raw + offset - p);
760 wc = wc2;
761 }
762 break;
763 }
764 }
765
766 if (wc == WEOF)
767 pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
768 if (wc == WEOF)
769 pstr->tip_context
770 = re_string_context_at (pstr, prev_valid_len - 1, eflags);
771 else
772 pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
773 && IS_WIDE_WORD_CHAR (wc))
774 ? CONTEXT_WORD
775 : ((IS_WIDE_NEWLINE (wc)
776 && pstr->newline_anchor)
777 ? CONTEXT_NEWLINE : 0));
778 if (BE (pstr->valid_len, 0))
779 {
780 for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
781 pstr->wcs[wcs_idx] = WEOF;
782 if (pstr->mbs_allocated)
783 memset (pstr->mbs, 255, pstr->valid_len);
784 }
785 pstr->valid_raw_len = pstr->valid_len;
786 }
787 else
788 #endif /* RE_ENABLE_I18N */
789 {
790 int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
791 pstr->valid_raw_len = 0;
792 if (pstr->trans)
793 c = pstr->trans[c];
794 pstr->tip_context = (bitset_contain (pstr->word_char, c)
795 ? CONTEXT_WORD
796 : ((IS_NEWLINE (c) && pstr->newline_anchor)
797 ? CONTEXT_NEWLINE : 0));
798 }
799 }
800 if (!BE (pstr->mbs_allocated, 0))
801 pstr->mbs += offset;
802 }
803 pstr->raw_mbs_idx = idx;
804 pstr->len -= offset;
805 pstr->stop -= offset;
806
807 /* Then build the buffers. */
808 #ifdef RE_ENABLE_I18N
809 if (pstr->mb_cur_max > 1)
810 {
811 if (pstr->icase)
812 {
813 reg_errcode_t ret = build_wcs_upper_buffer (pstr);
814 if (BE (ret != REG_NOERROR, 0))
815 return ret;
816 }
817 else
818 build_wcs_buffer (pstr);
819 }
820 else
821 #endif /* RE_ENABLE_I18N */
822 if (BE (pstr->mbs_allocated, 0))
823 {
824 if (pstr->icase)
825 build_upper_buffer (pstr);
826 else if (pstr->trans != NULL)
827 re_string_translate_buffer (pstr);
828 }
829 else
830 pstr->valid_len = pstr->len;
831
832 pstr->cur_idx = 0;
833 return REG_NOERROR;
834 }
835
836 static unsigned char
837 internal_function __attribute ((pure))
838 re_string_peek_byte_case (const re_string_t *pstr, int idx)
839 {
840 int ch, off;
841
842 /* Handle the common (easiest) cases first. */
843 if (BE (!pstr->mbs_allocated, 1))
844 return re_string_peek_byte (pstr, idx);
845
846 #ifdef RE_ENABLE_I18N
847 if (pstr->mb_cur_max > 1
848 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
849 return re_string_peek_byte (pstr, idx);
850 #endif
851
852 off = pstr->cur_idx + idx;
853 #ifdef RE_ENABLE_I18N
854 if (pstr->offsets_needed)
855 off = pstr->offsets[off];
856 #endif
857
858 ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
859
860 #ifdef RE_ENABLE_I18N
861 /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
862 this function returns CAPITAL LETTER I instead of first byte of
863 DOTLESS SMALL LETTER I. The latter would confuse the parser,
864 since peek_byte_case doesn't advance cur_idx in any way. */
865 if (pstr->offsets_needed && !isascii (ch))
866 return re_string_peek_byte (pstr, idx);
867 #endif
868
869 return ch;
870 }
871
872 static unsigned char
873 internal_function __attribute ((pure))
874 re_string_fetch_byte_case (re_string_t *pstr)
875 {
876 if (BE (!pstr->mbs_allocated, 1))
877 return re_string_fetch_byte (pstr);
878
879 #ifdef RE_ENABLE_I18N
880 if (pstr->offsets_needed)
881 {
882 int off, ch;
883
884 /* For tr_TR.UTF-8 [[:islower:]] there is
885 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip
886 in that case the whole multi-byte character and return
887 the original letter. On the other side, with
888 [[: DOTLESS SMALL LETTER I return [[:I, as doing
889 anything else would complicate things too much. */
890
891 if (!re_string_first_byte (pstr, pstr->cur_idx))
892 return re_string_fetch_byte (pstr);
893
894 off = pstr->offsets[pstr->cur_idx];
895 ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
896
897 if (! isascii (ch))
898 return re_string_fetch_byte (pstr);
899
900 re_string_skip_bytes (pstr,
901 re_string_char_size_at (pstr, pstr->cur_idx));
902 return ch;
903 }
904 #endif
905
906 return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
907 }
908
909 static void
910 internal_function
911 re_string_destruct (re_string_t *pstr)
912 {
913 #ifdef RE_ENABLE_I18N
914 re_free (pstr->wcs);
915 re_free (pstr->offsets);
916 #endif /* RE_ENABLE_I18N */
917 if (pstr->mbs_allocated)
918 re_free (pstr->mbs);
919 }
920
921 /* Return the context at IDX in INPUT. */
922
923 static unsigned int
924 internal_function
925 re_string_context_at (const re_string_t *input, int idx, int eflags)
926 {
927 int c;
928 if (BE (idx < 0, 0))
929 /* In this case, we use the value stored in input->tip_context,
930 since we can't know the character in input->mbs[-1] here. */
931 return input->tip_context;
932 if (BE (idx == input->len, 0))
933 return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
934 : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
935 #ifdef RE_ENABLE_I18N
936 if (input->mb_cur_max > 1)
937 {
938 wint_t wc;
939 int wc_idx = idx;
940 while(input->wcs[wc_idx] == WEOF)
941 {
942 #ifdef DEBUG
943 /* It must not happen. */
944 assert (wc_idx >= 0);
945 #endif
946 --wc_idx;
947 if (wc_idx < 0)
948 return input->tip_context;
949 }
950 wc = input->wcs[wc_idx];
951 if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
952 return CONTEXT_WORD;
953 return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
954 ? CONTEXT_NEWLINE : 0);
955 }
956 else
957 #endif
958 {
959 c = re_string_byte_at (input, idx);
960 if (bitset_contain (input->word_char, c))
961 return CONTEXT_WORD;
962 return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
963 }
964 }
965
966 /* Functions for set operation. */
967
968 static reg_errcode_t
969 internal_function
970 re_node_set_alloc (re_node_set *set, int size)
971 {
972 /*
973 * ADR: valgrind says size can be 0, which then doesn't
974 * free the block of size 0. Harumph. This seems
975 * to work ok, though.
976 */
977 if (size == 0)
978 {
979 memset(set, 0, sizeof(*set));
980 return REG_NOERROR;
981 }
982 set->alloc = size;
983 set->nelem = 0;
984 set->elems = re_malloc (int, size);
985 if (BE (set->elems == NULL, 0))
986 return REG_ESPACE;
987 return REG_NOERROR;
988 }
989
990 static reg_errcode_t
991 internal_function
992 re_node_set_init_1 (re_node_set *set, int elem)
993 {
994 set->alloc = 1;
995 set->nelem = 1;
996 set->elems = re_malloc (int, 1);
997 if (BE (set->elems == NULL, 0))
998 {
999 set->alloc = set->nelem = 0;
1000 return REG_ESPACE;
1001 }
1002 set->elems[0] = elem;
1003 return REG_NOERROR;
1004 }
1005
1006 static reg_errcode_t
1007 internal_function
1008 re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
1009 {
1010 set->alloc = 2;
1011 set->elems = re_malloc (int, 2);
1012 if (BE (set->elems == NULL, 0))
1013 return REG_ESPACE;
1014 if (elem1 == elem2)
1015 {
1016 set->nelem = 1;
1017 set->elems[0] = elem1;
1018 }
1019 else
1020 {
1021 set->nelem = 2;
1022 if (elem1 < elem2)
1023 {
1024 set->elems[0] = elem1;
1025 set->elems[1] = elem2;
1026 }
1027 else
1028 {
1029 set->elems[0] = elem2;
1030 set->elems[1] = elem1;
1031 }
1032 }
1033 return REG_NOERROR;
1034 }
1035
1036 static reg_errcode_t
1037 internal_function
1038 re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
1039 {
1040 dest->nelem = src->nelem;
1041 if (src->nelem > 0)
1042 {
1043 dest->alloc = dest->nelem;
1044 dest->elems = re_malloc (int, dest->alloc);
1045 if (BE (dest->elems == NULL, 0))
1046 {
1047 dest->alloc = dest->nelem = 0;
1048 return REG_ESPACE;
1049 }
1050 memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
1051 }
1052 else
1053 re_node_set_init_empty (dest);
1054 return REG_NOERROR;
1055 }
1056
1057 /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
1058 DEST. Return value indicate the error code or REG_NOERROR if succeeded.
1059 Note: We assume dest->elems is NULL, when dest->alloc is 0. */
1060
1061 static reg_errcode_t
1062 internal_function
1063 re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
1064 const re_node_set *src2)
1065 {
1066 int i1, i2, is, id, delta, sbase;
1067 if (src1->nelem == 0 || src2->nelem == 0)
1068 return REG_NOERROR;
1069
1070 /* We need dest->nelem + 2 * elems_in_intersection; this is a
1071 conservative estimate. */
1072 if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
1073 {
1074 int new_alloc = src1->nelem + src2->nelem + dest->alloc;
1075 int *new_elems = re_realloc (dest->elems, int, new_alloc);
1076 if (BE (new_elems == NULL, 0))
1077 return REG_ESPACE;
1078 dest->elems = new_elems;
1079 dest->alloc = new_alloc;
1080 }
1081
1082 /* Find the items in the intersection of SRC1 and SRC2, and copy
1083 into the top of DEST those that are not already in DEST itself. */
1084 sbase = dest->nelem + src1->nelem + src2->nelem;
1085 i1 = src1->nelem - 1;
1086 i2 = src2->nelem - 1;
1087 id = dest->nelem - 1;
1088 for (;;)
1089 {
1090 if (src1->elems[i1] == src2->elems[i2])
1091 {
1092 /* Try to find the item in DEST. Maybe we could binary search? */
1093 while (id >= 0 && dest->elems[id] > src1->elems[i1])
1094 --id;
1095
1096 if (id < 0 || dest->elems[id] != src1->elems[i1])
1097 dest->elems[--sbase] = src1->elems[i1];
1098
1099 if (--i1 < 0 || --i2 < 0)
1100 break;
1101 }
1102
1103 /* Lower the highest of the two items. */
1104 else if (src1->elems[i1] < src2->elems[i2])
1105 {
1106 if (--i2 < 0)
1107 break;
1108 }
1109 else
1110 {
1111 if (--i1 < 0)
1112 break;
1113 }
1114 }
1115
1116 id = dest->nelem - 1;
1117 is = dest->nelem + src1->nelem + src2->nelem - 1;
1118 delta = is - sbase + 1;
1119
1120 /* Now copy. When DELTA becomes zero, the remaining
1121 DEST elements are already in place; this is more or
1122 less the same loop that is in re_node_set_merge. */
1123 dest->nelem += delta;
1124 if (delta > 0 && id >= 0)
1125 for (;;)
1126 {
1127 if (dest->elems[is] > dest->elems[id])
1128 {
1129 /* Copy from the top. */
1130 dest->elems[id + delta--] = dest->elems[is--];
1131 if (delta == 0)
1132 break;
1133 }
1134 else
1135 {
1136 /* Slide from the bottom. */
1137 dest->elems[id + delta] = dest->elems[id];
1138 if (--id < 0)
1139 break;
1140 }
1141 }
1142
1143 /* Copy remaining SRC elements. */
1144 memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
1145
1146 return REG_NOERROR;
1147 }
1148
1149 /* Calculate the union set of the sets SRC1 and SRC2. And store it to
1150 DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
1151
1152 static reg_errcode_t
1153 internal_function
1154 re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
1155 const re_node_set *src2)
1156 {
1157 int i1, i2, id;
1158 if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
1159 {
1160 dest->alloc = src1->nelem + src2->nelem;
1161 dest->elems = re_malloc (int, dest->alloc);
1162 if (BE (dest->elems == NULL, 0))
1163 return REG_ESPACE;
1164 }
1165 else
1166 {
1167 if (src1 != NULL && src1->nelem > 0)
1168 return re_node_set_init_copy (dest, src1);
1169 else if (src2 != NULL && src2->nelem > 0)
1170 return re_node_set_init_copy (dest, src2);
1171 else
1172 re_node_set_init_empty (dest);
1173 return REG_NOERROR;
1174 }
1175 for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
1176 {
1177 if (src1->elems[i1] > src2->elems[i2])
1178 {
1179 dest->elems[id++] = src2->elems[i2++];
1180 continue;
1181 }
1182 if (src1->elems[i1] == src2->elems[i2])
1183 ++i2;
1184 dest->elems[id++] = src1->elems[i1++];
1185 }
1186 if (i1 < src1->nelem)
1187 {
1188 memcpy (dest->elems + id, src1->elems + i1,
1189 (src1->nelem - i1) * sizeof (int));
1190 id += src1->nelem - i1;
1191 }
1192 else if (i2 < src2->nelem)
1193 {
1194 memcpy (dest->elems + id, src2->elems + i2,
1195 (src2->nelem - i2) * sizeof (int));
1196 id += src2->nelem - i2;
1197 }
1198 dest->nelem = id;
1199 return REG_NOERROR;
1200 }
1201
1202 /* Calculate the union set of the sets DEST and SRC. And store it to
1203 DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
1204
1205 static reg_errcode_t
1206 internal_function
1207 re_node_set_merge (re_node_set *dest, const re_node_set *src)
1208 {
1209 int is, id, sbase, delta;
1210 if (src == NULL || src->nelem == 0)
1211 return REG_NOERROR;
1212 if (dest->alloc < 2 * src->nelem + dest->nelem)
1213 {
1214 int new_alloc = 2 * (src->nelem + dest->alloc);
1215 int *new_buffer = re_realloc (dest->elems, int, new_alloc);
1216 if (BE (new_buffer == NULL, 0))
1217 return REG_ESPACE;
1218 dest->elems = new_buffer;
1219 dest->alloc = new_alloc;
1220 }
1221
1222 if (BE (dest->nelem == 0, 0))
1223 {
1224 dest->nelem = src->nelem;
1225 memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
1226 return REG_NOERROR;
1227 }
1228
1229 /* Copy into the top of DEST the items of SRC that are not
1230 found in DEST. Maybe we could binary search in DEST? */
1231 for (sbase = dest->nelem + 2 * src->nelem,
1232 is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
1233 {
1234 if (dest->elems[id] == src->elems[is])
1235 {
1236 is--;
1237 id--;
1238 }
1239 else if (dest->elems[id] < src->elems[is])
1240 dest->elems[--sbase] = src->elems[is--];
1241 else /* if (dest->elems[id] > src->elems[is]) */
1242 --id;
1243 }
1244
1245 if (is >= 0)
1246 {
1247 /* If DEST is exhausted, the remaining items of SRC must be unique. */
1248 sbase -= is + 1;
1249 memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
1250 }
1251
1252 id = dest->nelem - 1;
1253 is = dest->nelem + 2 * src->nelem - 1;
1254 delta = is - sbase + 1;
1255 if (delta == 0)
1256 return REG_NOERROR;
1257
1258 /* Now copy. When DELTA becomes zero, the remaining
1259 DEST elements are already in place. */
1260 dest->nelem += delta;
1261 for (;;)
1262 {
1263 if (dest->elems[is] > dest->elems[id])
1264 {
1265 /* Copy from the top. */
1266 dest->elems[id + delta--] = dest->elems[is--];
1267 if (delta == 0)
1268 break;
1269 }
1270 else
1271 {
1272 /* Slide from the bottom. */
1273 dest->elems[id + delta] = dest->elems[id];
1274 if (--id < 0)
1275 {
1276 /* Copy remaining SRC elements. */
1277 memcpy (dest->elems, dest->elems + sbase,
1278 delta * sizeof (int));
1279 break;
1280 }
1281 }
1282 }
1283
1284 return REG_NOERROR;
1285 }
1286
1287 /* Insert the new element ELEM to the re_node_set* SET.
1288 SET should not already have ELEM.
1289 return -1 if an error has occurred, return 1 otherwise. */
1290
1291 static int
1292 internal_function
1293 re_node_set_insert (re_node_set *set, int elem)
1294 {
1295 int idx;
1296 /* In case the set is empty. */
1297 if (set->alloc == 0)
1298 {
1299 if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
1300 return 1;
1301 else
1302 return -1;
1303 }
1304
1305 if (BE (set->nelem, 0) == 0)
1306 {
1307 /* We already guaranteed above that set->alloc != 0. */
1308 set->elems[0] = elem;
1309 ++set->nelem;
1310 return 1;
1311 }
1312
1313 /* Realloc if we need. */
1314 if (set->alloc == set->nelem)
1315 {
1316 int *new_elems;
1317 set->alloc = set->alloc * 2;
1318 new_elems = re_realloc (set->elems, int, set->alloc);
1319 if (BE (new_elems == NULL, 0))
1320 return -1;
1321 set->elems = new_elems;
1322 }
1323
1324 /* Move the elements which follows the new element. Test the
1325 first element separately to skip a check in the inner loop. */
1326 if (elem < set->elems[0])
1327 {
1328 idx = 0;
1329 for (idx = set->nelem; idx > 0; idx--)
1330 set->elems[idx] = set->elems[idx - 1];
1331 }
1332 else
1333 {
1334 for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
1335 set->elems[idx] = set->elems[idx - 1];
1336 }
1337
1338 /* Insert the new element. */
1339 set->elems[idx] = elem;
1340 ++set->nelem;
1341 return 1;
1342 }
1343
1344 /* Insert the new element ELEM to the re_node_set* SET.
1345 SET should not already have any element greater than or equal to ELEM.
1346 Return -1 if an error has occurred, return 1 otherwise. */
1347
1348 static int
1349 internal_function
1350 re_node_set_insert_last (re_node_set *set, int elem)
1351 {
1352 /* Realloc if we need. */
1353 if (set->alloc == set->nelem)
1354 {
1355 int *new_elems;
1356 set->alloc = (set->alloc + 1) * 2;
1357 new_elems = re_realloc (set->elems, int, set->alloc);
1358 if (BE (new_elems == NULL, 0))
1359 return -1;
1360 set->elems = new_elems;
1361 }
1362
1363 /* Insert the new element. */
1364 set->elems[set->nelem++] = elem;
1365 return 1;
1366 }
1367
1368 /* Compare two node sets SET1 and SET2.
1369 return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */
1370
1371 static int
1372 internal_function __attribute ((pure))
1373 re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
1374 {
1375 int i;
1376 if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
1377 return 0;
1378 for (i = set1->nelem ; --i >= 0 ; )
1379 if (set1->elems[i] != set2->elems[i])
1380 return 0;
1381 return 1;
1382 }
1383
1384 /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
1385
1386 static int
1387 internal_function __attribute ((pure))
1388 re_node_set_contains (const re_node_set *set, int elem)
1389 {
1390 unsigned int idx, right, mid;
1391 if (set->nelem <= 0)
1392 return 0;
1393
1394 /* Binary search the element. */
1395 idx = 0;
1396 right = set->nelem - 1;
1397 while (idx < right)
1398 {
1399 mid = idx + (right - idx) / 2;
1400 if (set->elems[mid] < elem)
1401 idx = mid + 1;
1402 else
1403 right = mid;
1404 }
1405 return set->elems[idx] == elem ? idx + 1 : 0;
1406 }
1407
1408 static void
1409 internal_function
1410 re_node_set_remove_at (re_node_set *set, int idx)
1411 {
1412 if (idx < 0 || idx >= set->nelem)
1413 return;
1414 --set->nelem;
1415 for (; idx < set->nelem; idx++)
1416 set->elems[idx] = set->elems[idx + 1];
1417 }
1418
1419
1420 /* Add the token TOKEN to dfa->nodes, and return the index of the token.
1421 Or return -1, if an error has occurred. */
1422
1423 static int
1424 internal_function
1425 re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
1426 {
1427 if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
1428 {
1429 size_t new_nodes_alloc = dfa->nodes_alloc * 2;
1430 int *new_nexts, *new_indices;
1431 re_node_set *new_edests, *new_eclosures;
1432 re_token_t *new_nodes;
1433
1434 /* Avoid overflows in realloc. */
1435 const size_t max_object_size = MAX (sizeof (re_token_t),
1436 MAX (sizeof (re_node_set),
1437 sizeof (int)));
1438 if (BE (SIZE_MAX / max_object_size < new_nodes_alloc, 0))
1439 return -1;
1440
1441 new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
1442 if (BE (new_nodes == NULL, 0))
1443 return -1;
1444 dfa->nodes = new_nodes;
1445 new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
1446 new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
1447 new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
1448 new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
1449 if (BE (new_nexts == NULL || new_indices == NULL
1450 || new_edests == NULL || new_eclosures == NULL, 0))
1451 return -1;
1452 dfa->nexts = new_nexts;
1453 dfa->org_indices = new_indices;
1454 dfa->edests = new_edests;
1455 dfa->eclosures = new_eclosures;
1456 dfa->nodes_alloc = new_nodes_alloc;
1457 }
1458 dfa->nodes[dfa->nodes_len] = token;
1459 dfa->nodes[dfa->nodes_len].constraint = 0;
1460 #ifdef RE_ENABLE_I18N
1461 dfa->nodes[dfa->nodes_len].accept_mb =
1462 (token.type == OP_PERIOD && dfa->mb_cur_max > 1) || token.type == COMPLEX_BRACKET;
1463 #endif
1464 dfa->nexts[dfa->nodes_len] = -1;
1465 re_node_set_init_empty (dfa->edests + dfa->nodes_len);
1466 re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
1467 return dfa->nodes_len++;
1468 }
1469
1470 static inline unsigned int
1471 internal_function
1472 calc_state_hash (const re_node_set *nodes, unsigned int context)
1473 {
1474 unsigned int hash = nodes->nelem + context;
1475 int i;
1476 for (i = 0 ; i < nodes->nelem ; i++)
1477 hash += nodes->elems[i];
1478 return hash;
1479 }
1480
1481 /* Search for the state whose node_set is equivalent to NODES.
1482 Return the pointer to the state, if we found it in the DFA.
1483 Otherwise create the new one and return it. In case of an error
1484 return NULL and set the error code in ERR.
1485 Note: - We assume NULL as the invalid state, then it is possible that
1486 return value is NULL and ERR is REG_NOERROR.
1487 - We never return non-NULL value in case of any errors, it is for
1488 optimization. */
1489
1490 static re_dfastate_t *
1491 internal_function
1492 re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
1493 const re_node_set *nodes)
1494 {
1495 unsigned int hash;
1496 re_dfastate_t *new_state;
1497 struct re_state_table_entry *spot;
1498 int i;
1499 if (BE (nodes->nelem == 0, 0))
1500 {
1501 *err = REG_NOERROR;
1502 return NULL;
1503 }
1504 hash = calc_state_hash (nodes, 0);
1505 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1506
1507 for (i = 0 ; i < spot->num ; i++)
1508 {
1509 re_dfastate_t *state = spot->array[i];
1510 if (hash != state->hash)
1511 continue;
1512 if (re_node_set_compare (&state->nodes, nodes))
1513 return state;
1514 }
1515
1516 /* There are no appropriate state in the dfa, create the new one. */
1517 new_state = create_ci_newstate (dfa, nodes, hash);
1518 if (BE (new_state == NULL, 0))
1519 *err = REG_ESPACE;
1520
1521 return new_state;
1522 }
1523
1524 /* Search for the state whose node_set is equivalent to NODES and
1525 whose context is equivalent to CONTEXT.
1526 Return the pointer to the state, if we found it in the DFA.
1527 Otherwise create the new one and return it. In case of an error
1528 return NULL and set the error code in ERR.
1529 Note: - We assume NULL as the invalid state, then it is possible that
1530 return value is NULL and ERR is REG_NOERROR.
1531 - We never return non-NULL value in case of any errors, it is for
1532 optimization. */
1533
1534 static re_dfastate_t *
1535 internal_function
1536 re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
1537 const re_node_set *nodes, unsigned int context)
1538 {
1539 unsigned int hash;
1540 re_dfastate_t *new_state;
1541 struct re_state_table_entry *spot;
1542 int i;
1543 if (nodes->nelem == 0)
1544 {
1545 *err = REG_NOERROR;
1546 return NULL;
1547 }
1548 hash = calc_state_hash (nodes, context);
1549 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1550
1551 for (i = 0 ; i < spot->num ; i++)
1552 {
1553 re_dfastate_t *state = spot->array[i];
1554 if (state->hash == hash
1555 && state->context == context
1556 && re_node_set_compare (state->entrance_nodes, nodes))
1557 return state;
1558 }
1559 /* There are no appropriate state in `dfa', create the new one. */
1560 new_state = create_cd_newstate (dfa, nodes, context, hash);
1561 if (BE (new_state == NULL, 0))
1562 *err = REG_ESPACE;
1563
1564 return new_state;
1565 }
1566
1567 /* Finish initialization of the new state NEWSTATE, and using its hash value
1568 HASH put in the appropriate bucket of DFA's state table. Return value
1569 indicates the error code if failed. */
1570
1571 static reg_errcode_t
1572 register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
1573 unsigned int hash)
1574 {
1575 struct re_state_table_entry *spot;
1576 reg_errcode_t err;
1577 int i;
1578
1579 newstate->hash = hash;
1580 err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
1581 if (BE (err != REG_NOERROR, 0))
1582 return REG_ESPACE;
1583 for (i = 0; i < newstate->nodes.nelem; i++)
1584 {
1585 int elem = newstate->nodes.elems[i];
1586 if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
1587 if (re_node_set_insert_last (&newstate->non_eps_nodes, elem) < 0)
1588 return REG_ESPACE;
1589 }
1590
1591 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1592 if (BE (spot->alloc <= spot->num, 0))
1593 {
1594 int new_alloc = 2 * spot->num + 2;
1595 re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
1596 new_alloc);
1597 if (BE (new_array == NULL, 0))
1598 return REG_ESPACE;
1599 spot->array = new_array;
1600 spot->alloc = new_alloc;
1601 }
1602 spot->array[spot->num++] = newstate;
1603 return REG_NOERROR;
1604 }
1605
1606 static void
1607 free_state (re_dfastate_t *state)
1608 {
1609 re_node_set_free (&state->non_eps_nodes);
1610 re_node_set_free (&state->inveclosure);
1611 if (state->entrance_nodes != &state->nodes)
1612 {
1613 re_node_set_free (state->entrance_nodes);
1614 re_free (state->entrance_nodes);
1615 }
1616 re_node_set_free (&state->nodes);
1617 re_free (state->word_trtable);
1618 re_free (state->trtable);
1619 re_free (state);
1620 }
1621
1622 /* Create the new state which is independent of contexts.
1623 Return the new state if succeeded, otherwise return NULL. */
1624
1625 static re_dfastate_t *
1626 internal_function
1627 create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
1628 unsigned int hash)
1629 {
1630 int i;
1631 reg_errcode_t err;
1632 re_dfastate_t *newstate;
1633
1634 newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
1635 if (BE (newstate == NULL, 0))
1636 return NULL;
1637 err = re_node_set_init_copy (&newstate->nodes, nodes);
1638 if (BE (err != REG_NOERROR, 0))
1639 {
1640 re_free (newstate);
1641 return NULL;
1642 }
1643
1644 newstate->entrance_nodes = &newstate->nodes;
1645 for (i = 0 ; i < nodes->nelem ; i++)
1646 {
1647 re_token_t *node = dfa->nodes + nodes->elems[i];
1648 re_token_type_t type = node->type;
1649 if (type == CHARACTER && !node->constraint)
1650 continue;
1651 #ifdef RE_ENABLE_I18N
1652 newstate->accept_mb |= node->accept_mb;
1653 #endif /* RE_ENABLE_I18N */
1654
1655 /* If the state has the halt node, the state is a halt state. */
1656 if (type == END_OF_RE)
1657 newstate->halt = 1;
1658 else if (type == OP_BACK_REF)
1659 newstate->has_backref = 1;
1660 else if (type == ANCHOR || node->constraint)
1661 newstate->has_constraint = 1;
1662 }
1663 err = register_state (dfa, newstate, hash);
1664 if (BE (err != REG_NOERROR, 0))
1665 {
1666 free_state (newstate);
1667 newstate = NULL;
1668 }
1669 return newstate;
1670 }
1671
1672 /* Create the new state which is depend on the context CONTEXT.
1673 Return the new state if succeeded, otherwise return NULL. */
1674
1675 static re_dfastate_t *
1676 internal_function
1677 create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
1678 unsigned int context, unsigned int hash)
1679 {
1680 int i, nctx_nodes = 0;
1681 reg_errcode_t err;
1682 re_dfastate_t *newstate;
1683
1684 newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
1685 if (BE (newstate == NULL, 0))
1686 return NULL;
1687 err = re_node_set_init_copy (&newstate->nodes, nodes);
1688 if (BE (err != REG_NOERROR, 0))
1689 {
1690 re_free (newstate);
1691 return NULL;
1692 }
1693
1694 newstate->context = context;
1695 newstate->entrance_nodes = &newstate->nodes;
1696
1697 for (i = 0 ; i < nodes->nelem ; i++)
1698 {
1699 re_token_t *node = dfa->nodes + nodes->elems[i];
1700 re_token_type_t type = node->type;
1701 unsigned int constraint = node->constraint;
1702
1703 if (type == CHARACTER && !constraint)
1704 continue;
1705 #ifdef RE_ENABLE_I18N
1706 newstate->accept_mb |= node->accept_mb;
1707 #endif /* RE_ENABLE_I18N */
1708
1709 /* If the state has the halt node, the state is a halt state. */
1710 if (type == END_OF_RE)
1711 newstate->halt = 1;
1712 else if (type == OP_BACK_REF)
1713 newstate->has_backref = 1;
1714
1715 if (constraint)
1716 {
1717 if (newstate->entrance_nodes == &newstate->nodes)
1718 {
1719 newstate->entrance_nodes = re_malloc (re_node_set, 1);
1720 if (BE (newstate->entrance_nodes == NULL, 0))
1721 {
1722 free_state (newstate);
1723 return NULL;
1724 }
1725 if (re_node_set_init_copy (newstate->entrance_nodes, nodes)
1726 != REG_NOERROR)
1727 return NULL;
1728 nctx_nodes = 0;
1729 newstate->has_constraint = 1;
1730 }
1731
1732 if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
1733 {
1734 re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
1735 ++nctx_nodes;
1736 }
1737 }
1738 }
1739 err = register_state (dfa, newstate, hash);
1740 if (BE (err != REG_NOERROR, 0))
1741 {
1742 free_state (newstate);
1743 newstate = NULL;
1744 }
1745 return newstate;
1746 }