Annotation of embedaddon/smartmontools/regex/regex_internal.c, revision 1.1

1.1     ! misho       1: /* Extended regular expression matching and search library.
        !             2:    Copyright (C) 2002, 2003 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, write to the Free
        !            18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
        !            19:    02111-1307 USA.  */
        !            20: 
        !            21: static void re_string_construct_common (const char *str, int len,
        !            22:                                        re_string_t *pstr,
        !            23:                                        RE_TRANSLATE_TYPE trans, int icase);
        !            24: #ifdef RE_ENABLE_I18N
        !            25: static int re_string_skip_chars (re_string_t *pstr, int new_raw_idx,
        !            26:                                 wint_t *last_wc);
        !            27: #endif /* RE_ENABLE_I18N */
        !            28: static re_dfastate_t *create_newstate_common (re_dfa_t *dfa,
        !            29:                                              const re_node_set *nodes,
        !            30:                                              unsigned int hash);
        !            31: static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate,
        !            32:                                     unsigned int hash);
        !            33: static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa,
        !            34:                                          const re_node_set *nodes,
        !            35:                                          unsigned int hash);
        !            36: static re_dfastate_t *create_cd_newstate (re_dfa_t *dfa,
        !            37:                                          const re_node_set *nodes,
        !            38:                                          unsigned int context,
        !            39:                                          unsigned int hash);
        !            40: static unsigned int inline calc_state_hash (const re_node_set *nodes,
        !            41:                                            unsigned int context);
        !            42: 
        !            43: /* Functions for string operation.  */
        !            44: 
        !            45: /* This function allocate the buffers.  It is necessary to call
        !            46:    re_string_reconstruct before using the object.  */
        !            47: 
        !            48: static reg_errcode_t
        !            49: re_string_allocate (pstr, str, len, init_len, trans, icase)
        !            50:      re_string_t *pstr;
        !            51:      const char *str;
        !            52:      int len, init_len, icase;
        !            53:      RE_TRANSLATE_TYPE trans;
        !            54: {
        !            55:   reg_errcode_t ret;
        !            56:   int init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
        !            57:   re_string_construct_common (str, len, pstr, trans, icase);
        !            58:   pstr->stop = pstr->len;
        !            59: 
        !            60:   ret = re_string_realloc_buffers (pstr, init_buf_len);
        !            61:   if (BE (ret != REG_NOERROR, 0))
        !            62:     return ret;
        !            63: 
        !            64:   pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
        !            65:                    : (unsigned char *) str);
        !            66:   pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
        !            67:   pstr->valid_len = (MBS_CASE_ALLOCATED (pstr) || MBS_ALLOCATED (pstr)
        !            68:                     || MB_CUR_MAX > 1) ? pstr->valid_len : len;
        !            69:   return REG_NOERROR;
        !            70: }
        !            71: 
        !            72: /* This function allocate the buffers, and initialize them.  */
        !            73: 
        !            74: static reg_errcode_t
        !            75: re_string_construct (pstr, str, len, trans, icase)
        !            76:      re_string_t *pstr;
        !            77:      const char *str;
        !            78:      int len, icase;
        !            79:      RE_TRANSLATE_TYPE trans;
        !            80: {
        !            81:   reg_errcode_t ret;
        !            82:   re_string_construct_common (str, len, pstr, trans, icase);
        !            83:   pstr->stop = pstr->len;
        !            84:   /* Set 0 so that this function can initialize whole buffers.  */
        !            85:   pstr->valid_len = 0;
        !            86: 
        !            87:   if (len > 0)
        !            88:     {
        !            89:       ret = re_string_realloc_buffers (pstr, len + 1);
        !            90:       if (BE (ret != REG_NOERROR, 0))
        !            91:        return ret;
        !            92:     }
        !            93:   pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
        !            94:                    : (unsigned char *) str);
        !            95:   pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
        !            96: 
        !            97:   if (icase)
        !            98:     {
        !            99: #ifdef RE_ENABLE_I18N
        !           100:       if (MB_CUR_MAX > 1)
        !           101:        build_wcs_upper_buffer (pstr);
        !           102:       else
        !           103: #endif /* RE_ENABLE_I18N  */
        !           104:        build_upper_buffer (pstr);
        !           105:     }
        !           106:   else
        !           107:     {
        !           108: #ifdef RE_ENABLE_I18N
        !           109:       if (MB_CUR_MAX > 1)
        !           110:        build_wcs_buffer (pstr);
        !           111:       else
        !           112: #endif /* RE_ENABLE_I18N  */
        !           113:        {
        !           114:          if (trans != NULL)
        !           115:            re_string_translate_buffer (pstr);
        !           116:          else
        !           117:            pstr->valid_len = len;
        !           118:        }
        !           119:     }
        !           120: 
        !           121:   /* Initialized whole buffers, then valid_len == bufs_len.  */
        !           122:   pstr->valid_len = pstr->bufs_len;
        !           123:   return REG_NOERROR;
        !           124: }
        !           125: 
        !           126: /* Helper functions for re_string_allocate, and re_string_construct.  */
        !           127: 
        !           128: static reg_errcode_t
        !           129: re_string_realloc_buffers (pstr, new_buf_len)
        !           130:      re_string_t *pstr;
        !           131:      int new_buf_len;
        !           132: {
        !           133: #ifdef RE_ENABLE_I18N
        !           134:   if (MB_CUR_MAX > 1)
        !           135:     {
        !           136:       wint_t *new_array = re_realloc (pstr->wcs, wint_t, new_buf_len);
        !           137:       if (BE (new_array == NULL, 0))
        !           138:        return REG_ESPACE;
        !           139:       pstr->wcs = new_array;
        !           140:     }
        !           141: #endif /* RE_ENABLE_I18N  */
        !           142:   if (MBS_ALLOCATED (pstr))
        !           143:     {
        !           144:       unsigned char *new_array = re_realloc (pstr->mbs, unsigned char,
        !           145:                                             new_buf_len);
        !           146:       if (BE (new_array == NULL, 0))
        !           147:        return REG_ESPACE;
        !           148:       pstr->mbs = new_array;
        !           149:     }
        !           150:   if (MBS_CASE_ALLOCATED (pstr))
        !           151:     {
        !           152:       unsigned char *new_array = re_realloc (pstr->mbs_case, unsigned char,
        !           153:                                             new_buf_len);
        !           154:       if (BE (new_array == NULL, 0))
        !           155:        return REG_ESPACE;
        !           156:       pstr->mbs_case = new_array;
        !           157:       if (!MBS_ALLOCATED (pstr))
        !           158:        pstr->mbs = pstr->mbs_case;
        !           159:     }
        !           160:   pstr->bufs_len = new_buf_len;
        !           161:   return REG_NOERROR;
        !           162: }
        !           163: 
        !           164: 
        !           165: static void
        !           166: re_string_construct_common (str, len, pstr, trans, icase)
        !           167:      const char *str;
        !           168:      int len;
        !           169:      re_string_t *pstr;
        !           170:      RE_TRANSLATE_TYPE trans;
        !           171:      int icase;
        !           172: {
        !           173:   memset (pstr, '\0', sizeof (re_string_t));
        !           174:   pstr->raw_mbs = (const unsigned char *) str;
        !           175:   pstr->len = len;
        !           176:   pstr->trans = trans;
        !           177:   pstr->icase = icase ? 1 : 0;
        !           178: }
        !           179: 
        !           180: #ifdef RE_ENABLE_I18N
        !           181: 
        !           182: /* Build wide character buffer PSTR->WCS.
        !           183:    If the byte sequence of the string are:
        !           184:      <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
        !           185:    Then wide character buffer will be:
        !           186:      <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>
        !           187:    We use WEOF for padding, they indicate that the position isn't
        !           188:    a first byte of a multibyte character.
        !           189: 
        !           190:    Note that this function assumes PSTR->VALID_LEN elements are already
        !           191:    built and starts from PSTR->VALID_LEN.  */
        !           192: 
        !           193: static void
        !           194: build_wcs_buffer (pstr)
        !           195:      re_string_t *pstr;
        !           196: {
        !           197:   mbstate_t prev_st;
        !           198:   int byte_idx, end_idx, mbclen, remain_len;
        !           199:   /* Build the buffers from pstr->valid_len to either pstr->len or
        !           200:      pstr->bufs_len.  */
        !           201:   end_idx = (pstr->bufs_len > pstr->len)? pstr->len : pstr->bufs_len;
        !           202:   for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
        !           203:     {
        !           204:       wchar_t wc;
        !           205:       remain_len = end_idx - byte_idx;
        !           206:       prev_st = pstr->cur_state;
        !           207:       mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
        !           208:                              + byte_idx), remain_len, &pstr->cur_state);
        !           209:       if (BE (mbclen == (size_t) -2, 0))
        !           210:        {
        !           211:          /* The buffer doesn't have enough space, finish to build.  */
        !           212:          pstr->cur_state = prev_st;
        !           213:          break;
        !           214:        }
        !           215:       else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
        !           216:        {
        !           217:          /* We treat these cases as a singlebyte character.  */
        !           218:          mbclen = 1;
        !           219:          wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
        !           220:          pstr->cur_state = prev_st;
        !           221:        }
        !           222: 
        !           223:       /* Apply the translateion if we need.  */
        !           224:       if (pstr->trans != NULL && mbclen == 1)
        !           225:        {
        !           226:          int ch = pstr->trans[pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]];
        !           227:          pstr->mbs_case[byte_idx] = ch;
        !           228:        }
        !           229:       /* Write wide character and padding.  */
        !           230:       pstr->wcs[byte_idx++] = wc;
        !           231:       /* Write paddings.  */
        !           232:       for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
        !           233:        pstr->wcs[byte_idx++] = WEOF;
        !           234:     }
        !           235:   pstr->valid_len = byte_idx;
        !           236: }
        !           237: 
        !           238: /* Build wide character buffer PSTR->WCS like build_wcs_buffer,
        !           239:    but for REG_ICASE.  */
        !           240: 
        !           241: static void
        !           242: build_wcs_upper_buffer (pstr)
        !           243:      re_string_t *pstr;
        !           244: {
        !           245:   mbstate_t prev_st;
        !           246:   int byte_idx, end_idx, mbclen, remain_len;
        !           247:   /* Build the buffers from pstr->valid_len to either pstr->len or
        !           248:      pstr->bufs_len.  */
        !           249:   end_idx = (pstr->bufs_len > pstr->len)? pstr->len : pstr->bufs_len;
        !           250:   for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
        !           251:     {
        !           252:       wchar_t wc;
        !           253:       remain_len = end_idx - byte_idx;
        !           254:       prev_st = pstr->cur_state;
        !           255:       mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
        !           256:                              + byte_idx), remain_len, &pstr->cur_state);
        !           257:       if (BE (mbclen == (size_t) -2, 0))
        !           258:        {
        !           259:          /* The buffer doesn't have enough space, finish to build.  */
        !           260:          pstr->cur_state = prev_st;
        !           261:          break;
        !           262:        }
        !           263:       else if (mbclen == 1 || mbclen == (size_t) -1 || mbclen == 0)
        !           264:        {
        !           265:          /* In case of a singlebyte character.  */
        !           266:          int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
        !           267:          /* Apply the translateion if we need.  */
        !           268:          if (pstr->trans != NULL && mbclen == 1)
        !           269:            {
        !           270:              ch = pstr->trans[ch];
        !           271:              pstr->mbs_case[byte_idx] = ch;
        !           272:            }
        !           273:          pstr->wcs[byte_idx] = iswlower (wc) ? toupper (wc) : wc;
        !           274:          pstr->mbs[byte_idx++] = islower (ch) ? toupper (ch) : ch;
        !           275:          if (BE (mbclen == (size_t) -1, 0))
        !           276:            pstr->cur_state = prev_st;
        !           277:        }
        !           278:       else /* mbclen > 1 */
        !           279:        {
        !           280:          if (iswlower (wc))
        !           281:            wcrtomb ((char *) pstr->mbs + byte_idx, towupper (wc), &prev_st);
        !           282:          else
        !           283:            memcpy (pstr->mbs + byte_idx,
        !           284:                    pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
        !           285:          pstr->wcs[byte_idx++] = iswlower (wc) ? toupper (wc) : wc;
        !           286:          /* Write paddings.  */
        !           287:          for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
        !           288:            pstr->wcs[byte_idx++] = WEOF;
        !           289:        }
        !           290:     }
        !           291:   pstr->valid_len = byte_idx;
        !           292: }
        !           293: 
        !           294: /* Skip characters until the index becomes greater than NEW_RAW_IDX.
        !           295:    Return the index.  */
        !           296: 
        !           297: static int
        !           298: re_string_skip_chars (pstr, new_raw_idx, last_wc)
        !           299:      re_string_t *pstr;
        !           300:      int new_raw_idx;
        !           301:      wint_t *last_wc;
        !           302: {
        !           303:   mbstate_t prev_st;
        !           304:   int rawbuf_idx, mbclen;
        !           305:   wchar_t wc = 0;
        !           306: 
        !           307:   /* Skip the characters which are not necessary to check.  */
        !           308:   for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_len;
        !           309:        rawbuf_idx < new_raw_idx;)
        !           310:     {
        !           311:       int remain_len;
        !           312:       remain_len = pstr->len - rawbuf_idx;
        !           313:       prev_st = pstr->cur_state;
        !           314:       mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
        !           315:                        remain_len, &pstr->cur_state);
        !           316:       if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
        !           317:        {
        !           318:          /* We treat these cases as a singlebyte character.  */
        !           319:          mbclen = 1;
        !           320:          pstr->cur_state = prev_st;
        !           321:        }
        !           322:       /* Then proceed the next character.  */
        !           323:       rawbuf_idx += mbclen;
        !           324:     }
        !           325:   *last_wc = (wint_t) wc;
        !           326:   return rawbuf_idx;
        !           327: }
        !           328: #endif /* RE_ENABLE_I18N  */
        !           329: 
        !           330: /* Build the buffer PSTR->MBS, and apply the translation if we need.
        !           331:    This function is used in case of REG_ICASE.  */
        !           332: 
        !           333: static void
        !           334: build_upper_buffer (pstr)
        !           335:      re_string_t *pstr;
        !           336: {
        !           337:   int char_idx, end_idx;
        !           338:   end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
        !           339: 
        !           340:   for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
        !           341:     {
        !           342:       int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
        !           343:       if (pstr->trans != NULL)
        !           344:        {
        !           345:          ch =  pstr->trans[ch];
        !           346:          pstr->mbs_case[char_idx] = ch;
        !           347:        }
        !           348:       if (islower (ch))
        !           349:        pstr->mbs[char_idx] = toupper (ch);
        !           350:       else
        !           351:        pstr->mbs[char_idx] = ch;
        !           352:     }
        !           353:   pstr->valid_len = char_idx;
        !           354: }
        !           355: 
        !           356: /* Apply TRANS to the buffer in PSTR.  */
        !           357: 
        !           358: static void
        !           359: re_string_translate_buffer (pstr)
        !           360:      re_string_t *pstr;
        !           361: {
        !           362:   int buf_idx, end_idx;
        !           363:   end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
        !           364: 
        !           365:   for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
        !           366:     {
        !           367:       int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
        !           368:       pstr->mbs_case[buf_idx] = pstr->trans[ch];
        !           369:     }
        !           370: 
        !           371:   pstr->valid_len = buf_idx;
        !           372: }
        !           373: 
        !           374: /* This function re-construct the buffers.
        !           375:    Concretely, convert to wide character in case of MB_CUR_MAX > 1,
        !           376:    convert to upper case in case of REG_ICASE, apply translation.  */
        !           377: 
        !           378: static reg_errcode_t
        !           379: re_string_reconstruct (pstr, idx, eflags, newline)
        !           380:      re_string_t *pstr;
        !           381:      int idx, eflags, newline;
        !           382: {
        !           383:   int offset = idx - pstr->raw_mbs_idx;
        !           384:   if (offset < 0)
        !           385:     {
        !           386:       /* Reset buffer.  */
        !           387: #ifdef RE_ENABLE_I18N
        !           388:       if (MB_CUR_MAX > 1)
        !           389:        memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
        !           390: #endif /* RE_ENABLE_I18N */
        !           391:       pstr->len += pstr->raw_mbs_idx;
        !           392:       pstr->stop += pstr->raw_mbs_idx;
        !           393:       pstr->valid_len = pstr->raw_mbs_idx = 0;
        !           394:       pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
        !           395:                           : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
        !           396:       if (!MBS_CASE_ALLOCATED (pstr))
        !           397:        pstr->mbs_case = (unsigned char *) pstr->raw_mbs;
        !           398:       if (!MBS_ALLOCATED (pstr) && !MBS_CASE_ALLOCATED (pstr))
        !           399:        pstr->mbs = (unsigned char *) pstr->raw_mbs;
        !           400:       offset = idx;
        !           401:     }
        !           402: 
        !           403:   if (offset != 0)
        !           404:     {
        !           405:       /* Are the characters which are already checked remain?  */
        !           406:       if (offset < pstr->valid_len)
        !           407:        {
        !           408:          /* Yes, move them to the front of the buffer.  */
        !           409:          pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags,
        !           410:                                                    newline);
        !           411: #ifdef RE_ENABLE_I18N
        !           412:          if (MB_CUR_MAX > 1)
        !           413:            memmove (pstr->wcs, pstr->wcs + offset,
        !           414:                     (pstr->valid_len - offset) * sizeof (wint_t));
        !           415: #endif /* RE_ENABLE_I18N */
        !           416:          if (MBS_ALLOCATED (pstr))
        !           417:            memmove (pstr->mbs, pstr->mbs + offset,
        !           418:                     pstr->valid_len - offset);
        !           419:          if (MBS_CASE_ALLOCATED (pstr))
        !           420:            memmove (pstr->mbs_case, pstr->mbs_case + offset,
        !           421:                     pstr->valid_len - offset);
        !           422:          pstr->valid_len -= offset;
        !           423: #if DEBUG
        !           424:          assert (pstr->valid_len > 0);
        !           425: #endif
        !           426:        }
        !           427:       else
        !           428:        {
        !           429:          /* No, skip all characters until IDX.  */
        !           430:          pstr->valid_len = 0;
        !           431: #ifdef RE_ENABLE_I18N
        !           432:          if (MB_CUR_MAX > 1)
        !           433:            {
        !           434:              int wcs_idx;
        !           435:              wint_t wc;
        !           436:              pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
        !           437:              for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
        !           438:                pstr->wcs[wcs_idx] = WEOF;
        !           439:              if (pstr->trans && wc <= 0xff)
        !           440:                wc = pstr->trans[wc];
        !           441:              pstr->tip_context = (IS_WIDE_WORD_CHAR (wc) ? CONTEXT_WORD
        !           442:                                   : ((newline && IS_WIDE_NEWLINE (wc))
        !           443:                                      ? CONTEXT_NEWLINE : 0));
        !           444:            }
        !           445:          else
        !           446: #endif /* RE_ENABLE_I18N */
        !           447:            {
        !           448:              int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
        !           449:              if (pstr->trans)
        !           450:                c = pstr->trans[c];
        !           451:              pstr->tip_context = (IS_WORD_CHAR (c) ? CONTEXT_WORD
        !           452:                                   : ((newline && IS_NEWLINE (c))
        !           453:                                      ? CONTEXT_NEWLINE : 0));
        !           454:            }
        !           455:        }
        !           456:       if (!MBS_CASE_ALLOCATED (pstr))
        !           457:        {
        !           458:          pstr->mbs_case += offset;
        !           459:          /* In case of !MBS_ALLOCATED && !MBS_CASE_ALLOCATED.  */
        !           460:          if (!MBS_ALLOCATED (pstr))
        !           461:            pstr->mbs += offset;
        !           462:        }
        !           463:     }
        !           464:   pstr->raw_mbs_idx = idx;
        !           465:   pstr->len -= offset;
        !           466:   pstr->stop -= offset;
        !           467: 
        !           468:   /* Then build the buffers.  */
        !           469: #ifdef RE_ENABLE_I18N
        !           470:   if (MB_CUR_MAX > 1)
        !           471:     {
        !           472:       if (pstr->icase)
        !           473:        build_wcs_upper_buffer (pstr);
        !           474:       else
        !           475:        build_wcs_buffer (pstr);
        !           476:     }
        !           477:   else
        !           478: #endif /* RE_ENABLE_I18N */
        !           479:     {
        !           480:       if (pstr->icase)
        !           481:        build_upper_buffer (pstr);
        !           482:       else if (pstr->trans != NULL)
        !           483:        re_string_translate_buffer (pstr);
        !           484:     }
        !           485:   pstr->cur_idx = 0;
        !           486: 
        !           487:   return REG_NOERROR;
        !           488: }
        !           489: 
        !           490: static void
        !           491: re_string_destruct (pstr)
        !           492:      re_string_t *pstr;
        !           493: {
        !           494: #ifdef RE_ENABLE_I18N
        !           495:   re_free (pstr->wcs);
        !           496: #endif /* RE_ENABLE_I18N  */
        !           497:   if (MBS_ALLOCATED (pstr))
        !           498:     re_free (pstr->mbs);
        !           499:   if (MBS_CASE_ALLOCATED (pstr))
        !           500:     re_free (pstr->mbs_case);
        !           501: }
        !           502: 
        !           503: /* Return the context at IDX in INPUT.  */
        !           504: 
        !           505: static unsigned int
        !           506: re_string_context_at (input, idx, eflags, newline_anchor)
        !           507:      const re_string_t *input;
        !           508:      int idx, eflags, newline_anchor;
        !           509: {
        !           510:   int c;
        !           511:   if (idx < 0 || idx == input->len)
        !           512:     {
        !           513:       if (idx < 0)
        !           514:        /* In this case, we use the value stored in input->tip_context,
        !           515:           since we can't know the character in input->mbs[-1] here.  */
        !           516:        return input->tip_context;
        !           517:       else /* (idx == input->len) */
        !           518:        return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
        !           519:                : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
        !           520:     }
        !           521: #ifdef RE_ENABLE_I18N
        !           522:   if (MB_CUR_MAX > 1)
        !           523:     {
        !           524:       wint_t wc;
        !           525:       int wc_idx = idx;
        !           526:       while(input->wcs[wc_idx] == WEOF)
        !           527:        {
        !           528: #ifdef DEBUG
        !           529:          /* It must not happen.  */
        !           530:          assert (wc_idx >= 0);
        !           531: #endif
        !           532:          --wc_idx;
        !           533:          if (wc_idx < 0)
        !           534:            return input->tip_context;
        !           535:        }
        !           536:       wc = input->wcs[wc_idx];
        !           537:       if (IS_WIDE_WORD_CHAR (wc))
        !           538:        return CONTEXT_WORD;
        !           539:       return (newline_anchor && IS_WIDE_NEWLINE (wc)) ? CONTEXT_NEWLINE : 0;
        !           540:     }
        !           541:   else
        !           542: #endif
        !           543:     {
        !           544:       c = re_string_byte_at (input, idx);
        !           545:       if (IS_WORD_CHAR (c))
        !           546:        return CONTEXT_WORD;
        !           547:       return (newline_anchor && IS_NEWLINE (c)) ? CONTEXT_NEWLINE : 0;
        !           548:     }
        !           549: }
        !           550: 
        !           551: /* Functions for set operation.  */
        !           552: 
        !           553: static reg_errcode_t
        !           554: re_node_set_alloc (set, size)
        !           555:      re_node_set *set;
        !           556:      int size;
        !           557: {
        !           558:   set->alloc = size;
        !           559:   set->nelem = 0;
        !           560:   set->elems = re_malloc (int, size);
        !           561:   if (BE (set->elems == NULL, 0))
        !           562:     return REG_ESPACE;
        !           563:   return REG_NOERROR;
        !           564: }
        !           565: 
        !           566: static reg_errcode_t
        !           567: re_node_set_init_1 (set, elem)
        !           568:      re_node_set *set;
        !           569:      int elem;
        !           570: {
        !           571:   set->alloc = 1;
        !           572:   set->nelem = 1;
        !           573:   set->elems = re_malloc (int, 1);
        !           574:   if (BE (set->elems == NULL, 0))
        !           575:     {
        !           576:       set->alloc = set->nelem = 0;
        !           577:       return REG_ESPACE;
        !           578:     }
        !           579:   set->elems[0] = elem;
        !           580:   return REG_NOERROR;
        !           581: }
        !           582: 
        !           583: static reg_errcode_t
        !           584: re_node_set_init_2 (set, elem1, elem2)
        !           585:      re_node_set *set;
        !           586:      int elem1, elem2;
        !           587: {
        !           588:   set->alloc = 2;
        !           589:   set->elems = re_malloc (int, 2);
        !           590:   if (BE (set->elems == NULL, 0))
        !           591:     return REG_ESPACE;
        !           592:   if (elem1 == elem2)
        !           593:     {
        !           594:       set->nelem = 1;
        !           595:       set->elems[0] = elem1;
        !           596:     }
        !           597:   else
        !           598:     {
        !           599:       set->nelem = 2;
        !           600:       if (elem1 < elem2)
        !           601:        {
        !           602:          set->elems[0] = elem1;
        !           603:          set->elems[1] = elem2;
        !           604:        }
        !           605:       else
        !           606:        {
        !           607:          set->elems[0] = elem2;
        !           608:          set->elems[1] = elem1;
        !           609:        }
        !           610:     }
        !           611:   return REG_NOERROR;
        !           612: }
        !           613: 
        !           614: static reg_errcode_t
        !           615: re_node_set_init_copy (dest, src)
        !           616:      re_node_set *dest;
        !           617:      const re_node_set *src;
        !           618: {
        !           619:   dest->nelem = src->nelem;
        !           620:   if (src->nelem > 0)
        !           621:     {
        !           622:       dest->alloc = dest->nelem;
        !           623:       dest->elems = re_malloc (int, dest->alloc);
        !           624:       if (BE (dest->elems == NULL, 0))
        !           625:        {
        !           626:          dest->alloc = dest->nelem = 0;
        !           627:          return REG_ESPACE;
        !           628:        }
        !           629:       memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
        !           630:     }
        !           631:   else
        !           632:     re_node_set_init_empty (dest);
        !           633:   return REG_NOERROR;
        !           634: }
        !           635: 
        !           636: /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
        !           637:    DEST. Return value indicate the error code or REG_NOERROR if succeeded.
        !           638:    Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
        !           639: 
        !           640: static reg_errcode_t
        !           641: re_node_set_add_intersect (dest, src1, src2)
        !           642:      re_node_set *dest;
        !           643:      const re_node_set *src1, *src2;
        !           644: {
        !           645:   int i1, i2, id;
        !           646:   if (src1->nelem > 0 && src2->nelem > 0)
        !           647:     {
        !           648:       if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
        !           649:        {
        !           650:          dest->alloc = src1->nelem + src2->nelem + dest->nelem;
        !           651:          dest->elems = re_realloc (dest->elems, int, dest->alloc);
        !           652:          if (BE (dest->elems == NULL, 0))
        !           653:            return REG_ESPACE;
        !           654:        }
        !           655:     }
        !           656:   else
        !           657:     return REG_NOERROR;
        !           658: 
        !           659:   for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
        !           660:     {
        !           661:       if (src1->elems[i1] > src2->elems[i2])
        !           662:        {
        !           663:          ++i2;
        !           664:          continue;
        !           665:        }
        !           666:       if (src1->elems[i1] == src2->elems[i2])
        !           667:        {
        !           668:          while (id < dest->nelem && dest->elems[id] < src2->elems[i2])
        !           669:            ++id;
        !           670:          if (id < dest->nelem && dest->elems[id] == src2->elems[i2])
        !           671:            ++id;
        !           672:          else
        !           673:            {
        !           674:              memmove (dest->elems + id + 1, dest->elems + id,
        !           675:                       sizeof (int) * (dest->nelem - id));
        !           676:              dest->elems[id++] = src2->elems[i2++];
        !           677:              ++dest->nelem;
        !           678:            }
        !           679:        }
        !           680:       ++i1;
        !           681:     }
        !           682:   return REG_NOERROR;
        !           683: }
        !           684: 
        !           685: /* Calculate the union set of the sets SRC1 and SRC2. And store it to
        !           686:    DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
        !           687: 
        !           688: static reg_errcode_t
        !           689: re_node_set_init_union (dest, src1, src2)
        !           690:      re_node_set *dest;
        !           691:      const re_node_set *src1, *src2;
        !           692: {
        !           693:   int i1, i2, id;
        !           694:   if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
        !           695:     {
        !           696:       dest->alloc = src1->nelem + src2->nelem;
        !           697:       dest->elems = re_malloc (int, dest->alloc);
        !           698:       if (BE (dest->elems == NULL, 0))
        !           699:        return REG_ESPACE;
        !           700:     }
        !           701:   else
        !           702:     {
        !           703:       if (src1 != NULL && src1->nelem > 0)
        !           704:        return re_node_set_init_copy (dest, src1);
        !           705:       else if (src2 != NULL && src2->nelem > 0)
        !           706:        return re_node_set_init_copy (dest, src2);
        !           707:       else
        !           708:        re_node_set_init_empty (dest);
        !           709:       return REG_NOERROR;
        !           710:     }
        !           711:   for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
        !           712:     {
        !           713:       if (src1->elems[i1] > src2->elems[i2])
        !           714:        {
        !           715:          dest->elems[id++] = src2->elems[i2++];
        !           716:          continue;
        !           717:        }
        !           718:       if (src1->elems[i1] == src2->elems[i2])
        !           719:        ++i2;
        !           720:       dest->elems[id++] = src1->elems[i1++];
        !           721:     }
        !           722:   if (i1 < src1->nelem)
        !           723:     {
        !           724:       memcpy (dest->elems + id, src1->elems + i1,
        !           725:             (src1->nelem - i1) * sizeof (int));
        !           726:       id += src1->nelem - i1;
        !           727:     }
        !           728:   else if (i2 < src2->nelem)
        !           729:     {
        !           730:       memcpy (dest->elems + id, src2->elems + i2,
        !           731:             (src2->nelem - i2) * sizeof (int));
        !           732:       id += src2->nelem - i2;
        !           733:     }
        !           734:   dest->nelem = id;
        !           735:   return REG_NOERROR;
        !           736: }
        !           737: 
        !           738: /* Calculate the union set of the sets DEST and SRC. And store it to
        !           739:    DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
        !           740: 
        !           741: static reg_errcode_t
        !           742: re_node_set_merge (dest, src)
        !           743:      re_node_set *dest;
        !           744:      const re_node_set *src;
        !           745: {
        !           746:   int si, di;
        !           747:   if (src == NULL || src->nelem == 0)
        !           748:     return REG_NOERROR;
        !           749:   if (dest->alloc < src->nelem + dest->nelem)
        !           750:     {
        !           751:       int *new_buffer;
        !           752:       dest->alloc = 2 * (src->nelem + dest->alloc);
        !           753:       new_buffer = re_realloc (dest->elems, int, dest->alloc);
        !           754:       if (BE (new_buffer == NULL, 0))
        !           755:        return REG_ESPACE;
        !           756:       dest->elems = new_buffer;
        !           757:     }
        !           758: 
        !           759:   for (si = 0, di = 0 ; si < src->nelem && di < dest->nelem ;)
        !           760:     {
        !           761:       int cp_from, ncp, mid, right, src_elem = src->elems[si];
        !           762:       /* Binary search the spot we will add the new element.  */
        !           763:       right = dest->nelem;
        !           764:       while (di < right)
        !           765:        {
        !           766:          mid = (di + right) / 2;
        !           767:          if (dest->elems[mid] < src_elem)
        !           768:            di = mid + 1;
        !           769:          else
        !           770:            right = mid;
        !           771:        }
        !           772:       if (di >= dest->nelem)
        !           773:        break;
        !           774: 
        !           775:       if (dest->elems[di] == src_elem)
        !           776:        {
        !           777:          /* Skip since, DEST already has the element.  */
        !           778:          ++di;
        !           779:          ++si;
        !           780:          continue;
        !           781:        }
        !           782: 
        !           783:       /* Skip the src elements which are less than dest->elems[di].  */
        !           784:       cp_from = si;
        !           785:       while (si < src->nelem && src->elems[si] < dest->elems[di])
        !           786:        ++si;
        !           787:       /* Copy these src elements.  */
        !           788:       ncp = si - cp_from;
        !           789:       memmove (dest->elems + di + ncp, dest->elems + di,
        !           790:               sizeof (int) * (dest->nelem - di));
        !           791:       memcpy (dest->elems + di, src->elems + cp_from,
        !           792:              sizeof (int) * ncp);
        !           793:       /* Update counters.  */
        !           794:       di += ncp;
        !           795:       dest->nelem += ncp;
        !           796:     }
        !           797: 
        !           798:   /* Copy remaining src elements.  */
        !           799:   if (si < src->nelem)
        !           800:     {
        !           801:       memcpy (dest->elems + di, src->elems + si,
        !           802:              sizeof (int) * (src->nelem - si));
        !           803:       dest->nelem += src->nelem - si;
        !           804:     }
        !           805:   return REG_NOERROR;
        !           806: }
        !           807: 
        !           808: /* Insert the new element ELEM to the re_node_set* SET.
        !           809:    return 0 if SET already has ELEM,
        !           810:    return -1 if an error is occured, return 1 otherwise.  */
        !           811: 
        !           812: static int
        !           813: re_node_set_insert (set, elem)
        !           814:      re_node_set *set;
        !           815:      int elem;
        !           816: {
        !           817:   int idx, right, mid;
        !           818:   /* In case of the set is empty.  */
        !           819:   if (set->elems == NULL || set->alloc == 0)
        !           820:     {
        !           821:       if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
        !           822:        return 1;
        !           823:       else
        !           824:        return -1;
        !           825:     }
        !           826: 
        !           827:   /* Binary search the spot we will add the new element.  */
        !           828:   idx = 0;
        !           829:   right = set->nelem;
        !           830:   while (idx < right)
        !           831:     {
        !           832:       mid = (idx + right) / 2;
        !           833:       if (set->elems[mid] < elem)
        !           834:        idx = mid + 1;
        !           835:       else
        !           836:        right = mid;
        !           837:     }
        !           838: 
        !           839:   /* Realloc if we need.  */
        !           840:   if (set->alloc < set->nelem + 1)
        !           841:     {
        !           842:       int *new_array;
        !           843:       set->alloc = set->alloc * 2;
        !           844:       new_array = re_malloc (int, set->alloc);
        !           845:       if (BE (new_array == NULL, 0))
        !           846:        return -1;
        !           847:       /* Copy the elements they are followed by the new element.  */
        !           848:       if (idx > 0)
        !           849:        memcpy (new_array, set->elems, sizeof (int) * (idx));
        !           850:       /* Copy the elements which follows the new element.  */
        !           851:       if (set->nelem - idx > 0)
        !           852:        memcpy (new_array + idx + 1, set->elems + idx,
        !           853:                sizeof (int) * (set->nelem - idx));
        !           854:       re_free (set->elems);
        !           855:       set->elems = new_array;
        !           856:     }
        !           857:   else
        !           858:     {
        !           859:       /* Move the elements which follows the new element.  */
        !           860:       if (set->nelem - idx > 0)
        !           861:        memmove (set->elems + idx + 1, set->elems + idx,
        !           862:                 sizeof (int) * (set->nelem - idx));
        !           863:     }
        !           864:   /* Insert the new element.  */
        !           865:   set->elems[idx] = elem;
        !           866:   ++set->nelem;
        !           867:   return 1;
        !           868: }
        !           869: 
        !           870: /* Compare two node sets SET1 and SET2.
        !           871:    return 1 if SET1 and SET2 are equivalent, retrun 0 otherwise.  */
        !           872: 
        !           873: static int
        !           874: re_node_set_compare (set1, set2)
        !           875:      const re_node_set *set1, *set2;
        !           876: {
        !           877:   int i;
        !           878:   if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
        !           879:     return 0;
        !           880:   for (i = 0 ; i < set1->nelem ; i++)
        !           881:     if (set1->elems[i] != set2->elems[i])
        !           882:       return 0;
        !           883:   return 1;
        !           884: }
        !           885: 
        !           886: /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */
        !           887: 
        !           888: static int
        !           889: re_node_set_contains (set, elem)
        !           890:      const re_node_set *set;
        !           891:      int elem;
        !           892: {
        !           893:   int idx, right, mid;
        !           894:   if (set->nelem <= 0)
        !           895:     return 0;
        !           896: 
        !           897:   /* Binary search the element.  */
        !           898:   idx = 0;
        !           899:   right = set->nelem - 1;
        !           900:   while (idx < right)
        !           901:     {
        !           902:       mid = (idx + right) / 2;
        !           903:       if (set->elems[mid] < elem)
        !           904:        idx = mid + 1;
        !           905:       else
        !           906:        right = mid;
        !           907:     }
        !           908:   return set->elems[idx] == elem ? idx + 1 : 0;
        !           909: }
        !           910: 
        !           911: static void
        !           912: re_node_set_remove_at (set, idx)
        !           913:      re_node_set *set;
        !           914:      int idx;
        !           915: {
        !           916:   if (idx < 0 || idx >= set->nelem)
        !           917:     return;
        !           918:   if (idx < set->nelem - 1)
        !           919:     memmove (set->elems + idx, set->elems + idx + 1,
        !           920:             sizeof (int) * (set->nelem - idx - 1));
        !           921:   --set->nelem;
        !           922: }
        !           923: 
        !           924: 
        !           925: /* Add the token TOKEN to dfa->nodes, and return the index of the token.
        !           926:    Or return -1, if an error will be occured.  */
        !           927: 
        !           928: static int
        !           929: re_dfa_add_node (dfa, token, mode)
        !           930:      re_dfa_t *dfa;
        !           931:      re_token_t token;
        !           932:      int mode;
        !           933: {
        !           934:   if (dfa->nodes_len >= dfa->nodes_alloc)
        !           935:     {
        !           936:       re_token_t *new_array;
        !           937:       dfa->nodes_alloc *= 2;
        !           938:       new_array = re_realloc (dfa->nodes, re_token_t, dfa->nodes_alloc);
        !           939:       if (BE (new_array == NULL, 0))
        !           940:        return -1;
        !           941:       else
        !           942:        dfa->nodes = new_array;
        !           943:       if (mode)
        !           944:        {
        !           945:          int *new_nexts, *new_indices;
        !           946:          re_node_set *new_edests, *new_eclosures, *new_inveclosures;
        !           947: 
        !           948:          new_nexts = re_realloc (dfa->nexts, int, dfa->nodes_alloc);
        !           949:          new_indices = re_realloc (dfa->org_indices, int, dfa->nodes_alloc);
        !           950:          new_edests = re_realloc (dfa->edests, re_node_set, dfa->nodes_alloc);
        !           951:          new_eclosures = re_realloc (dfa->eclosures, re_node_set,
        !           952:                                      dfa->nodes_alloc);
        !           953:          new_inveclosures = re_realloc (dfa->inveclosures, re_node_set,
        !           954:                                         dfa->nodes_alloc);
        !           955:          if (BE (new_nexts == NULL || new_indices == NULL
        !           956:                  || new_edests == NULL || new_eclosures == NULL
        !           957:                  || new_inveclosures == NULL, 0))
        !           958:            return -1;
        !           959:          dfa->nexts = new_nexts;
        !           960:          dfa->org_indices = new_indices;
        !           961:          dfa->edests = new_edests;
        !           962:          dfa->eclosures = new_eclosures;
        !           963:          dfa->inveclosures = new_inveclosures;
        !           964:        }
        !           965:     }
        !           966:   dfa->nodes[dfa->nodes_len] = token;
        !           967:   dfa->nodes[dfa->nodes_len].duplicated = 0;
        !           968:   dfa->nodes[dfa->nodes_len].constraint = 0;
        !           969:   return dfa->nodes_len++;
        !           970: }
        !           971: 
        !           972: static unsigned int inline
        !           973: calc_state_hash (nodes, context)
        !           974:      const re_node_set *nodes;
        !           975:      unsigned int context;
        !           976: {
        !           977:   unsigned int hash = nodes->nelem + context;
        !           978:   int i;
        !           979:   for (i = 0 ; i < nodes->nelem ; i++)
        !           980:     hash += nodes->elems[i];
        !           981:   return hash;
        !           982: }
        !           983: 
        !           984: /* Search for the state whose node_set is equivalent to NODES.
        !           985:    Return the pointer to the state, if we found it in the DFA.
        !           986:    Otherwise create the new one and return it.  In case of an error
        !           987:    return NULL and set the error code in ERR.
        !           988:    Note: - We assume NULL as the invalid state, then it is possible that
        !           989:           return value is NULL and ERR is REG_NOERROR.
        !           990:         - We never return non-NULL value in case of any errors, it is for
        !           991:           optimization.  */
        !           992: 
        !           993: static re_dfastate_t*
        !           994: re_acquire_state (err, dfa, nodes)
        !           995:      reg_errcode_t *err;
        !           996:      re_dfa_t *dfa;
        !           997:      const re_node_set *nodes;
        !           998: {
        !           999:   unsigned int hash;
        !          1000:   re_dfastate_t *new_state;
        !          1001:   struct re_state_table_entry *spot;
        !          1002:   int i;
        !          1003:   if (BE (nodes->nelem == 0, 0))
        !          1004:     {
        !          1005:       *err = REG_NOERROR;
        !          1006:       return NULL;
        !          1007:     }
        !          1008:   hash = calc_state_hash (nodes, 0);
        !          1009:   spot = dfa->state_table + (hash & dfa->state_hash_mask);
        !          1010: 
        !          1011:   for (i = 0 ; i < spot->num ; i++)
        !          1012:     {
        !          1013:       re_dfastate_t *state = spot->array[i];
        !          1014:       if (hash != state->hash)
        !          1015:        continue;
        !          1016:       if (re_node_set_compare (&state->nodes, nodes))
        !          1017:        return state;
        !          1018:     }
        !          1019: 
        !          1020:   /* There are no appropriate state in the dfa, create the new one.  */
        !          1021:   new_state = create_ci_newstate (dfa, nodes, hash);
        !          1022:   if (BE (new_state != NULL, 1))
        !          1023:     return new_state;
        !          1024:   else
        !          1025:     {
        !          1026:       *err = REG_ESPACE;
        !          1027:       return NULL;
        !          1028:     }
        !          1029: }
        !          1030: 
        !          1031: /* Search for the state whose node_set is equivalent to NODES and
        !          1032:    whose context is equivalent to CONTEXT.
        !          1033:    Return the pointer to the state, if we found it in the DFA.
        !          1034:    Otherwise create the new one and return it.  In case of an error
        !          1035:    return NULL and set the error code in ERR.
        !          1036:    Note: - We assume NULL as the invalid state, then it is possible that
        !          1037:           return value is NULL and ERR is REG_NOERROR.
        !          1038:         - We never return non-NULL value in case of any errors, it is for
        !          1039:           optimization.  */
        !          1040: 
        !          1041: static re_dfastate_t*
        !          1042: re_acquire_state_context (err, dfa, nodes, context)
        !          1043:      reg_errcode_t *err;
        !          1044:      re_dfa_t *dfa;
        !          1045:      const re_node_set *nodes;
        !          1046:      unsigned int context;
        !          1047: {
        !          1048:   unsigned int hash;
        !          1049:   re_dfastate_t *new_state;
        !          1050:   struct re_state_table_entry *spot;
        !          1051:   int i;
        !          1052:   if (nodes->nelem == 0)
        !          1053:     {
        !          1054:       *err = REG_NOERROR;
        !          1055:       return NULL;
        !          1056:     }
        !          1057:   hash = calc_state_hash (nodes, context);
        !          1058:   spot = dfa->state_table + (hash & dfa->state_hash_mask);
        !          1059: 
        !          1060:   for (i = 0 ; i < spot->num ; i++)
        !          1061:     {
        !          1062:       re_dfastate_t *state = spot->array[i];
        !          1063:       if (hash != state->hash)
        !          1064:        continue;
        !          1065:       if (re_node_set_compare (state->entrance_nodes, nodes)
        !          1066:          && state->context == context)
        !          1067:        return state;
        !          1068:     }
        !          1069:   /* There are no appropriate state in `dfa', create the new one.  */
        !          1070:   new_state = create_cd_newstate (dfa, nodes, context, hash);
        !          1071:   if (BE (new_state != NULL, 1))
        !          1072:     return new_state;
        !          1073:   else
        !          1074:     {
        !          1075:       *err = REG_ESPACE;
        !          1076:       return NULL;
        !          1077:     }
        !          1078: }
        !          1079: 
        !          1080: /* Allocate memory for DFA state and initialize common properties.
        !          1081:    Return the new state if succeeded, otherwise return NULL.  */
        !          1082: 
        !          1083: static re_dfastate_t *
        !          1084: create_newstate_common (dfa, nodes, hash)
        !          1085:      re_dfa_t *dfa;
        !          1086:      const re_node_set *nodes;
        !          1087:      unsigned int hash;
        !          1088: {
        !          1089:   re_dfastate_t *newstate;
        !          1090:   reg_errcode_t err;
        !          1091:   newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
        !          1092:   if (BE (newstate == NULL, 0))
        !          1093:     return NULL;
        !          1094:   err = re_node_set_init_copy (&newstate->nodes, nodes);
        !          1095:   if (BE (err != REG_NOERROR, 0))
        !          1096:     {
        !          1097:       re_free (newstate);
        !          1098:       return NULL;
        !          1099:     }
        !          1100:   newstate->trtable = NULL;
        !          1101:   newstate->trtable_search = NULL;
        !          1102:   newstate->hash = hash;
        !          1103:   return newstate;
        !          1104: }
        !          1105: 
        !          1106: /* Store the new state NEWSTATE whose hash value is HASH in appropriate
        !          1107:    position.  Return value indicate the error code if failed.  */
        !          1108: 
        !          1109: static reg_errcode_t
        !          1110: register_state (dfa, newstate, hash)
        !          1111:      re_dfa_t *dfa;
        !          1112:      re_dfastate_t *newstate;
        !          1113:      unsigned int hash;
        !          1114: {
        !          1115:   struct re_state_table_entry *spot;
        !          1116:   spot = dfa->state_table + (hash & dfa->state_hash_mask);
        !          1117: 
        !          1118:   if (spot->alloc <= spot->num)
        !          1119:     {
        !          1120:       re_dfastate_t **new_array;
        !          1121:       spot->alloc = 2 * spot->num + 2;
        !          1122:       new_array = re_realloc (spot->array, re_dfastate_t *, spot->alloc);
        !          1123:       if (BE (new_array == NULL, 0))
        !          1124:        return REG_ESPACE;
        !          1125:       spot->array = new_array;
        !          1126:     }
        !          1127:   spot->array[spot->num++] = newstate;
        !          1128:   return REG_NOERROR;
        !          1129: }
        !          1130: 
        !          1131: /* Create the new state which is independ of contexts.
        !          1132:    Return the new state if succeeded, otherwise return NULL.  */
        !          1133: 
        !          1134: static re_dfastate_t *
        !          1135: create_ci_newstate (dfa, nodes, hash)
        !          1136:      re_dfa_t *dfa;
        !          1137:      const re_node_set *nodes;
        !          1138:      unsigned int hash;
        !          1139: {
        !          1140:   int i;
        !          1141:   reg_errcode_t err;
        !          1142:   re_dfastate_t *newstate;
        !          1143:   newstate = create_newstate_common (dfa, nodes, hash);
        !          1144:   if (BE (newstate == NULL, 0))
        !          1145:     return NULL;
        !          1146:   newstate->entrance_nodes = &newstate->nodes;
        !          1147: 
        !          1148:   for (i = 0 ; i < nodes->nelem ; i++)
        !          1149:     {
        !          1150:       re_token_t *node = dfa->nodes + nodes->elems[i];
        !          1151:       re_token_type_t type = node->type;
        !          1152:       if (type == CHARACTER && !node->constraint)
        !          1153:        continue;
        !          1154: 
        !          1155:       /* If the state has the halt node, the state is a halt state.  */
        !          1156:       else if (type == END_OF_RE)
        !          1157:        newstate->halt = 1;
        !          1158: #ifdef RE_ENABLE_I18N
        !          1159:       else if (type == COMPLEX_BRACKET
        !          1160:               || (type == OP_PERIOD && MB_CUR_MAX > 1))
        !          1161:        newstate->accept_mb = 1;
        !          1162: #endif /* RE_ENABLE_I18N */
        !          1163:       else if (type == OP_BACK_REF)
        !          1164:        newstate->has_backref = 1;
        !          1165:       else if (type == ANCHOR || node->constraint)
        !          1166:        newstate->has_constraint = 1;
        !          1167:     }
        !          1168:   err = register_state (dfa, newstate, hash);
        !          1169:   if (BE (err != REG_NOERROR, 0))
        !          1170:     {
        !          1171:       free_state (newstate);
        !          1172:       newstate = NULL;
        !          1173:     }
        !          1174:   return newstate;
        !          1175: }
        !          1176: 
        !          1177: /* Create the new state which is depend on the context CONTEXT.
        !          1178:    Return the new state if succeeded, otherwise return NULL.  */
        !          1179: 
        !          1180: static re_dfastate_t *
        !          1181: create_cd_newstate (dfa, nodes, context, hash)
        !          1182:      re_dfa_t *dfa;
        !          1183:      const re_node_set *nodes;
        !          1184:      unsigned int context, hash;
        !          1185: {
        !          1186:   int i, nctx_nodes = 0;
        !          1187:   reg_errcode_t err;
        !          1188:   re_dfastate_t *newstate;
        !          1189: 
        !          1190:   newstate = create_newstate_common (dfa, nodes, hash);
        !          1191:   if (BE (newstate == NULL, 0))
        !          1192:     return NULL;
        !          1193:   newstate->context = context;
        !          1194:   newstate->entrance_nodes = &newstate->nodes;
        !          1195: 
        !          1196:   for (i = 0 ; i < nodes->nelem ; i++)
        !          1197:     {
        !          1198:       unsigned int constraint = 0;
        !          1199:       re_token_t *node = dfa->nodes + nodes->elems[i];
        !          1200:       re_token_type_t type = node->type;
        !          1201:       if (node->constraint)
        !          1202:        constraint = node->constraint;
        !          1203: 
        !          1204:       if (type == CHARACTER && !constraint)
        !          1205:        continue;
        !          1206:       /* If the state has the halt node, the state is a halt state.  */
        !          1207:       else if (type == END_OF_RE)
        !          1208:        newstate->halt = 1;
        !          1209: #ifdef RE_ENABLE_I18N
        !          1210:       else if (type == COMPLEX_BRACKET
        !          1211:               || (type == OP_PERIOD && MB_CUR_MAX > 1))
        !          1212:        newstate->accept_mb = 1;
        !          1213: #endif /* RE_ENABLE_I18N */
        !          1214:       else if (type == OP_BACK_REF)
        !          1215:        newstate->has_backref = 1;
        !          1216:       else if (type == ANCHOR)
        !          1217:        constraint = node->opr.ctx_type;
        !          1218: 
        !          1219:       if (constraint)
        !          1220:        {
        !          1221:          if (newstate->entrance_nodes == &newstate->nodes)
        !          1222:            {
        !          1223:              newstate->entrance_nodes = re_malloc (re_node_set, 1);
        !          1224:              if (BE (newstate->entrance_nodes == NULL, 0))
        !          1225:                {
        !          1226:                  free_state (newstate);
        !          1227:                  return NULL;
        !          1228:                }
        !          1229:              re_node_set_init_copy (newstate->entrance_nodes, nodes);
        !          1230:              nctx_nodes = 0;
        !          1231:              newstate->has_constraint = 1;
        !          1232:            }
        !          1233: 
        !          1234:          if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
        !          1235:            {
        !          1236:              re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
        !          1237:              ++nctx_nodes;
        !          1238:            }
        !          1239:        }
        !          1240:     }
        !          1241:   err = register_state (dfa, newstate, hash);
        !          1242:   if (BE (err != REG_NOERROR, 0))
        !          1243:     {
        !          1244:       free_state (newstate);
        !          1245:       newstate = NULL;
        !          1246:     }
        !          1247:   return  newstate;
        !          1248: }
        !          1249: 
        !          1250: static void
        !          1251: free_state (state)
        !          1252:      re_dfastate_t *state;
        !          1253: {
        !          1254:   if (state->entrance_nodes != &state->nodes)
        !          1255:     {
        !          1256:       re_node_set_free (state->entrance_nodes);
        !          1257:       re_free (state->entrance_nodes);
        !          1258:     }
        !          1259:   re_node_set_free (&state->nodes);
        !          1260:   re_free (state->trtable);
        !          1261:   re_free (state->trtable_search);
        !          1262:   re_free (state);
        !          1263: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>