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