PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mbstring - php_mbregex.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 470 596 78.9 %
Date: 2014-07-21 Functions: 36 39 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Tsukada Takuya <tsukada@fminn.nagano.nagano.jp>              |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : 
      22             : #ifdef HAVE_CONFIG_H
      23             : #include "config.h"
      24             : #endif
      25             : 
      26             : #include "php.h"
      27             : #include "php_ini.h"
      28             : 
      29             : #if HAVE_MBREGEX
      30             : 
      31             : #include "ext/standard/php_smart_str.h"
      32             : #include "ext/standard/info.h"
      33             : #include "php_mbregex.h"
      34             : #include "mbstring.h"
      35             :  
      36             : #include "php_onig_compat.h" /* must come prior to the oniguruma header */
      37             : #include <oniguruma.h>
      38             : #undef UChar
      39             : 
      40             : ZEND_EXTERN_MODULE_GLOBALS(mbstring)
      41             : 
      42             : struct _zend_mb_regex_globals {
      43             :         OnigEncoding default_mbctype;
      44             :         OnigEncoding current_mbctype;
      45             :         HashTable ht_rc;
      46             :         zval *search_str;
      47             :         zval *search_str_val;
      48             :         unsigned int search_pos;
      49             :         php_mb_regex_t *search_re;
      50             :         OnigRegion *search_regs;
      51             :         OnigOptionType regex_default_options;
      52             :         OnigSyntaxType *regex_default_syntax;
      53             : };
      54             : 
      55             : #define MBREX(g) (MBSTRG(mb_regex_globals)->g)
      56             : 
      57             : /* {{{ static void php_mb_regex_free_cache() */
      58         226 : static void php_mb_regex_free_cache(php_mb_regex_t **pre) 
      59             : {
      60         226 :         onig_free(*pre);
      61         226 : }
      62             : /* }}} */
      63             : 
      64             : /* {{{ _php_mb_regex_globals_ctor */
      65       21257 : static int _php_mb_regex_globals_ctor(zend_mb_regex_globals *pglobals TSRMLS_DC)
      66             : {
      67       21257 :         pglobals->default_mbctype = ONIG_ENCODING_UTF8;
      68       21257 :         pglobals->current_mbctype = ONIG_ENCODING_UTF8;
      69       21257 :         zend_hash_init(&(pglobals->ht_rc), 0, NULL, (void (*)(void *)) php_mb_regex_free_cache, 1);
      70       21257 :         pglobals->search_str = (zval*) NULL;
      71       21257 :         pglobals->search_re = (php_mb_regex_t*)NULL;
      72       21257 :         pglobals->search_pos = 0;
      73       21257 :         pglobals->search_regs = (OnigRegion*)NULL;
      74       21257 :         pglobals->regex_default_options = ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE;
      75       21257 :         pglobals->regex_default_syntax = ONIG_SYNTAX_RUBY;
      76       21257 :         return SUCCESS;
      77             : }
      78             : /* }}} */
      79             : 
      80             : /* {{{ _php_mb_regex_globals_dtor */
      81       21290 : static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) 
      82             : {
      83       21290 :         zend_hash_destroy(&pglobals->ht_rc);
      84       21290 : }
      85             : /* }}} */
      86             : 
      87             : /* {{{ php_mb_regex_globals_alloc */
      88       21257 : zend_mb_regex_globals *php_mb_regex_globals_alloc(TSRMLS_D)
      89             : {
      90       21257 :         zend_mb_regex_globals *pglobals = pemalloc(
      91             :                         sizeof(zend_mb_regex_globals), 1);
      92       21257 :         if (!pglobals) {
      93           0 :                 return NULL;
      94             :         }
      95       21257 :         if (SUCCESS != _php_mb_regex_globals_ctor(pglobals TSRMLS_CC)) {
      96           0 :                 pefree(pglobals, 1);
      97           0 :                 return NULL;
      98             :         }
      99       21257 :         return pglobals;
     100             : }
     101             : /* }}} */
     102             : 
     103             : /* {{{ php_mb_regex_globals_free */
     104       21290 : void php_mb_regex_globals_free(zend_mb_regex_globals *pglobals TSRMLS_DC)
     105             : {
     106       21290 :         if (!pglobals) {
     107           0 :                 return;
     108             :         }
     109       21290 :         _php_mb_regex_globals_dtor(pglobals TSRMLS_CC);
     110       21290 :         pefree(pglobals, 1);
     111             : }
     112             : /* }}} */
     113             : 
     114             : /* {{{ PHP_MINIT_FUNCTION(mb_regex) */
     115       21257 : PHP_MINIT_FUNCTION(mb_regex)
     116             : {
     117       21257 :         onig_init();
     118       21257 :         return SUCCESS;
     119             : }
     120             : /* }}} */
     121             : 
     122             : /* {{{ PHP_MSHUTDOWN_FUNCTION(mb_regex) */
     123       21290 : PHP_MSHUTDOWN_FUNCTION(mb_regex)
     124             : {
     125       21290 :         onig_end();
     126       21290 :         return SUCCESS;
     127             : }
     128             : /* }}} */
     129             : 
     130             : /* {{{ PHP_RINIT_FUNCTION(mb_regex) */
     131       21214 : PHP_RINIT_FUNCTION(mb_regex)
     132             : {
     133       21214 :         return MBSTRG(mb_regex_globals) ? SUCCESS: FAILURE;
     134             : }
     135             : /* }}} */
     136             : 
     137             : /* {{{ PHP_RSHUTDOWN_FUNCTION(mb_regex) */
     138       21249 : PHP_RSHUTDOWN_FUNCTION(mb_regex)
     139             : {
     140       21249 :         MBREX(current_mbctype) = MBREX(default_mbctype);
     141             : 
     142       21249 :         if (MBREX(search_str) != NULL) {
     143           4 :                 zval_ptr_dtor(&MBREX(search_str));
     144           4 :                 MBREX(search_str) = (zval *)NULL;
     145             :         }
     146       21249 :         MBREX(search_pos) = 0;
     147             : 
     148       21249 :         if (MBREX(search_regs) != NULL) {
     149           2 :                 onig_region_free(MBREX(search_regs), 1);
     150           2 :                 MBREX(search_regs) = (OnigRegion *)NULL;
     151             :         }
     152       21249 :         zend_hash_clean(&MBREX(ht_rc));
     153             : 
     154       21249 :         return SUCCESS;
     155             : }
     156             : /* }}} */
     157             : 
     158             : /* {{{ PHP_MINFO_FUNCTION(mb_regex) */
     159         150 : PHP_MINFO_FUNCTION(mb_regex)
     160             : {
     161             :         char buf[32];
     162         150 :         php_info_print_table_start();
     163         150 :         php_info_print_table_row(2, "Multibyte (japanese) regex support", "enabled");
     164         150 :         snprintf(buf, sizeof(buf), "%d.%d.%d",
     165             :                         ONIGURUMA_VERSION_MAJOR,
     166             :                         ONIGURUMA_VERSION_MINOR,
     167             :                         ONIGURUMA_VERSION_TEENY);
     168             : #ifdef PHP_ONIG_BUNDLED
     169             : #ifdef USE_COMBINATION_EXPLOSION_CHECK
     170         150 :         php_info_print_table_row(2, "Multibyte regex (oniguruma) backtrack check", "On");
     171             : #else   /* USE_COMBINATION_EXPLOSION_CHECK */
     172             :         php_info_print_table_row(2, "Multibyte regex (oniguruma) backtrack check", "Off");
     173             : #endif  /* USE_COMBINATION_EXPLOSION_CHECK */
     174             : #endif /* PHP_BUNDLED_ONIG */
     175         150 :         php_info_print_table_row(2, "Multibyte regex (oniguruma) version", buf);
     176         150 :         php_info_print_table_end();
     177         150 : }
     178             : /* }}} */
     179             : 
     180             : /*
     181             :  * encoding name resolver
     182             :  */
     183             : 
     184             : /* {{{ encoding name map */
     185             : typedef struct _php_mb_regex_enc_name_map_t {
     186             :         const char *names;
     187             :         OnigEncoding code;
     188             : } php_mb_regex_enc_name_map_t;
     189             : 
     190             : php_mb_regex_enc_name_map_t enc_name_map[] = {
     191             : #ifdef ONIG_ENCODING_EUC_JP
     192             :         {
     193             :                 "EUC-JP\0EUCJP\0X-EUC-JP\0UJIS\0EUCJP\0EUCJP-WIN\0",
     194             :                 ONIG_ENCODING_EUC_JP
     195             :         },
     196             : #endif
     197             : #ifdef ONIG_ENCODING_UTF8
     198             :         {
     199             :                 "UTF-8\0UTF8\0",
     200             :                 ONIG_ENCODING_UTF8
     201             :         },
     202             : #endif
     203             : #ifdef ONIG_ENCODING_UTF16_BE
     204             :         {
     205             :                 "UTF-16\0UTF-16BE\0",
     206             :                 ONIG_ENCODING_UTF16_BE
     207             :         },
     208             : #endif
     209             : #ifdef ONIG_ENCODING_UTF16_LE
     210             :         {
     211             :                 "UTF-16LE\0",
     212             :                 ONIG_ENCODING_UTF16_LE
     213             :         },
     214             : #endif
     215             : #ifdef ONIG_ENCODING_UTF32_BE
     216             :         {
     217             :                 "UCS-4\0UTF-32\0UTF-32BE\0",
     218             :                 ONIG_ENCODING_UTF32_BE
     219             :         },
     220             : #endif
     221             : #ifdef ONIG_ENCODING_UTF32_LE
     222             :         {
     223             :                 "UCS-4LE\0UTF-32LE\0",
     224             :                 ONIG_ENCODING_UTF32_LE
     225             :         },
     226             : #endif
     227             : #ifdef ONIG_ENCODING_SJIS
     228             :         {
     229             :                 "SJIS\0CP932\0MS932\0SHIFT_JIS\0SJIS-WIN\0WINDOWS-31J\0",
     230             :                 ONIG_ENCODING_SJIS
     231             :         },
     232             : #endif
     233             : #ifdef ONIG_ENCODING_BIG5
     234             :         {
     235             :                 "BIG5\0BIG-5\0BIGFIVE\0CN-BIG5\0BIG-FIVE\0",
     236             :                 ONIG_ENCODING_BIG5
     237             :         },
     238             : #endif
     239             : #ifdef ONIG_ENCODING_EUC_CN
     240             :         {
     241             :                 "EUC-CN\0EUCCN\0EUC_CN\0GB-2312\0GB2312\0",
     242             :                 ONIG_ENCODING_EUC_CN
     243             :         },
     244             : #endif
     245             : #ifdef ONIG_ENCODING_EUC_TW
     246             :         {
     247             :                 "EUC-TW\0EUCTW\0EUC_TW\0",
     248             :                 ONIG_ENCODING_EUC_TW
     249             :         },
     250             : #endif
     251             : #ifdef ONIG_ENCODING_EUC_KR
     252             :         {
     253             :                 "EUC-KR\0EUCKR\0EUC_KR\0",
     254             :                 ONIG_ENCODING_EUC_KR
     255             :         },
     256             : #endif
     257             : #if defined(ONIG_ENCODING_KOI8) && !PHP_ONIG_BAD_KOI8_ENTRY
     258             :         {
     259             :                 "KOI8\0KOI-8\0",
     260             :                 ONIG_ENCODING_KOI8
     261             :         },
     262             : #endif
     263             : #ifdef ONIG_ENCODING_KOI8_R
     264             :         {
     265             :                 "KOI8R\0KOI8-R\0KOI-8R\0",
     266             :                 ONIG_ENCODING_KOI8_R
     267             :         },
     268             : #endif
     269             : #ifdef ONIG_ENCODING_ISO_8859_1
     270             :         {
     271             :                 "ISO-8859-1\0ISO8859-1\0ISO_8859_1\0ISO8859_1\0",
     272             :                 ONIG_ENCODING_ISO_8859_1
     273             :         },
     274             : #endif
     275             : #ifdef ONIG_ENCODING_ISO_8859_2
     276             :         {
     277             :                 "ISO-8859-2\0ISO8859-2\0ISO_8859_2\0ISO8859_2\0",
     278             :                 ONIG_ENCODING_ISO_8859_2
     279             :         },
     280             : #endif
     281             : #ifdef ONIG_ENCODING_ISO_8859_3
     282             :         {
     283             :                 "ISO-8859-3\0ISO8859-3\0ISO_8859_3\0ISO8859_3\0",
     284             :                 ONIG_ENCODING_ISO_8859_3
     285             :         },
     286             : #endif
     287             : #ifdef ONIG_ENCODING_ISO_8859_4
     288             :         {
     289             :                 "ISO-8859-4\0ISO8859-4\0ISO_8859_4\0ISO8859_4\0",
     290             :                 ONIG_ENCODING_ISO_8859_4
     291             :         },
     292             : #endif
     293             : #ifdef ONIG_ENCODING_ISO_8859_5
     294             :         {
     295             :                 "ISO-8859-5\0ISO8859-5\0ISO_8859_5\0ISO8859_5\0",
     296             :                 ONIG_ENCODING_ISO_8859_5
     297             :         },
     298             : #endif
     299             : #ifdef ONIG_ENCODING_ISO_8859_6
     300             :         {
     301             :                 "ISO-8859-6\0ISO8859-6\0ISO_8859_6\0ISO8859_6\0",
     302             :                 ONIG_ENCODING_ISO_8859_6
     303             :         },
     304             : #endif
     305             : #ifdef ONIG_ENCODING_ISO_8859_7
     306             :         {
     307             :                 "ISO-8859-7\0ISO8859-7\0ISO_8859_7\0ISO8859_7\0",
     308             :                 ONIG_ENCODING_ISO_8859_7
     309             :         },
     310             : #endif
     311             : #ifdef ONIG_ENCODING_ISO_8859_8
     312             :         {
     313             :                 "ISO-8859-8\0ISO8859-8\0ISO_8859_8\0ISO8859_8\0",
     314             :                 ONIG_ENCODING_ISO_8859_8
     315             :         },
     316             : #endif
     317             : #ifdef ONIG_ENCODING_ISO_8859_9
     318             :         {
     319             :                 "ISO-8859-9\0ISO8859-9\0ISO_8859_9\0ISO8859_9\0",
     320             :                 ONIG_ENCODING_ISO_8859_9
     321             :         },
     322             : #endif
     323             : #ifdef ONIG_ENCODING_ISO_8859_10
     324             :         {
     325             :                 "ISO-8859-10\0ISO8859-10\0ISO_8859_10\0ISO8859_10\0",
     326             :                 ONIG_ENCODING_ISO_8859_10
     327             :         },
     328             : #endif
     329             : #ifdef ONIG_ENCODING_ISO_8859_11
     330             :         {
     331             :                 "ISO-8859-11\0ISO8859-11\0ISO_8859_11\0ISO8859_11\0",
     332             :                 ONIG_ENCODING_ISO_8859_11
     333             :         },
     334             : #endif
     335             : #ifdef ONIG_ENCODING_ISO_8859_13
     336             :         {
     337             :                 "ISO-8859-13\0ISO8859-13\0ISO_8859_13\0ISO8859_13\0",
     338             :                 ONIG_ENCODING_ISO_8859_13
     339             :         },
     340             : #endif
     341             : #ifdef ONIG_ENCODING_ISO_8859_14
     342             :         {
     343             :                 "ISO-8859-14\0ISO8859-14\0ISO_8859_14\0ISO8859_14\0",
     344             :                 ONIG_ENCODING_ISO_8859_14
     345             :         },
     346             : #endif
     347             : #ifdef ONIG_ENCODING_ISO_8859_15
     348             :         {
     349             :                 "ISO-8859-15\0ISO8859-15\0ISO_8859_15\0ISO8859_15\0",
     350             :                 ONIG_ENCODING_ISO_8859_15
     351             :         },
     352             : #endif
     353             : #ifdef ONIG_ENCODING_ISO_8859_16
     354             :         {
     355             :                 "ISO-8859-16\0ISO8859-16\0ISO_8859_16\0ISO8859_16\0",
     356             :                 ONIG_ENCODING_ISO_8859_16
     357             :         },
     358             : #endif
     359             : #ifdef ONIG_ENCODING_ASCII
     360             :         {
     361             :                 "ASCII\0US-ASCII\0US_ASCII\0ISO646\0",
     362             :                 ONIG_ENCODING_ASCII
     363             :         },
     364             : #endif
     365             :         { NULL, ONIG_ENCODING_UNDEF }
     366             : };
     367             : /* }}} */
     368             : 
     369             : /* {{{ php_mb_regex_name2mbctype */
     370      191167 : static OnigEncoding _php_mb_regex_name2mbctype(const char *pname)
     371             : {
     372             :         const char *p;
     373             :         php_mb_regex_enc_name_map_t *mapping;
     374             : 
     375      191167 :         if (pname == NULL || !*pname) {
     376      126918 :                 return ONIG_ENCODING_UNDEF;
     377             :         }
     378             : 
     379      134511 :         for (mapping = enc_name_map; mapping->names != NULL; mapping++) {
     380      540362 :                 for (p = mapping->names; *p != '\0'; p += (strlen(p) + 1)) {
     381      470100 :                         if (strcasecmp(p, pname) == 0) {
     382       64105 :                                 return mapping->code;
     383             :                         }
     384             :                 }
     385             :         }
     386             : 
     387         144 :         return ONIG_ENCODING_UNDEF;
     388             : }
     389             : /* }}} */
     390             : 
     391             : /* {{{ php_mb_regex_mbctype2name */
     392         307 : static const char *_php_mb_regex_mbctype2name(OnigEncoding mbctype)
     393             : {
     394             :         php_mb_regex_enc_name_map_t *mapping;
     395             : 
     396        2675 :         for (mapping = enc_name_map; mapping->names != NULL; mapping++) {
     397        2675 :                 if (mapping->code == mbctype) {
     398         307 :                         return mapping->names;
     399             :                 }
     400             :         }
     401             : 
     402           0 :         return NULL;
     403             : }
     404             : /* }}} */
     405             : 
     406             : /* {{{ php_mb_regex_set_mbctype */
     407       63767 : int php_mb_regex_set_mbctype(const char *encname TSRMLS_DC)
     408             : {
     409       63767 :         OnigEncoding mbctype = _php_mb_regex_name2mbctype(encname);
     410       63767 :         if (mbctype == ONIG_ENCODING_UNDEF) {
     411       63509 :                 return FAILURE;
     412             :         }
     413         258 :         MBREX(current_mbctype) = mbctype;
     414         258 :         return SUCCESS;
     415             : }
     416             : /* }}} */
     417             : 
     418             : /* {{{ php_mb_regex_set_default_mbctype */
     419      127276 : int php_mb_regex_set_default_mbctype(const char *encname TSRMLS_DC)
     420             : {
     421      127276 :         OnigEncoding mbctype = _php_mb_regex_name2mbctype(encname);
     422      127276 :         if (mbctype == ONIG_ENCODING_UNDEF) {
     423       63509 :                 return FAILURE;
     424             :         }
     425       63767 :         MBREX(default_mbctype) = mbctype;
     426       63767 :         return SUCCESS;
     427             : }
     428             : /* }}} */
     429             : 
     430             : /* {{{ php_mb_regex_get_mbctype */
     431           0 : const char *php_mb_regex_get_mbctype(TSRMLS_D)
     432             : {
     433           0 :         return _php_mb_regex_mbctype2name(MBREX(current_mbctype));
     434             : }
     435             : /* }}} */
     436             : 
     437             : /* {{{ php_mb_regex_get_default_mbctype */
     438           0 : const char *php_mb_regex_get_default_mbctype(TSRMLS_D)
     439             : {
     440           0 :         return _php_mb_regex_mbctype2name(MBREX(default_mbctype));
     441             : }
     442             : /* }}} */
     443             : 
     444             : /*
     445             :  * regex cache
     446             :  */
     447             : /* {{{ php_mbregex_compile_pattern */
     448         413 : static php_mb_regex_t *php_mbregex_compile_pattern(const char *pattern, int patlen, OnigOptionType options, OnigEncoding enc, OnigSyntaxType *syntax TSRMLS_DC)
     449             : {
     450         413 :         int err_code = 0;
     451         413 :         int found = 0;
     452         413 :         php_mb_regex_t *retval = NULL, **rc = NULL;
     453             :         OnigErrorInfo err_info;
     454             :         OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
     455             : 
     456         413 :         found = zend_hash_find(&MBREX(ht_rc), (char *)pattern, patlen+1, (void **) &rc);
     457         639 :         if (found == FAILURE || (*rc)->options != options || (*rc)->enc != enc || (*rc)->syntax != syntax) {
     458         226 :                 if ((err_code = onig_new(&retval, (OnigUChar *)pattern, (OnigUChar *)(pattern + patlen), options, enc, syntax, &err_info)) != ONIG_NORMAL) {
     459           0 :                         onig_error_code_to_str(err_str, err_code, err_info);
     460           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex compile err: %s", err_str);
     461           0 :                         retval = NULL;
     462           0 :                         goto out;
     463             :                 }
     464         226 :                 zend_hash_update(&MBREX(ht_rc), (char *) pattern, patlen + 1, (void *) &retval, sizeof(retval), NULL);
     465         187 :         } else if (found == SUCCESS) {
     466         187 :                 retval = *rc;
     467             :         }
     468             : out:
     469         413 :         return retval; 
     470             : }
     471             : /* }}} */
     472             : 
     473             : /* {{{ _php_mb_regex_get_option_string */
     474           7 : static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionType option, OnigSyntaxType *syntax)
     475             : {
     476           7 :         size_t len_left = len;
     477           7 :         size_t len_req = 0;
     478           7 :         char *p = str;
     479             :         char c;
     480             : 
     481           7 :         if ((option & ONIG_OPTION_IGNORECASE) != 0) {
     482           0 :                 if (len_left > 0) {
     483           0 :                         --len_left;
     484           0 :                         *(p++) = 'i';
     485             :                 }
     486           0 :                 ++len_req;      
     487             :         }
     488             : 
     489           7 :         if ((option & ONIG_OPTION_EXTEND) != 0) {
     490           1 :                 if (len_left > 0) {
     491           1 :                         --len_left;
     492           1 :                         *(p++) = 'x';
     493             :                 }
     494           1 :                 ++len_req;      
     495             :         }
     496             : 
     497           7 :         if ((option & (ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE)) ==
     498             :                         (ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE)) {
     499           0 :                 if (len_left > 0) {
     500           0 :                         --len_left;
     501           0 :                         *(p++) = 'p';
     502             :                 }
     503           0 :                 ++len_req;      
     504             :         } else {
     505           7 :                 if ((option & ONIG_OPTION_MULTILINE) != 0) {
     506           1 :                         if (len_left > 0) {
     507           1 :                                 --len_left;
     508           1 :                                 *(p++) = 'm';
     509             :                         }
     510           1 :                         ++len_req;      
     511             :                 }
     512             : 
     513           7 :                 if ((option & ONIG_OPTION_SINGLELINE) != 0) {
     514           0 :                         if (len_left > 0) {
     515           0 :                                 --len_left;
     516           0 :                                 *(p++) = 's';
     517             :                         }
     518           0 :                         ++len_req;      
     519             :                 }
     520             :         }       
     521           7 :         if ((option & ONIG_OPTION_FIND_LONGEST) != 0) {
     522           0 :                 if (len_left > 0) {
     523           0 :                         --len_left;
     524           0 :                         *(p++) = 'l';
     525             :                 }
     526           0 :                 ++len_req;      
     527             :         }
     528           7 :         if ((option & ONIG_OPTION_FIND_NOT_EMPTY) != 0) {
     529           0 :                 if (len_left > 0) {
     530           0 :                         --len_left;
     531           0 :                         *(p++) = 'n';
     532             :                 }
     533           0 :                 ++len_req;      
     534             :         }
     535             : 
     536           7 :         c = 0;
     537             : 
     538           7 :         if (syntax == ONIG_SYNTAX_JAVA) {
     539           0 :                 c = 'j';
     540           7 :         } else if (syntax == ONIG_SYNTAX_GNU_REGEX) {
     541           0 :                 c = 'u';
     542           7 :         } else if (syntax == ONIG_SYNTAX_GREP) {
     543           0 :                 c = 'g';
     544           7 :         } else if (syntax == ONIG_SYNTAX_EMACS) {
     545           0 :                 c = 'c';
     546           7 :         } else if (syntax == ONIG_SYNTAX_RUBY) {
     547           7 :                 c = 'r';
     548           0 :         } else if (syntax == ONIG_SYNTAX_PERL) {
     549           0 :                 c = 'z';
     550           0 :         } else if (syntax == ONIG_SYNTAX_POSIX_BASIC) {
     551           0 :                 c = 'b';
     552           0 :         } else if (syntax == ONIG_SYNTAX_POSIX_EXTENDED) {
     553           0 :                 c = 'd';
     554             :         }
     555             : 
     556           7 :         if (c != 0) {
     557           7 :                 if (len_left > 0) {
     558           7 :                         --len_left;
     559           7 :                         *(p++) = c;
     560             :                 }
     561           7 :                 ++len_req;
     562             :         }
     563             : 
     564             : 
     565           7 :         if (len_left > 0) {
     566           7 :                 --len_left;
     567           7 :                 *(p++) = '\0';
     568             :         }
     569           7 :         ++len_req;      
     570           7 :         if (len < len_req) {
     571           0 :                 return len_req;
     572             :         }
     573             : 
     574           7 :         return 0;
     575             : }
     576             : /* }}} */
     577             : 
     578             : /* {{{ _php_mb_regex_init_options */
     579             : static void
     580         117 : _php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) 
     581             : {
     582             :         int n;
     583             :         char c;
     584         117 :         int optm = 0; 
     585             : 
     586         117 :         *syntax = ONIG_SYNTAX_RUBY;
     587             : 
     588         117 :         if (parg != NULL) {
     589         117 :                 n = 0;
     590         317 :                 while(n < narg) {
     591          83 :                         c = parg[n++];
     592          83 :                         switch (c) {
     593             :                                 case 'i':
     594           1 :                                         optm |= ONIG_OPTION_IGNORECASE;
     595           1 :                                         break;
     596             :                                 case 'x':
     597           9 :                                         optm |= ONIG_OPTION_EXTEND;
     598           9 :                                         break;
     599             :                                 case 'm':
     600           1 :                                         optm |= ONIG_OPTION_MULTILINE;
     601           1 :                                         break;
     602             :                                 case 's':
     603           0 :                                         optm |= ONIG_OPTION_SINGLELINE;
     604           0 :                                         break;
     605             :                                 case 'p':
     606           0 :                                         optm |= ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE;
     607           0 :                                         break;
     608             :                                 case 'l':
     609           0 :                                         optm |= ONIG_OPTION_FIND_LONGEST;
     610           0 :                                         break;
     611             :                                 case 'n':
     612           0 :                                         optm |= ONIG_OPTION_FIND_NOT_EMPTY;
     613           0 :                                         break;
     614             :                                 case 'j':
     615           0 :                                         *syntax = ONIG_SYNTAX_JAVA;
     616           0 :                                         break;
     617             :                                 case 'u':
     618           0 :                                         *syntax = ONIG_SYNTAX_GNU_REGEX;
     619           0 :                                         break;
     620             :                                 case 'g':
     621           0 :                                         *syntax = ONIG_SYNTAX_GREP;
     622           0 :                                         break;
     623             :                                 case 'c':
     624           0 :                                         *syntax = ONIG_SYNTAX_EMACS;
     625           0 :                                         break;
     626             :                                 case 'r':
     627           0 :                                         *syntax = ONIG_SYNTAX_RUBY;
     628           0 :                                         break;
     629             :                                 case 'z':
     630           0 :                                         *syntax = ONIG_SYNTAX_PERL;
     631           0 :                                         break;
     632             :                                 case 'b':
     633           0 :                                         *syntax = ONIG_SYNTAX_POSIX_BASIC;
     634           0 :                                         break;
     635             :                                 case 'd':
     636           0 :                                         *syntax = ONIG_SYNTAX_POSIX_EXTENDED;
     637           0 :                                         break;
     638             :                                 case 'e':
     639           1 :                                         if (eval != NULL) *eval = 1; 
     640             :                                         break;
     641             :                                 default:
     642             :                                         break;
     643             :                         }
     644             :                 }
     645         117 :                 if (option != NULL) *option|=optm; 
     646             :         }
     647         117 : }
     648             : /* }}} */
     649             : 
     650             : /*
     651             :  * php functions
     652             :  */
     653             : 
     654             : /* {{{ proto string mb_regex_encoding([string encoding])
     655             :    Returns the current encoding for regex as a string. */
     656         240 : PHP_FUNCTION(mb_regex_encoding)
     657             : {
     658         240 :         size_t argc = ZEND_NUM_ARGS();
     659             :         char *encoding;
     660             :         int encoding_len;
     661             :         OnigEncoding mbctype;
     662             : 
     663         240 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &encoding, &encoding_len) == FAILURE) {
     664           2 :                 return;
     665             :         }
     666             : 
     667         238 :         if (argc == 0) {
     668         114 :                 const char *retval = _php_mb_regex_mbctype2name(MBREX(current_mbctype));
     669             : 
     670         114 :                 if (retval == NULL) {
     671           0 :                         RETURN_FALSE;
     672             :                 }
     673             : 
     674         114 :                 RETURN_STRING((char *)retval, 1);
     675         124 :         } else if (argc == 1) {
     676         124 :                 mbctype = _php_mb_regex_name2mbctype(encoding);
     677             : 
     678         124 :                 if (mbctype == ONIG_ENCODING_UNDEF) {
     679          44 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
     680          44 :                         RETURN_FALSE;
     681             :                 }
     682             : 
     683          80 :                 MBREX(current_mbctype) = mbctype;
     684          80 :                 RETURN_TRUE;
     685             :         }
     686             : }
     687             : /* }}} */
     688             : 
     689             : /* {{{ _php_mb_regex_ereg_exec */
     690         146 : static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
     691             : {
     692             :         zval **arg_pattern, *array;
     693             :         char *string;
     694             :         int string_len;
     695             :         php_mb_regex_t *re;
     696         146 :         OnigRegion *regs = NULL;
     697             :         int i, match_len, beg, end;
     698             :         OnigOptionType options;
     699             :         char *str;
     700             : 
     701         146 :         array = NULL;
     702             : 
     703         146 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|z", &arg_pattern, &string, &string_len, &array) == FAILURE) {
     704           4 :                 RETURN_FALSE;
     705             :         }
     706             : 
     707         142 :         options = MBREX(regex_default_options);
     708         142 :         if (icase) {
     709           9 :                 options |= ONIG_OPTION_IGNORECASE;
     710             :         }
     711             : 
     712             :         /* compile the regular expression from the supplied regex */
     713         142 :         if (Z_TYPE_PP(arg_pattern) != IS_STRING) {
     714             :                 /* we convert numbers to integers and treat them as a string */
     715          34 :                 if (Z_TYPE_PP(arg_pattern) == IS_DOUBLE) {
     716          30 :                         convert_to_long_ex(arg_pattern);        /* get rid of decimal places */
     717             :                 }
     718         186 :                 convert_to_string_ex(arg_pattern);
     719             :                 /* don't bother doing an extended regex with just a number */
     720             :         }
     721             : 
     722         142 :         if (!Z_STRVAL_PP(arg_pattern) || Z_STRLEN_PP(arg_pattern) == 0) {
     723          17 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "empty pattern");
     724          17 :                 RETVAL_FALSE;
     725          17 :                 goto out;
     726             :         }
     727             : 
     728         125 :         re = php_mbregex_compile_pattern(Z_STRVAL_PP(arg_pattern), Z_STRLEN_PP(arg_pattern), options, MBREX(current_mbctype), MBREX(regex_default_syntax) TSRMLS_CC);
     729         125 :         if (re == NULL) {
     730           0 :                 RETVAL_FALSE;
     731           0 :                 goto out;
     732             :         }
     733             : 
     734         125 :         regs = onig_region_new();
     735             : 
     736             :         /* actually execute the regular expression */
     737         125 :         if (onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, (OnigUChar *)(string + string_len), regs, 0) < 0) {
     738          50 :                 RETVAL_FALSE;
     739          50 :                 goto out;
     740             :         }
     741             : 
     742          75 :         match_len = 1;
     743          75 :         str = string;
     744          75 :         if (array != NULL) {
     745          65 :                 match_len = regs->end[0] - regs->beg[0];
     746          65 :                 zval_dtor(array);
     747          65 :                 array_init(array);
     748         187 :                 for (i = 0; i < regs->num_regs; i++) {
     749         122 :                         beg = regs->beg[i];
     750         122 :                         end = regs->end[i];
     751         240 :                         if (beg >= 0 && beg < end && end <= string_len) {
     752         118 :                                 add_index_stringl(array, i, (char *)&str[beg], end - beg, 1);
     753             :                         } else {
     754           4 :                                 add_index_bool(array, i, 0);
     755             :                         }
     756             :                 }
     757             :         }
     758             : 
     759          75 :         if (match_len == 0) {
     760           4 :                 match_len = 1;
     761             :         }
     762          75 :         RETVAL_LONG(match_len);
     763             : out:
     764         142 :         if (regs != NULL) {
     765         125 :                 onig_region_free(regs, 1);
     766             :         }
     767             : }
     768             : /* }}} */
     769             : 
     770             : /* {{{ proto int mb_ereg(string pattern, string string [, array registers])
     771             :    Regular expression match for multibyte string */
     772         137 : PHP_FUNCTION(mb_ereg)
     773             : {
     774         137 :         _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     775         137 : }
     776             : /* }}} */
     777             : 
     778             : /* {{{ proto int mb_eregi(string pattern, string string [, array registers])
     779             :    Case-insensitive regular expression match for multibyte string */
     780           9 : PHP_FUNCTION(mb_eregi)
     781             : {
     782           9 :         _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     783           9 : }
     784             : /* }}} */
     785             : 
     786             : /* {{{ _php_mb_regex_ereg_replace_exec */
     787         193 : static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable)
     788             : {
     789             :         zval **arg_pattern_zval;
     790             : 
     791             :         char *arg_pattern;
     792             :         int arg_pattern_len;
     793             : 
     794             :         char *replace;
     795             :         int replace_len;
     796             : 
     797             :         zend_fcall_info arg_replace_fci;
     798             :         zend_fcall_info_cache arg_replace_fci_cache;
     799             : 
     800             :         char *string;
     801             :         int string_len;
     802             : 
     803             :         char *p;
     804             :         php_mb_regex_t *re;
     805             :         OnigSyntaxType *syntax;
     806         193 :         OnigRegion *regs = NULL;
     807         193 :         smart_str out_buf = { 0 };
     808         193 :         smart_str eval_buf = { 0 };
     809             :         smart_str *pbuf;
     810             :         int i, err, eval, n;
     811             :         OnigUChar *pos;
     812             :         OnigUChar *string_lim;
     813         193 :         char *description = NULL;
     814             :         char pat_buf[2];
     815             : 
     816             :         const mbfl_encoding *enc;
     817             : 
     818             :         {
     819             :                 const char *current_enc_name;
     820         193 :                 current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype));
     821         386 :                 if (current_enc_name == NULL ||
     822         193 :                         (enc = mbfl_name2encoding(current_enc_name)) == NULL) {
     823           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error");
     824           0 :                         RETURN_FALSE;
     825             :                 }
     826             :         }
     827         193 :         eval = 0;
     828             :         {
     829         193 :                 char *option_str = NULL;
     830         193 :                 int option_str_len = 0;
     831             : 
     832         193 :                 if (!is_callable) {
     833         192 :                         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
     834             :                                                 &arg_pattern_zval,
     835             :                                                 &replace, &replace_len,
     836             :                                                 &string, &string_len,
     837             :                                                 &option_str, &option_str_len) == FAILURE) {
     838           5 :                                 RETURN_FALSE;
     839             :                         }
     840             :                 } else {
     841           1 :                         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zfs|s",
     842             :                                                 &arg_pattern_zval,
     843             :                                                 &arg_replace_fci, &arg_replace_fci_cache,
     844             :                                                 &string, &string_len,
     845             :                                                 &option_str, &option_str_len) == FAILURE) {
     846           0 :                                 RETURN_FALSE;
     847             :                         }
     848             :                 }
     849             : 
     850         188 :                 if (option_str != NULL) {
     851          93 :                         _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval);
     852             :                 } else {
     853          95 :                         options |= MBREX(regex_default_options);
     854          95 :                         syntax = MBREX(regex_default_syntax);
     855             :                 }
     856             :         }
     857         188 :         if (Z_TYPE_PP(arg_pattern_zval) == IS_STRING) {
     858         170 :                 arg_pattern = Z_STRVAL_PP(arg_pattern_zval);
     859         170 :                 arg_pattern_len = Z_STRLEN_PP(arg_pattern_zval);
     860             :         } else {
     861             :                 /* FIXME: this code is not multibyte aware! */
     862          84 :                 convert_to_long_ex(arg_pattern_zval);
     863          18 :                 pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); 
     864          18 :                 pat_buf[1] = '\0';
     865             : 
     866          18 :                 arg_pattern = pat_buf;
     867          18 :                 arg_pattern_len = 1;    
     868             :         }
     869             :         /* create regex pattern buffer */
     870         188 :         re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax TSRMLS_CC);
     871         188 :         if (re == NULL) {
     872           0 :                 RETURN_FALSE;
     873             :         }
     874             : 
     875         190 :         if (eval || is_callable) {
     876           2 :                 pbuf = &eval_buf;
     877           2 :                 description = zend_make_compiled_string_description("mbregex replace" TSRMLS_CC);
     878             :         } else {
     879         186 :                 pbuf = &out_buf;
     880         186 :                 description = NULL;
     881             :         }
     882             : 
     883         188 :         if (is_callable) {
     884           1 :                 if (eval) {
     885           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option 'e' cannot be used with replacement callback");
     886           0 :                         RETURN_FALSE;
     887             :                 }
     888             :         }
     889             : 
     890             :         /* do the actual work */
     891         188 :         err = 0;
     892         188 :         pos = (OnigUChar *)string;
     893         188 :         string_lim = (OnigUChar*)(string + string_len);
     894         188 :         regs = onig_region_new();
     895         912 :         while (err >= 0) {
     896         537 :                 err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0);
     897         537 :                 if (err <= -2) {
     898             :                         OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
     899           0 :                         onig_error_code_to_str(err_str, err);
     900           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str);
     901           0 :                         break;
     902             :                 }
     903         537 :                 if (err >= 0) {
     904             : #if moriyoshi_0
     905             :                         if (regs->beg[0] == regs->end[0]) {
     906             :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
     907             :                                 break;
     908             :                         }
     909             : #endif
     910             :                         /* copy the part of the string before the match */
     911         350 :                         smart_str_appendl(&out_buf, pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos));
     912             : 
     913         350 :                         if (!is_callable) {
     914             :                                 /* copy replacement and backrefs */
     915         346 :                                 i = 0;
     916         346 :                                 p = replace;
     917        1728 :                                 while (i < replace_len) {
     918        1036 :                                         int fwd = (int) php_mb_mbchar_bytes_ex(p, enc);
     919        1036 :                                         n = -1;
     920        1837 :                                         if ((replace_len - i) >= 2 && fwd == 1 &&
     921         801 :                                         p[0] == '\\' && p[1] >= '0' && p[1] <= '9') {
     922          14 :                                                 n = p[1] - '0';
     923             :                                         }
     924        1049 :                                         if (n >= 0 && n < regs->num_regs) {
     925          13 :                                                 if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && regs->end[n] <= string_len) {
     926          13 :                                                         smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]);
     927             :                                                 }
     928          13 :                                                 p += 2;
     929          13 :                                                 i += 2;
     930             :                                         } else {
     931        1023 :                                                 smart_str_appendl(pbuf, p, fwd);
     932        1023 :                                                 p += fwd;
     933        1023 :                                                 i += fwd;
     934             :                                         }
     935             :                                 }
     936             :                         }
     937             :                                 
     938         350 :                         if (eval) {
     939             :                                 zval v;
     940             :                                 /* null terminate buffer */
     941           1 :                                 smart_str_0(&eval_buf);
     942             :                                 /* do eval */
     943           1 :                                 if (zend_eval_stringl(eval_buf.c, eval_buf.len, &v, description TSRMLS_CC) == FAILURE) {
     944           1 :                                         efree(description);
     945           1 :                                         php_error_docref(NULL TSRMLS_CC,E_ERROR, "Failed evaluating code: %s%s", PHP_EOL, eval_buf.c);
     946             :                                         /* zend_error() does not return in this case */
     947             :                                 }
     948             : 
     949             :                                 /* result of eval */
     950           0 :                                 convert_to_string(&v);
     951           0 :                                 smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v));
     952             :                                 /* Clean up */
     953           0 :                                 eval_buf.len = 0;
     954             :                                 zval_dtor(&v);
     955         349 :                         } else if (is_callable) {
     956             :                                 zval *retval_ptr;
     957             :                                 zval **args[1];
     958             :                                 zval *subpats;
     959             :                                 int i;
     960             :                                 
     961           4 :                                 MAKE_STD_ZVAL(subpats);
     962           4 :                                 array_init(subpats);
     963             :                                 
     964          12 :                                 for (i = 0; i < regs->num_regs; i++) {
     965           8 :                                         add_next_index_stringl(subpats, string + regs->beg[i], regs->end[i] - regs->beg[i], 1);
     966             :                                 }                               
     967             :                                 
     968           4 :                                 args[0] = &subpats;
     969             :                                 /* null terminate buffer */
     970           4 :                                 smart_str_0(&eval_buf);
     971             :                                 
     972           4 :                                 arg_replace_fci.param_count = 1;
     973           4 :                                 arg_replace_fci.params = args;
     974           4 :                                 arg_replace_fci.retval_ptr_ptr = &retval_ptr;
     975           8 :                                 if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr) {
     976           4 :                                         convert_to_string_ex(&retval_ptr);
     977           4 :                                         smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
     978           4 :                                         eval_buf.len = 0;
     979           4 :                                         zval_ptr_dtor(&retval_ptr);
     980             :                                 } else {
     981           0 :                                         efree(description);
     982           0 :                                         if (!EG(exception)) {
     983           0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function");
     984             :                                         }
     985             :                                 }
     986           4 :                                 zval_ptr_dtor(&subpats);
     987             :                         }
     988             : 
     989         349 :                         n = regs->end[0];
     990         349 :                         if ((pos - (OnigUChar *)string) < n) {
     991         323 :                                 pos = (OnigUChar *)string + n;
     992             :                         } else {
     993          26 :                                 if (pos < string_lim) {
     994          21 :                                         smart_str_appendl(&out_buf, pos, 1); 
     995             :                                 }
     996          26 :                                 pos++;
     997             :                         }
     998             :                 } else { /* nomatch */
     999             :                         /* stick that last bit of string on our output */
    1000         187 :                         if (string_lim - pos > 0) {
    1001         135 :                                 smart_str_appendl(&out_buf, pos, string_lim - pos);
    1002             :                         }
    1003             :                 }
    1004         536 :                 onig_region_free(regs, 0);
    1005             :         }
    1006             : 
    1007         187 :         if (description) {
    1008           1 :                 efree(description);
    1009             :         }
    1010         187 :         if (regs != NULL) {
    1011         187 :                 onig_region_free(regs, 1);
    1012             :         }
    1013         187 :         smart_str_free(&eval_buf);
    1014             : 
    1015         187 :         if (err <= -2) {
    1016           0 :                 smart_str_free(&out_buf);   
    1017           0 :                 RETVAL_FALSE;
    1018             :         } else {
    1019         187 :                 smart_str_appendc(&out_buf, '\0');
    1020         187 :                 RETVAL_STRINGL((char *)out_buf.c, out_buf.len - 1, 0);
    1021             :         }
    1022             : }
    1023             : /* }}} */
    1024             : 
    1025             : /* {{{ proto string mb_ereg_replace(string pattern, string replacement, string string [, string option])
    1026             :    Replace regular expression for multibyte string */
    1027         126 : PHP_FUNCTION(mb_ereg_replace)
    1028             : {
    1029         126 :         _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
    1030         125 : }
    1031             : /* }}} */
    1032             : 
    1033             : /* {{{ proto string mb_eregi_replace(string pattern, string replacement, string string)
    1034             :    Case insensitive replace regular expression for multibyte string */
    1035          66 : PHP_FUNCTION(mb_eregi_replace)
    1036             : {
    1037          66 :         _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE, 0);
    1038          66 : }
    1039             : /* }}} */
    1040             : 
    1041             : /* {{{ proto string mb_ereg_replace_callback(string pattern, string callback, string string [, string option])
    1042             :     regular expression for multibyte string using replacement callback */
    1043           1 : PHP_FUNCTION(mb_ereg_replace_callback)
    1044             : {
    1045           1 :         _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
    1046           1 : }
    1047             : /* }}} */
    1048             : 
    1049             : /* {{{ proto array mb_split(string pattern, string string [, int limit])
    1050             :    split multibyte string into array by regular expression */
    1051          88 : PHP_FUNCTION(mb_split)
    1052             : {
    1053             :         char *arg_pattern;
    1054             :         int arg_pattern_len;
    1055             :         php_mb_regex_t *re;
    1056          88 :         OnigRegion *regs = NULL;
    1057             :         char *string;
    1058             :         OnigUChar *pos, *chunk_pos;
    1059             :         int string_len;
    1060             : 
    1061             :         int n, err;
    1062          88 :         long count = -1;
    1063             : 
    1064          88 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &arg_pattern, &arg_pattern_len, &string, &string_len, &count) == FAILURE) {
    1065          11 :                 RETURN_FALSE;
    1066             :         } 
    1067             : 
    1068          77 :         if (count > 0) {
    1069          60 :                 count--;
    1070             :         }
    1071             : 
    1072             :         /* create regex pattern buffer */
    1073          77 :         if ((re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, MBREX(regex_default_options), MBREX(current_mbctype), MBREX(regex_default_syntax) TSRMLS_CC)) == NULL) {
    1074           0 :                 RETURN_FALSE;
    1075             :         }
    1076             : 
    1077          77 :         array_init(return_value);
    1078             : 
    1079          77 :         chunk_pos = pos = (OnigUChar *)string;
    1080          77 :         err = 0;
    1081          77 :         regs = onig_region_new();
    1082             :         /* churn through str, generating array entries as we go */
    1083         335 :         while (count != 0 && (pos - (OnigUChar *)string) < string_len) {
    1084             :                 int beg, end;
    1085         214 :                 err = onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), pos, (OnigUChar *)(string + string_len), regs, 0);
    1086         214 :                 if (err < 0) {
    1087          33 :                         break;
    1088             :                 }
    1089         181 :                 beg = regs->beg[0], end = regs->end[0];
    1090             :                 /* add it to the array */
    1091         181 :                 if ((pos - (OnigUChar *)string) < end) {
    1092         148 :                         if (beg < string_len && beg >= (chunk_pos - (OnigUChar *)string)) {
    1093          74 :                                 add_next_index_stringl(return_value, (char *)chunk_pos, ((OnigUChar *)(string + beg) - chunk_pos), 1);
    1094          74 :                                 --count;
    1095             :                         } else {
    1096           0 :                                 err = -2;
    1097           0 :                                 break;
    1098             :                         }
    1099             :                         /* point at our new starting point */
    1100          74 :                         chunk_pos = pos = (OnigUChar *)string + end;
    1101             :                 } else {
    1102         107 :                         pos++;
    1103             :                 }
    1104         181 :                 onig_region_free(regs, 0);
    1105             :         }
    1106             : 
    1107          77 :         onig_region_free(regs, 1);
    1108             : 
    1109             :         /* see if we encountered an error */
    1110          77 :         if (err <= -2) {
    1111             :                 OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
    1112           0 :                 onig_error_code_to_str(err_str, err);
    1113           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in mbsplit(): %s", err_str);
    1114             :                 zval_dtor(return_value);
    1115           0 :                 RETURN_FALSE;
    1116             :         }
    1117             : 
    1118             :         /* otherwise we just have one last element to add to the array */
    1119          77 :         n = ((OnigUChar *)(string + string_len) - chunk_pos);
    1120          77 :         if (n > 0) {
    1121          62 :                 add_next_index_stringl(return_value, (char *)chunk_pos, n, 1);
    1122             :         } else {
    1123          15 :                 add_next_index_stringl(return_value, "", 0, 1);
    1124             :         }
    1125             : }
    1126             : /* }}} */
    1127             : 
    1128             : /* {{{ proto bool mb_ereg_match(string pattern, string string [,string option])
    1129             :    Regular expression match for multibyte string */
    1130           7 : PHP_FUNCTION(mb_ereg_match)
    1131             : {
    1132             :         char *arg_pattern;
    1133             :         int arg_pattern_len;
    1134             : 
    1135             :         char *string;
    1136             :         int string_len;
    1137             : 
    1138             :         php_mb_regex_t *re;
    1139             :         OnigSyntaxType *syntax;
    1140           7 :         OnigOptionType option = 0;
    1141             :         int err;
    1142             : 
    1143             :         {
    1144           7 :                 char *option_str = NULL;
    1145           7 :                 int option_str_len = 0;
    1146             : 
    1147           7 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s",
    1148             :                                           &arg_pattern, &arg_pattern_len, &string, &string_len,
    1149             :                                           &option_str, &option_str_len)==FAILURE) {
    1150           3 :                         RETURN_FALSE;
    1151             :                 }
    1152             : 
    1153           4 :                 if (option_str != NULL) {
    1154           1 :                         _php_mb_regex_init_options(option_str, option_str_len, &option, &syntax, NULL);
    1155             :                 } else {
    1156           3 :                         option |= MBREX(regex_default_options);
    1157           3 :                         syntax = MBREX(regex_default_syntax);
    1158             :                 }
    1159             :         }
    1160             : 
    1161           4 :         if ((re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), syntax TSRMLS_CC)) == NULL) {
    1162           0 :                 RETURN_FALSE;
    1163             :         }
    1164             : 
    1165             :         /* match */
    1166           4 :         err = onig_match(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, NULL, 0);
    1167           4 :         if (err >= 0) {
    1168           2 :                 RETVAL_TRUE;
    1169             :         } else {
    1170           2 :                 RETVAL_FALSE;
    1171             :         }
    1172             : }
    1173             : /* }}} */
    1174             : 
    1175             : /* regex search */
    1176             : /* {{{ _php_mb_regex_ereg_search_exec */
    1177             : static void
    1178          69 : _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAMETERS, int mode)
    1179             : {
    1180          69 :         size_t argc = ZEND_NUM_ARGS();
    1181             :         char *arg_pattern, *arg_options;
    1182             :         int arg_pattern_len, arg_options_len;
    1183             :         int n, i, err, pos, len, beg, end;
    1184             :         OnigOptionType option;
    1185             :         OnigUChar *str;
    1186             :         OnigSyntaxType *syntax;
    1187             : 
    1188          69 :         if (zend_parse_parameters(argc TSRMLS_CC, "|ss", &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) {
    1189           0 :                 return;
    1190             :         }
    1191             : 
    1192          69 :         option = MBREX(regex_default_options);
    1193             : 
    1194          69 :         if (argc == 2) {
    1195           0 :                 option = 0;
    1196           0 :                 _php_mb_regex_init_options(arg_options, arg_options_len, &option, &syntax, NULL);
    1197             :         }
    1198             : 
    1199          69 :         if (argc > 0) {
    1200             :                 /* create regex pattern buffer */
    1201           2 :                 if ((MBREX(search_re) = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), MBREX(regex_default_syntax) TSRMLS_CC)) == NULL) {
    1202           0 :                         RETURN_FALSE;
    1203             :                 }
    1204             :         }
    1205             : 
    1206          69 :         pos = MBREX(search_pos);
    1207          69 :         str = NULL;
    1208          69 :         len = 0;
    1209          69 :         if (MBREX(search_str) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING){
    1210          68 :                 str = (OnigUChar *)Z_STRVAL_P(MBREX(search_str));
    1211          68 :                 len = Z_STRLEN_P(MBREX(search_str));
    1212             :         }
    1213             : 
    1214          69 :         if (MBREX(search_re) == NULL) {
    1215           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No regex given");
    1216           1 :                 RETURN_FALSE;
    1217             :         }
    1218             : 
    1219          68 :         if (str == NULL) {
    1220           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No string given");
    1221           0 :                 RETURN_FALSE;
    1222             :         }
    1223             : 
    1224          68 :         if (MBREX(search_regs)) {
    1225          49 :                 onig_region_free(MBREX(search_regs), 1);
    1226             :         }
    1227          68 :         MBREX(search_regs) = onig_region_new();
    1228             : 
    1229          68 :         err = onig_search(MBREX(search_re), str, str + len, str + pos, str  + len, MBREX(search_regs), 0);
    1230          68 :         if (err == ONIG_MISMATCH) {
    1231          17 :                 MBREX(search_pos) = len;
    1232          17 :                 RETVAL_FALSE;
    1233          51 :         } else if (err <= -2) {
    1234             :                 OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
    1235           0 :                 onig_error_code_to_str(err_str, err);
    1236           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in mbregex_search(): %s", err_str);
    1237           0 :                 RETVAL_FALSE;
    1238             :         } else {
    1239          51 :                 if (MBREX(search_regs)->beg[0] == MBREX(search_regs)->end[0]) {
    1240           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
    1241             :                 }
    1242          51 :                 switch (mode) {
    1243             :                 case 1:
    1244          45 :                         array_init(return_value);
    1245          45 :                         beg = MBREX(search_regs)->beg[0];
    1246          45 :                         end = MBREX(search_regs)->end[0];
    1247          45 :                         add_next_index_long(return_value, beg);
    1248          45 :                         add_next_index_long(return_value, end - beg);
    1249          45 :                         break;
    1250             :                 case 2:
    1251           5 :                         array_init(return_value);
    1252           5 :                         n = MBREX(search_regs)->num_regs;
    1253          10 :                         for (i = 0; i < n; i++) {
    1254           5 :                                 beg = MBREX(search_regs)->beg[i];
    1255           5 :                                 end = MBREX(search_regs)->end[i];
    1256          10 :                                 if (beg >= 0 && beg <= end && end <= len) {
    1257           5 :                                         add_index_stringl(return_value, i, (char *)&str[beg], end - beg, 1);
    1258             :                                 } else {
    1259           0 :                                         add_index_bool(return_value, i, 0);
    1260             :                                 }
    1261             :                         }
    1262           5 :                         break;
    1263             :                 default:
    1264           1 :                         RETVAL_TRUE;
    1265             :                         break;
    1266             :                 }
    1267          51 :                 end = MBREX(search_regs)->end[0];
    1268          51 :                 if (pos < end) {
    1269          51 :                         MBREX(search_pos) = end;
    1270             :                 } else {
    1271           0 :                         MBREX(search_pos) = pos + 1;
    1272             :                 }
    1273             :         }
    1274             : 
    1275          68 :         if (err < 0) {
    1276          17 :                 onig_region_free(MBREX(search_regs), 1);
    1277          17 :                 MBREX(search_regs) = (OnigRegion *)NULL;
    1278             :         }
    1279             : }
    1280             : /* }}} */
    1281             : 
    1282             : /* {{{ proto bool mb_ereg_search([string pattern[, string option]])
    1283             :    Regular expression search for multibyte string */
    1284           1 : PHP_FUNCTION(mb_ereg_search)
    1285             : {
    1286           1 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1287           1 : }
    1288             : /* }}} */
    1289             : 
    1290             : /* {{{ proto array mb_ereg_search_pos([string pattern[, string option]])
    1291             :    Regular expression search for multibyte string */
    1292          61 : PHP_FUNCTION(mb_ereg_search_pos)
    1293             : {
    1294          61 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1295          61 : }
    1296             : /* }}} */
    1297             : 
    1298             : /* {{{ proto array mb_ereg_search_regs([string pattern[, string option]])
    1299             :    Regular expression search for multibyte string */
    1300           7 : PHP_FUNCTION(mb_ereg_search_regs)
    1301             : {
    1302           7 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
    1303           7 : }
    1304             : /* }}} */
    1305             : 
    1306             : /* {{{ proto bool mb_ereg_search_init(string string [, string pattern[, string option]])
    1307             :    Initialize string and regular expression for search. */
    1308          23 : PHP_FUNCTION(mb_ereg_search_init)
    1309             : {
    1310          23 :         size_t argc = ZEND_NUM_ARGS();
    1311             :         zval *arg_str;
    1312          23 :         char *arg_pattern = NULL, *arg_options = NULL;
    1313          23 :         int arg_pattern_len = 0, arg_options_len = 0;
    1314          23 :         OnigSyntaxType *syntax = NULL;
    1315             :         OnigOptionType option;
    1316             : 
    1317          23 :         if (zend_parse_parameters(argc TSRMLS_CC, "z|ss", &arg_str, &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) {
    1318           3 :                 return;
    1319             :         }
    1320             :         
    1321          20 :         if (argc > 1 && arg_pattern_len == 0) {
    1322           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty pattern");
    1323           1 :                 RETURN_FALSE;
    1324             :         }
    1325             : 
    1326          19 :         option = MBREX(regex_default_options);
    1327          19 :         syntax = MBREX(regex_default_syntax);
    1328             : 
    1329          19 :         if (argc == 3) {
    1330          16 :                 option = 0;
    1331          16 :                 _php_mb_regex_init_options(arg_options, arg_options_len, &option, &syntax, NULL);
    1332             :         }
    1333             : 
    1334          19 :         if (argc > 1) {
    1335             :                 /* create regex pattern buffer */
    1336          17 :                 if ((MBREX(search_re) = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), syntax TSRMLS_CC)) == NULL) {
    1337           0 :                         RETURN_FALSE;
    1338             :                 }
    1339             :         }
    1340             : 
    1341          19 :         if (MBREX(search_str) != NULL) {
    1342          15 :                 zval_ptr_dtor(&MBREX(search_str));
    1343          15 :                 MBREX(search_str) = (zval *)NULL;
    1344             :         }
    1345             : 
    1346          19 :         MBREX(search_str) = arg_str;
    1347          19 :         Z_ADDREF_P(MBREX(search_str));
    1348          95 :         SEPARATE_ZVAL_IF_NOT_REF(&MBREX(search_str));
    1349             : 
    1350          19 :         MBREX(search_pos) = 0;
    1351             : 
    1352          19 :         if (MBREX(search_regs) != NULL) {
    1353           0 :                 onig_region_free(MBREX(search_regs), 1);
    1354           0 :                 MBREX(search_regs) = (OnigRegion *) NULL;
    1355             :         }
    1356             : 
    1357          19 :         RETURN_TRUE;
    1358             : }
    1359             : /* }}} */
    1360             : 
    1361             : /* {{{ proto array mb_ereg_search_getregs(void)
    1362             :    Get matched substring of the last time */
    1363          45 : PHP_FUNCTION(mb_ereg_search_getregs)
    1364             : {
    1365             :         int n, i, len, beg, end;
    1366             :         OnigUChar *str;
    1367             : 
    1368          90 :         if (MBREX(search_regs) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING && Z_STRVAL_P(MBREX(search_str)) != NULL) {
    1369          45 :                 array_init(return_value);
    1370             : 
    1371          45 :                 str = (OnigUChar *)Z_STRVAL_P(MBREX(search_str));
    1372          45 :                 len = Z_STRLEN_P(MBREX(search_str));
    1373          45 :                 n = MBREX(search_regs)->num_regs;
    1374         134 :                 for (i = 0; i < n; i++) {
    1375          89 :                         beg = MBREX(search_regs)->beg[i];
    1376          89 :                         end = MBREX(search_regs)->end[i];
    1377         178 :                         if (beg >= 0 && beg <= end && end <= len) {
    1378          89 :                                 add_index_stringl(return_value, i, (char *)&str[beg], end - beg, 1);
    1379             :                         } else {
    1380           0 :                                 add_index_bool(return_value, i, 0);
    1381             :                         }
    1382             :                 }
    1383             :         } else {
    1384           0 :                 RETVAL_FALSE;
    1385             :         }
    1386          45 : }
    1387             : /* }}} */
    1388             : 
    1389             : /* {{{ proto int mb_ereg_search_getpos(void)
    1390             :    Get search start position */
    1391          44 : PHP_FUNCTION(mb_ereg_search_getpos)
    1392             : {
    1393          44 :         RETVAL_LONG(MBREX(search_pos));
    1394          44 : }
    1395             : /* }}} */
    1396             : 
    1397             : /* {{{ proto bool mb_ereg_search_setpos(int position)
    1398             :    Set search start position */
    1399           0 : PHP_FUNCTION(mb_ereg_search_setpos)
    1400             : {
    1401             :         long position;
    1402             : 
    1403           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &position) == FAILURE) {
    1404           0 :                 return;
    1405             :         }
    1406             : 
    1407           0 :         if (position < 0 || (MBREX(search_str) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING && position >= Z_STRLEN_P(MBREX(search_str)))) {
    1408           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Position is out of range");
    1409           0 :                 MBREX(search_pos) = 0;
    1410           0 :                 RETURN_FALSE;
    1411             :         }
    1412             : 
    1413           0 :         MBREX(search_pos) = position;
    1414           0 :         RETURN_TRUE;
    1415             : }
    1416             : /* }}} */
    1417             : 
    1418             : /* {{{ php_mb_regex_set_options */
    1419           7 : static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) 
    1420             : {
    1421           7 :         if (prev_options != NULL) {
    1422           0 :                 *prev_options = MBREX(regex_default_options);
    1423             :         }
    1424           7 :         if (prev_syntax != NULL) {
    1425           0 :                 *prev_syntax = MBREX(regex_default_syntax);
    1426             :         }
    1427           7 :         MBREX(regex_default_options) = options;
    1428           7 :         MBREX(regex_default_syntax) = syntax;
    1429           7 : }
    1430             : /* }}} */
    1431             : 
    1432             : /* {{{ proto string mb_regex_set_options([string options])
    1433             :    Set or get the default options for mbregex functions */
    1434           7 : PHP_FUNCTION(mb_regex_set_options)
    1435             : {
    1436             :         OnigOptionType opt;
    1437             :         OnigSyntaxType *syntax;
    1438           7 :         char *string = NULL;
    1439             :         int string_len;
    1440             :         char buf[16];
    1441             : 
    1442           7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
    1443             :                                   &string, &string_len) == FAILURE) {
    1444           0 :                 RETURN_FALSE;
    1445             :         }
    1446           7 :         if (string != NULL) {
    1447           7 :                 opt = 0;
    1448           7 :                 syntax = NULL;
    1449           7 :                 _php_mb_regex_init_options(string, string_len, &opt, &syntax, NULL);
    1450           7 :                 _php_mb_regex_set_options(opt, syntax, NULL, NULL TSRMLS_CC);
    1451             :         } else {
    1452           0 :                 opt = MBREX(regex_default_options);
    1453           0 :                 syntax = MBREX(regex_default_syntax);
    1454             :         }
    1455           7 :         _php_mb_regex_get_option_string(buf, sizeof(buf), opt, syntax);
    1456             : 
    1457           7 :         RETVAL_STRING(buf, 1);
    1458             : }
    1459             : /* }}} */
    1460             : 
    1461             : #endif  /* HAVE_MBREGEX */
    1462             : 
    1463             : /*
    1464             :  * Local variables:
    1465             :  * tab-width: 4
    1466             :  * c-basic-offset: 4
    1467             :  * End:
    1468             :  * vim600: fdm=marker
    1469             :  * vim: noet sw=4 ts=4
    1470             :  */

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:12 +0000 (6 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.