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

LTP GCOV extension - code coverage report
Current view: directory - mbstring - php_mbregex.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 563
Code covered: 76.7 % Executed lines: 432
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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: php_mbregex.c 281727 2009-06-05 18:50:32Z mattwil $ */
      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                 : static void php_mb_regex_free_cache(php_mb_regex_t **pre) 
      59             223 : {
      60             223 :         onig_free(*pre);
      61             223 : }
      62                 : /* }}} */
      63                 : 
      64                 : /* {{{ _php_mb_regex_globals_ctor */
      65                 : static int _php_mb_regex_globals_ctor(zend_mb_regex_globals *pglobals TSRMLS_DC)
      66           17633 : {
      67           17633 :         pglobals->default_mbctype = ONIG_ENCODING_EUC_JP;
      68           17633 :         pglobals->current_mbctype = ONIG_ENCODING_EUC_JP;
      69           17633 :         zend_hash_init(&(pglobals->ht_rc), 0, NULL, (void (*)(void *)) php_mb_regex_free_cache, 1);
      70           17633 :         pglobals->search_str = (zval*) NULL;
      71           17633 :         pglobals->search_re = (php_mb_regex_t*)NULL;
      72           17633 :         pglobals->search_pos = 0;
      73           17633 :         pglobals->search_regs = (OnigRegion*)NULL;
      74           17633 :         pglobals->regex_default_options = ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE;
      75           17633 :         pglobals->regex_default_syntax = ONIG_SYNTAX_RUBY;
      76           17633 :         return SUCCESS;
      77                 : }
      78                 : /* }}} */
      79                 : 
      80                 : /* {{{ _php_mb_regex_globals_dtor */
      81                 : static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) 
      82           17665 : {
      83           17665 :         zend_hash_destroy(&pglobals->ht_rc);
      84           17665 : }
      85                 : /* }}} */
      86                 : 
      87                 : /* {{{ php_mb_regex_globals_alloc */
      88                 : zend_mb_regex_globals *php_mb_regex_globals_alloc(TSRMLS_D)
      89           17633 : {
      90           17633 :         zend_mb_regex_globals *pglobals = pemalloc(
      91                 :                         sizeof(zend_mb_regex_globals), 1);
      92           17633 :         if (!pglobals) {
      93               0 :                 return NULL;
      94                 :         }
      95           17633 :         if (SUCCESS != _php_mb_regex_globals_ctor(pglobals TSRMLS_CC)) {
      96               0 :                 pefree(pglobals, 1);
      97               0 :                 return NULL;
      98                 :         }
      99           17633 :         return pglobals;
     100                 : }
     101                 : /* }}} */
     102                 : 
     103                 : /* {{{ php_mb_regex_globals_free */
     104                 : void php_mb_regex_globals_free(zend_mb_regex_globals *pglobals TSRMLS_DC)
     105           17665 : {
     106           17665 :         if (!pglobals) {
     107               0 :                 return;
     108                 :         }
     109           17665 :         _php_mb_regex_globals_dtor(pglobals TSRMLS_CC);
     110           17665 :         pefree(pglobals, 1);
     111                 : }
     112                 : /* }}} */
     113                 : 
     114                 : /* {{{ PHP_MINIT_FUNCTION(mb_regex) */
     115                 : PHP_MINIT_FUNCTION(mb_regex)
     116           17633 : {
     117           17633 :         onig_init();
     118           17633 :         return SUCCESS;
     119                 : }
     120                 : /* }}} */
     121                 : 
     122                 : /* {{{ PHP_MSHUTDOWN_FUNCTION(mb_regex) */
     123                 : PHP_MSHUTDOWN_FUNCTION(mb_regex)
     124           17665 : {
     125           17665 :         onig_end();
     126           17665 :         return SUCCESS;
     127                 : }
     128                 : /* }}} */
     129                 : 
     130                 : /* {{{ PHP_RINIT_FUNCTION(mb_regex) */
     131                 : PHP_RINIT_FUNCTION(mb_regex)
     132           17619 : {
     133           17619 :         return MBSTRG(mb_regex_globals) ? SUCCESS: FAILURE;
     134                 : }
     135                 : /* }}} */
     136                 : 
     137                 : /* {{{ PHP_RSHUTDOWN_FUNCTION(mb_regex) */
     138                 : PHP_RSHUTDOWN_FUNCTION(mb_regex)
     139           17651 : {
     140           17651 :         MBREX(current_mbctype) = MBREX(default_mbctype);
     141                 : 
     142           17651 :         if (MBREX(search_str) != NULL) {
     143               4 :                 zval_ptr_dtor(&MBREX(search_str));
     144               4 :                 MBREX(search_str) = (zval *)NULL;
     145                 :         }
     146           17651 :         MBREX(search_pos) = 0;
     147                 : 
     148           17651 :         if (MBREX(search_regs) != NULL) {
     149               2 :                 onig_region_free(MBREX(search_regs), 1);
     150               2 :                 MBREX(search_regs) = (OnigRegion *)NULL;
     151                 :         }
     152           17651 :         zend_hash_clean(&MBREX(ht_rc));
     153                 : 
     154           17651 :         return SUCCESS;
     155                 : }
     156                 : /* }}} */
     157                 : 
     158                 : /* {{{ PHP_MINFO_FUNCTION(mb_regex) */
     159                 : PHP_MINFO_FUNCTION(mb_regex)
     160              42 : {
     161                 :         char buf[32];
     162              42 :         php_info_print_table_start();
     163              42 :         php_info_print_table_row(2, "Multibyte (japanese) regex support", "enabled");
     164              42 :         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              42 :         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              42 :         php_info_print_table_row(2, "Multibyte regex (oniguruma) version", buf);
     176              42 :         php_info_print_table_end();
     177              42 : }
     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                 : static OnigEncoding _php_mb_regex_name2mbctype(const char *pname)
     371          158653 : {
     372                 :         const char *p;
     373                 :         php_mb_regex_enc_name_map_t *mapping;
     374                 : 
     375          158653 :         if (pname == NULL) {
     376           35102 :                 return ONIG_ENCODING_UNDEF;
     377                 :         }
     378                 : 
     379         2165624 :         for (mapping = enc_name_map; mapping->names != NULL; mapping++) {
     380         9629969 :                 for (p = mapping->names; *p != '\0'; p += (strlen(p) + 1)) {
     381         7587896 :                         if (strcasecmp(p, pname) == 0) {
     382           53195 :                                 return mapping->code;
     383                 :                         }
     384                 :                 }
     385                 :         }
     386                 : 
     387           70356 :         return ONIG_ENCODING_UNDEF;
     388                 : }
     389                 : /* }}} */
     390                 : 
     391                 : /* {{{ php_mb_regex_mbctype2name */
     392                 : static const char *_php_mb_regex_mbctype2name(OnigEncoding mbctype)
     393             306 : {
     394                 :         php_mb_regex_enc_name_map_t *mapping;
     395                 : 
     396            1695 :         for (mapping = enc_name_map; mapping->names != NULL; mapping++) {
     397            1695 :                 if (mapping->code == mbctype) {
     398             306 :                         return mapping->names;
     399                 :                 }
     400                 :         }
     401                 : 
     402               0 :         return NULL;
     403                 : }
     404                 : /* }}} */
     405                 : 
     406                 : /* {{{ php_mb_regex_set_mbctype */
     407                 : int php_mb_regex_set_mbctype(const char *encname TSRMLS_DC)
     408           52912 : {
     409           52912 :         OnigEncoding mbctype = _php_mb_regex_name2mbctype(encname);
     410           52912 :         if (mbctype == ONIG_ENCODING_UNDEF) {
     411           52707 :                 return FAILURE;
     412                 :         }
     413             205 :         MBREX(current_mbctype) = mbctype;
     414             205 :         return SUCCESS;
     415                 : }
     416                 : /* }}} */
     417                 : 
     418                 : /* {{{ php_mb_regex_set_default_mbctype */
     419                 : int php_mb_regex_set_default_mbctype(const char *encname TSRMLS_DC)
     420          105619 : {
     421          105619 :         OnigEncoding mbctype = _php_mb_regex_name2mbctype(encname);
     422          105619 :         if (mbctype == ONIG_ENCODING_UNDEF) {
     423           52707 :                 return FAILURE;
     424                 :         }
     425           52912 :         MBREX(default_mbctype) = mbctype;
     426           52912 :         return SUCCESS;
     427                 : }
     428                 : /* }}} */
     429                 : 
     430                 : /* {{{ php_mb_regex_get_mbctype */
     431                 : const char *php_mb_regex_get_mbctype(TSRMLS_D)
     432               0 : {
     433               0 :         return _php_mb_regex_mbctype2name(MBREX(current_mbctype));
     434                 : }
     435                 : /* }}} */
     436                 : 
     437                 : /* {{{ php_mb_regex_get_default_mbctype */
     438                 : const char *php_mb_regex_get_default_mbctype(TSRMLS_D)
     439               0 : {
     440               0 :         return _php_mb_regex_mbctype2name(MBREX(default_mbctype));
     441                 : }
     442                 : /* }}} */
     443                 : 
     444                 : /*
     445                 :  * regex cache
     446                 :  */
     447                 : /* {{{ php_mbregex_compile_pattern */
     448                 : static php_mb_regex_t *php_mbregex_compile_pattern(const char *pattern, int patlen, OnigOptionType options, OnigEncoding enc, OnigSyntaxType *syntax TSRMLS_DC)
     449             410 : {
     450             410 :         int err_code = 0;
     451             410 :         int found = 0;
     452             410 :         php_mb_regex_t *retval = NULL, **rc = NULL;
     453                 :         OnigErrorInfo err_info;
     454                 :         OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
     455                 : 
     456             410 :         found = zend_hash_find(&MBREX(ht_rc), (char *)pattern, patlen+1, (void **) &rc);
     457             633 :         if (found == FAILURE || (*rc)->options != options || (*rc)->enc != enc || (*rc)->syntax != syntax) {
     458             223 :                 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             223 :                 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             410 : out:
     469             410 :         return retval; 
     470                 : }
     471                 : /* }}} */
     472                 : 
     473                 : /* {{{ _php_mb_regex_get_option_string */
     474                 : static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionType option, OnigSyntaxType *syntax)
     475               6 : {
     476               6 :         size_t len_left = len;
     477               6 :         size_t len_req = 0;
     478               6 :         char *p = str;
     479                 :         char c;
     480                 : 
     481               6 :         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               6 :         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               6 :         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               6 :                 if ((option & ONIG_OPTION_MULTILINE) != 0) {
     506               0 :                         if (len_left > 0) {
     507               0 :                                 --len_left;
     508               0 :                                 *(p++) = 'm';
     509                 :                         }
     510               0 :                         ++len_req;      
     511                 :                 }
     512                 : 
     513               6 :                 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               6 :         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               6 :         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               6 :         c = 0;
     537                 : 
     538               6 :         if (syntax == ONIG_SYNTAX_JAVA) {
     539               0 :                 c = 'j';
     540               6 :         } else if (syntax == ONIG_SYNTAX_GNU_REGEX) {
     541               0 :                 c = 'u';
     542               6 :         } else if (syntax == ONIG_SYNTAX_GREP) {
     543               0 :                 c = 'g';
     544               6 :         } else if (syntax == ONIG_SYNTAX_EMACS) {
     545               0 :                 c = 'c';
     546               6 :         } else if (syntax == ONIG_SYNTAX_RUBY) {
     547               6 :                 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               6 :         if (c != 0) {
     557               6 :                 if (len_left > 0) {
     558               6 :                         --len_left;
     559               6 :                         *(p++) = c;
     560                 :                 }
     561               6 :                 ++len_req;
     562                 :         }
     563                 : 
     564                 : 
     565               6 :         if (len_left > 0) {
     566               6 :                 --len_left;
     567               6 :                 *(p++) = '\0';
     568                 :         }
     569               6 :         ++len_req;      
     570               6 :         if (len < len_req) {
     571               0 :                 return len_req;
     572                 :         }
     573                 : 
     574               6 :         return 0;
     575                 : }
     576                 : /* }}} */
     577                 : 
     578                 : /* {{{ _php_mb_regex_init_options */
     579                 : static void
     580                 : _php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) 
     581             116 : {
     582                 :         int n;
     583                 :         char c;
     584             116 :         int optm = 0; 
     585                 : 
     586             116 :         *syntax = ONIG_SYNTAX_RUBY;
     587                 : 
     588             116 :         if (parg != NULL) {
     589             116 :                 n = 0;
     590             314 :                 while(n < narg) {
     591              82 :                         c = parg[n++];
     592              82 :                         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               0 :                                         optm |= ONIG_OPTION_MULTILINE;
     601               0 :                                         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             116 :                 if (option != NULL) *option|=optm; 
     646                 :         }
     647             116 : }
     648                 : /* }}} */
     649                 : 
     650                 : /*
     651                 :  * php funcions
     652                 :  */
     653                 : 
     654                 : /* {{{ proto string mb_regex_encoding([string encoding])
     655                 :    Returns the current encoding for regex as a string. */
     656                 : PHP_FUNCTION(mb_regex_encoding)
     657             238 : {
     658             238 :         size_t argc = ZEND_NUM_ARGS();
     659                 :         char *encoding;
     660                 :         int encoding_len;
     661                 :         OnigEncoding mbctype;
     662                 : 
     663             238 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &encoding, &encoding_len) == FAILURE) {
     664               2 :                 return;
     665                 :         }
     666                 : 
     667             236 :         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             122 :         } else if (argc == 1) {
     676             122 :                 mbctype = _php_mb_regex_name2mbctype(encoding);
     677                 : 
     678             122 :                 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              78 :                 MBREX(current_mbctype) = mbctype;
     684              78 :                 RETURN_TRUE;
     685                 :         }
     686                 : }
     687                 : /* }}} */
     688                 : 
     689                 : /* {{{ _php_mb_regex_ereg_exec */
     690                 : static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
     691             146 : {
     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               5 :                         convert_to_long_ex(arg_pattern);        /* get rid of decimal places */
     717                 :                 }
     718              34 :                 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             142 : 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                 : PHP_FUNCTION(mb_ereg)
     773             137 : {
     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                 : PHP_FUNCTION(mb_eregi)
     781               9 : {
     782               9 :         _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     783               9 : }
     784                 : /* }}} */
     785                 : 
     786                 : /* {{{ _php_mb_regex_ereg_replace_exec */
     787                 : static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options)
     788             192 : {
     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                 :         char *string;
     798                 :         int string_len;
     799                 : 
     800                 :         char *p;
     801                 :         php_mb_regex_t *re;
     802                 :         OnigSyntaxType *syntax;
     803             192 :         OnigRegion *regs = NULL;
     804             192 :         smart_str out_buf = { 0 };
     805             192 :         smart_str eval_buf = { 0 };
     806                 :         smart_str *pbuf;
     807                 :         int i, err, eval, n;
     808                 :         OnigUChar *pos;
     809                 :         OnigUChar *string_lim;
     810             192 :         char *description = NULL;
     811                 :         char pat_buf[2];
     812                 : 
     813                 :         const mbfl_encoding *enc;
     814                 : 
     815                 :         {
     816                 :                 const char *current_enc_name;
     817             192 :                 current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype));
     818             192 :                 if (current_enc_name == NULL ||
     819                 :                         (enc = mbfl_name2encoding(current_enc_name)) == NULL) {
     820               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error");
     821               0 :                         RETURN_FALSE;
     822                 :                 }
     823                 :         }
     824             192 :         eval = 0;
     825                 :         {
     826             192 :                 char *option_str = NULL;
     827             192 :                 int option_str_len = 0;
     828                 : 
     829             192 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
     830                 :                                                                         &arg_pattern_zval,
     831                 :                                                                         &replace, &replace_len,
     832                 :                                                                         &string, &string_len,
     833                 :                                                                         &option_str, &option_str_len) == FAILURE) {
     834               5 :                         RETURN_FALSE;
     835                 :                 }
     836                 : 
     837             187 :                 if (option_str != NULL) {
     838              93 :                         _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval);
     839                 :                 } else {
     840              94 :                         options |= MBREX(regex_default_options);
     841              94 :                         syntax = MBREX(regex_default_syntax);
     842                 :                 }
     843                 :         }
     844             187 :         if (Z_TYPE_PP(arg_pattern_zval) == IS_STRING) {
     845             169 :                 arg_pattern = Z_STRVAL_PP(arg_pattern_zval);
     846             169 :                 arg_pattern_len = Z_STRLEN_PP(arg_pattern_zval);
     847                 :         } else {
     848                 :                 /* FIXME: this code is not multibyte aware! */
     849              18 :                 convert_to_long_ex(arg_pattern_zval);
     850              18 :                 pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); 
     851              18 :                 pat_buf[1] = '\0';
     852                 : 
     853              18 :                 arg_pattern = pat_buf;
     854              18 :                 arg_pattern_len = 1;    
     855                 :         }
     856                 :         /* create regex pattern buffer */
     857             187 :         re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax TSRMLS_CC);
     858             187 :         if (re == NULL) {
     859               0 :                 RETURN_FALSE;
     860                 :         }
     861                 : 
     862             187 :         if (eval) {
     863               1 :                 pbuf = &eval_buf;
     864               1 :                 description = zend_make_compiled_string_description("mbregex replace" TSRMLS_CC);
     865                 :         } else {
     866             186 :                 pbuf = &out_buf;
     867             186 :                 description = NULL;
     868                 :         }
     869                 : 
     870                 :         /* do the actual work */
     871             187 :         err = 0;
     872             187 :         pos = (OnigUChar *)string;
     873             187 :         string_lim = (OnigUChar*)(string + string_len);
     874             187 :         regs = onig_region_new();
     875             905 :         while (err >= 0) {
     876             532 :                 err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0);
     877             532 :                 if (err <= -2) {
     878                 :                         OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
     879               0 :                         onig_error_code_to_str(err_str, err);
     880               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str);
     881               0 :                         break;
     882                 :                 }
     883             532 :                 if (err >= 0) {
     884                 : #if moriyoshi_0
     885                 :                         if (regs->beg[0] == regs->end[0]) {
     886                 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
     887                 :                                 break;
     888                 :                         }
     889                 : #endif
     890                 :                         /* copy the part of the string before the match */
     891             346 :                         smart_str_appendl(&out_buf, pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos));
     892                 :                         /* copy replacement and backrefs */
     893             346 :                         i = 0;
     894             346 :                         p = replace;
     895            1728 :                         while (i < replace_len) {
     896            1036 :                                 int fwd = (int) php_mb_mbchar_bytes_ex(p, enc);
     897            1036 :                                 n = -1;
     898            1036 :                                 if ((replace_len - i) >= 2 && fwd == 1 &&
     899                 :                                         p[0] == '\\' && p[1] >= '0' && p[1] <= '9') {
     900              14 :                                         n = p[1] - '0';
     901                 :                                 }
     902            1049 :                                 if (n >= 0 && n < regs->num_regs) {
     903              13 :                                         if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && regs->end[n] <= string_len) {
     904              13 :                                                 smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]);
     905                 :                                         }
     906              13 :                                         p += 2;
     907              13 :                                         i += 2;
     908                 :                                 } else {
     909            1023 :                                         smart_str_appendl(pbuf, p, fwd);
     910            1023 :                                         p += fwd;
     911            1023 :                                         i += fwd;
     912                 :                                 }
     913                 :                         }
     914             346 :                         if (eval) {
     915                 :                                 zval v;
     916                 :                                 /* null terminate buffer */
     917               1 :                                 smart_str_0(&eval_buf);
     918                 :                                 /* do eval */
     919               1 :                                 if (zend_eval_stringl(eval_buf.c, eval_buf.len, &v, description TSRMLS_CC) == FAILURE) {
     920               1 :                                         efree(description);
     921               1 :                                         php_error_docref(NULL TSRMLS_CC,E_ERROR, "Failed evaluating code: %s%s", PHP_EOL, eval_buf.c);
     922                 :                                         /* zend_error() does not return in this case */
     923                 :                                 }
     924                 : 
     925                 :                                 /* result of eval */
     926               0 :                                 convert_to_string(&v);
     927               0 :                                 smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v));
     928                 :                                 /* Clean up */
     929               0 :                                 eval_buf.len = 0;
     930               0 :                                 zval_dtor(&v);
     931                 :                         }
     932             345 :                         n = regs->end[0];
     933             345 :                         if ((pos - (OnigUChar *)string) < n) {
     934             319 :                                 pos = (OnigUChar *)string + n;
     935                 :                         } else {
     936              26 :                                 if (pos < string_lim) {
     937              21 :                                         smart_str_appendl(&out_buf, pos, 1); 
     938                 :                                 }
     939              26 :                                 pos++;
     940                 :                         }
     941                 :                 } else { /* nomatch */
     942                 :                         /* stick that last bit of string on our output */
     943             186 :                         if (string_lim - pos > 0) {
     944             135 :                                 smart_str_appendl(&out_buf, pos, string_lim - pos);
     945                 :                         }
     946                 :                 }
     947             531 :                 onig_region_free(regs, 0);
     948                 :         }
     949                 : 
     950             186 :         if (description) {
     951               0 :                 efree(description);
     952                 :         }
     953             186 :         if (regs != NULL) {
     954             186 :                 onig_region_free(regs, 1);
     955                 :         }
     956             186 :         smart_str_free(&eval_buf);
     957                 : 
     958             186 :         if (err <= -2) {
     959               0 :                 smart_str_free(&out_buf);   
     960               0 :                 RETVAL_FALSE;
     961                 :         } else {
     962             186 :                 smart_str_appendc(&out_buf, '\0');
     963             186 :                 RETVAL_STRINGL((char *)out_buf.c, out_buf.len - 1, 0);
     964                 :         }
     965                 : }
     966                 : /* }}} */
     967                 : 
     968                 : /* {{{ proto string mb_ereg_replace(string pattern, string replacement, string string [, string option])
     969                 :    Replace regular expression for multibyte string */
     970                 : PHP_FUNCTION(mb_ereg_replace)
     971             126 : {
     972             126 :         _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     973             125 : }
     974                 : /* }}} */
     975                 : 
     976                 : /* {{{ proto string mb_eregi_replace(string pattern, string replacement, string string)
     977                 :    Case insensitive replace regular expression for multibyte string */
     978                 : PHP_FUNCTION(mb_eregi_replace)
     979              66 : {
     980              66 :         _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE);
     981              66 : }
     982                 : /* }}} */
     983                 : 
     984                 : /* {{{ proto array mb_split(string pattern, string string [, int limit])
     985                 :    split multibyte string into array by regular expression */
     986                 : PHP_FUNCTION(mb_split)
     987              86 : {
     988                 :         char *arg_pattern;
     989                 :         int arg_pattern_len;
     990                 :         php_mb_regex_t *re;
     991              86 :         OnigRegion *regs = NULL;
     992                 :         char *string;
     993                 :         OnigUChar *pos;
     994                 :         int string_len;
     995                 : 
     996                 :         int n, err;
     997              86 :         long count = -1;
     998                 : 
     999              86 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &arg_pattern, &arg_pattern_len, &string, &string_len, &count) == FAILURE) {
    1000              11 :                 RETURN_FALSE;
    1001                 :         } 
    1002                 : 
    1003              75 :         if (count == 0) {
    1004              10 :                 count = 1;
    1005                 :         }
    1006                 : 
    1007                 :         /* create regex pattern buffer */
    1008              75 :         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) {
    1009               0 :                 RETURN_FALSE;
    1010                 :         }
    1011                 : 
    1012              75 :         array_init(return_value);
    1013                 : 
    1014              75 :         pos = (OnigUChar *)string;
    1015              75 :         err = 0;
    1016              75 :         regs = onig_region_new();
    1017                 :         /* churn through str, generating array entries as we go */
    1018             222 :         while ((--count != 0) &&
    1019                 :                    (err = onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), pos, (OnigUChar *)(string + string_len), regs, 0)) >= 0) {
    1020              80 :                 if (regs->beg[0] == regs->end[0]) {
    1021               8 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
    1022               8 :                         break;
    1023                 :                 }
    1024                 : 
    1025                 :                 /* add it to the array */
    1026              72 :                 if (regs->beg[0] < string_len && regs->beg[0] >= (pos - (OnigUChar *)string)) {
    1027              72 :                         add_next_index_stringl(return_value, (char *)pos, ((OnigUChar *)(string + regs->beg[0]) - pos), 1);
    1028                 :                 } else {
    1029               0 :                         err = -2;
    1030               0 :                         break;
    1031                 :                 }
    1032                 :                 /* point at our new starting point */
    1033              72 :                 n = regs->end[0];
    1034              72 :                 if ((pos - (OnigUChar *)string) < n) {
    1035              72 :                         pos = (OnigUChar *)string + n;
    1036                 :                 }
    1037              72 :                 if (count < 0) {
    1038              42 :                         count = 0;
    1039                 :                 }
    1040              72 :                 onig_region_free(regs, 0);
    1041                 :         }
    1042                 : 
    1043              75 :         onig_region_free(regs, 1);
    1044                 : 
    1045                 :         /* see if we encountered an error */
    1046              75 :         if (err <= -2) {
    1047                 :                 OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
    1048               0 :                 onig_error_code_to_str(err_str, err);
    1049               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in mbsplit(): %s", err_str);
    1050               0 :                 zval_dtor(return_value);
    1051               0 :                 RETURN_FALSE;
    1052                 :         }
    1053                 : 
    1054                 :         /* otherwise we just have one last element to add to the array */
    1055              75 :         n = ((OnigUChar *)(string + string_len) - pos);
    1056              75 :         if (n > 0) {
    1057              61 :                 add_next_index_stringl(return_value, (char *)pos, n, 1);
    1058                 :         } else {
    1059              14 :                 add_next_index_stringl(return_value, "", 0, 1);
    1060                 :         }
    1061                 : }
    1062                 : /* }}} */
    1063                 : 
    1064                 : /* {{{ proto bool mb_ereg_match(string pattern, string string [,string option])
    1065                 :    Regular expression match for multibyte string */
    1066                 : PHP_FUNCTION(mb_ereg_match)
    1067               7 : {
    1068                 :         char *arg_pattern;
    1069                 :         int arg_pattern_len;
    1070                 : 
    1071                 :         char *string;
    1072                 :         int string_len;
    1073                 : 
    1074                 :         php_mb_regex_t *re;
    1075                 :         OnigSyntaxType *syntax;
    1076               7 :         OnigOptionType option = 0;
    1077                 :         int err;
    1078                 : 
    1079                 :         {
    1080               7 :                 char *option_str = NULL;
    1081               7 :                 int option_str_len = 0;
    1082                 : 
    1083               7 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s",
    1084                 :                                           &arg_pattern, &arg_pattern_len, &string, &string_len,
    1085                 :                                           &option_str, &option_str_len)==FAILURE) {
    1086               3 :                         RETURN_FALSE;
    1087                 :                 }
    1088                 : 
    1089               4 :                 if (option_str != NULL) {
    1090               1 :                         _php_mb_regex_init_options(option_str, option_str_len, &option, &syntax, NULL);
    1091                 :                 } else {
    1092               3 :                         option |= MBREX(regex_default_options);
    1093               3 :                         syntax = MBREX(regex_default_syntax);
    1094                 :                 }
    1095                 :         }
    1096                 : 
    1097               4 :         if ((re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), syntax TSRMLS_CC)) == NULL) {
    1098               0 :                 RETURN_FALSE;
    1099                 :         }
    1100                 : 
    1101                 :         /* match */
    1102               4 :         err = onig_match(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, NULL, 0);
    1103               4 :         if (err >= 0) {
    1104               2 :                 RETVAL_TRUE;
    1105                 :         } else {
    1106               2 :                 RETVAL_FALSE;
    1107                 :         }
    1108                 : }
    1109                 : /* }}} */
    1110                 : 
    1111                 : /* regex search */
    1112                 : /* {{{ _php_mb_regex_ereg_search_exec */
    1113                 : static void
    1114                 : _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAMETERS, int mode)
    1115              68 : {
    1116              68 :         size_t argc = ZEND_NUM_ARGS();
    1117                 :         char *arg_pattern, *arg_options;
    1118                 :         int arg_pattern_len, arg_options_len;
    1119                 :         int n, i, err, pos, len, beg, end;
    1120                 :         OnigOptionType option;
    1121                 :         OnigUChar *str;
    1122                 :         OnigSyntaxType *syntax;
    1123                 : 
    1124              68 :         if (zend_parse_parameters(argc TSRMLS_CC, "|ss", &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) {
    1125               0 :                 return;
    1126                 :         }
    1127                 : 
    1128              68 :         option = MBREX(regex_default_options);
    1129                 : 
    1130              68 :         if (argc == 2) {
    1131               0 :                 option = 0;
    1132               0 :                 _php_mb_regex_init_options(arg_options, arg_options_len, &option, &syntax, NULL);
    1133                 :         }
    1134                 : 
    1135              68 :         if (argc > 0) {
    1136                 :                 /* create regex pattern buffer */
    1137               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) {
    1138               0 :                         RETURN_FALSE;
    1139                 :                 }
    1140                 :         }
    1141                 : 
    1142              68 :         pos = MBREX(search_pos);
    1143              68 :         str = NULL;
    1144              68 :         len = 0;
    1145              68 :         if (MBREX(search_str) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING){
    1146              68 :                 str = (OnigUChar *)Z_STRVAL_P(MBREX(search_str));
    1147              68 :                 len = Z_STRLEN_P(MBREX(search_str));
    1148                 :         }
    1149                 : 
    1150              68 :         if (MBREX(search_re) == NULL) {
    1151               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No regex given");
    1152               0 :                 RETURN_FALSE;
    1153                 :         }
    1154                 : 
    1155              68 :         if (str == NULL) {
    1156               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No string given");
    1157               0 :                 RETURN_FALSE;
    1158                 :         }
    1159                 : 
    1160              68 :         if (MBREX(search_regs)) {
    1161              49 :                 onig_region_free(MBREX(search_regs), 1);
    1162                 :         }
    1163              68 :         MBREX(search_regs) = onig_region_new();
    1164                 : 
    1165              68 :         err = onig_search(MBREX(search_re), str, str + len, str + pos, str  + len, MBREX(search_regs), 0);
    1166              68 :         if (err == ONIG_MISMATCH) {
    1167              17 :                 MBREX(search_pos) = len;
    1168              17 :                 RETVAL_FALSE;
    1169              51 :         } else if (err <= -2) {
    1170                 :                 OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
    1171               0 :                 onig_error_code_to_str(err_str, err);
    1172               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "mbregex search failure in mbregex_search(): %s", err_str);
    1173               0 :                 RETVAL_FALSE;
    1174                 :         } else {
    1175              51 :                 if (MBREX(search_regs)->beg[0] == MBREX(search_regs)->end[0]) {
    1176               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
    1177                 :                 }
    1178              51 :                 switch (mode) {
    1179                 :                 case 1:
    1180              45 :                         array_init(return_value);
    1181              45 :                         beg = MBREX(search_regs)->beg[0];
    1182              45 :                         end = MBREX(search_regs)->end[0];
    1183              45 :                         add_next_index_long(return_value, beg);
    1184              45 :                         add_next_index_long(return_value, end - beg);
    1185              45 :                         break;
    1186                 :                 case 2:
    1187               5 :                         array_init(return_value);
    1188               5 :                         n = MBREX(search_regs)->num_regs;
    1189              10 :                         for (i = 0; i < n; i++) {
    1190               5 :                                 beg = MBREX(search_regs)->beg[i];
    1191               5 :                                 end = MBREX(search_regs)->end[i];
    1192              10 :                                 if (beg >= 0 && beg <= end && end <= len) {
    1193               5 :                                         add_index_stringl(return_value, i, (char *)&str[beg], end - beg, 1);
    1194                 :                                 } else {
    1195               0 :                                         add_index_bool(return_value, i, 0);
    1196                 :                                 }
    1197                 :                         }
    1198               5 :                         break;
    1199                 :                 default:
    1200               1 :                         RETVAL_TRUE;
    1201                 :                         break;
    1202                 :                 }
    1203              51 :                 end = MBREX(search_regs)->end[0];
    1204              51 :                 if (pos < end) {
    1205              51 :                         MBREX(search_pos) = end;
    1206                 :                 } else {
    1207               0 :                         MBREX(search_pos) = pos + 1;
    1208                 :                 }
    1209                 :         }
    1210                 : 
    1211              68 :         if (err < 0) {
    1212              17 :                 onig_region_free(MBREX(search_regs), 1);
    1213              17 :                 MBREX(search_regs) = (OnigRegion *)NULL;
    1214                 :         }
    1215                 : }
    1216                 : /* }}} */
    1217                 : 
    1218                 : /* {{{ proto bool mb_ereg_search([string pattern[, string option]])
    1219                 :    Regular expression search for multibyte string */
    1220                 : PHP_FUNCTION(mb_ereg_search)
    1221               1 : {
    1222               1 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1223               1 : }
    1224                 : /* }}} */
    1225                 : 
    1226                 : /* {{{ proto array mb_ereg_search_pos([string pattern[, string option]])
    1227                 :    Regular expression search for multibyte string */
    1228                 : PHP_FUNCTION(mb_ereg_search_pos)
    1229              61 : {
    1230              61 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1231              61 : }
    1232                 : /* }}} */
    1233                 : 
    1234                 : /* {{{ proto array mb_ereg_search_regs([string pattern[, string option]])
    1235                 :    Regular expression search for multibyte string */
    1236                 : PHP_FUNCTION(mb_ereg_search_regs)
    1237               6 : {
    1238               6 :         _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
    1239               6 : }
    1240                 : /* }}} */
    1241                 : 
    1242                 : /* {{{ proto bool mb_ereg_search_init(string string [, string pattern[, string option]])
    1243                 :    Initialize string and regular expression for search. */
    1244                 : PHP_FUNCTION(mb_ereg_search_init)
    1245              22 : {
    1246              22 :         size_t argc = ZEND_NUM_ARGS();
    1247                 :         zval *arg_str;
    1248                 :         char *arg_pattern, *arg_options;
    1249                 :         int arg_pattern_len, arg_options_len;
    1250              22 :         OnigSyntaxType *syntax = NULL;
    1251                 :         OnigOptionType option;
    1252                 : 
    1253              22 :         if (zend_parse_parameters(argc TSRMLS_CC, "z|ss", &arg_str, &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) {
    1254               3 :                 return;
    1255                 :         }
    1256                 : 
    1257              19 :         option = MBREX(regex_default_options);
    1258              19 :         syntax = MBREX(regex_default_syntax);
    1259                 : 
    1260              19 :         if (argc == 3) {
    1261              16 :                 option = 0;
    1262              16 :                 _php_mb_regex_init_options(arg_options, arg_options_len, &option, &syntax, NULL);
    1263                 :         }
    1264                 : 
    1265              19 :         if (argc > 1) {
    1266                 :                 /* create regex pattern buffer */
    1267              17 :                 if ((MBREX(search_re) = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, option, MBREX(current_mbctype), syntax TSRMLS_CC)) == NULL) {
    1268               0 :                         RETURN_FALSE;
    1269                 :                 }
    1270                 :         }
    1271                 : 
    1272              19 :         if (MBREX(search_str) != NULL) {
    1273              15 :                 zval_ptr_dtor(&MBREX(search_str));
    1274              15 :                 MBREX(search_str) = (zval *)NULL;
    1275                 :         }
    1276                 : 
    1277              19 :         MBREX(search_str) = arg_str;
    1278              19 :         Z_ADDREF_P(MBREX(search_str));
    1279              19 :         SEPARATE_ZVAL_IF_NOT_REF(&MBREX(search_str));
    1280                 : 
    1281              19 :         MBREX(search_pos) = 0;
    1282                 : 
    1283              19 :         if (MBREX(search_regs) != NULL) {
    1284               0 :                 onig_region_free(MBREX(search_regs), 1);
    1285               0 :                 MBREX(search_regs) = (OnigRegion *) NULL;
    1286                 :         }
    1287                 : 
    1288              19 :         RETURN_TRUE;
    1289                 : }
    1290                 : /* }}} */
    1291                 : 
    1292                 : /* {{{ proto array mb_ereg_search_getregs(void)
    1293                 :    Get matched substring of the last time */
    1294                 : PHP_FUNCTION(mb_ereg_search_getregs)
    1295              45 : {
    1296                 :         int n, i, len, beg, end;
    1297                 :         OnigUChar *str;
    1298                 : 
    1299              90 :         if (MBREX(search_regs) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING && Z_STRVAL_P(MBREX(search_str)) != NULL) {
    1300              45 :                 array_init(return_value);
    1301                 : 
    1302              45 :                 str = (OnigUChar *)Z_STRVAL_P(MBREX(search_str));
    1303              45 :                 len = Z_STRLEN_P(MBREX(search_str));
    1304              45 :                 n = MBREX(search_regs)->num_regs;
    1305             134 :                 for (i = 0; i < n; i++) {
    1306              89 :                         beg = MBREX(search_regs)->beg[i];
    1307              89 :                         end = MBREX(search_regs)->end[i];
    1308             178 :                         if (beg >= 0 && beg <= end && end <= len) {
    1309              89 :                                 add_index_stringl(return_value, i, (char *)&str[beg], end - beg, 1);
    1310                 :                         } else {
    1311               0 :                                 add_index_bool(return_value, i, 0);
    1312                 :                         }
    1313                 :                 }
    1314                 :         } else {
    1315               0 :                 RETVAL_FALSE;
    1316                 :         }
    1317              45 : }
    1318                 : /* }}} */
    1319                 : 
    1320                 : /* {{{ proto int mb_ereg_search_getpos(void)
    1321                 :    Get search start position */
    1322                 : PHP_FUNCTION(mb_ereg_search_getpos)
    1323              44 : {
    1324              44 :         RETVAL_LONG(MBREX(search_pos));
    1325              44 : }
    1326                 : /* }}} */
    1327                 : 
    1328                 : /* {{{ proto bool mb_ereg_search_setpos(int position)
    1329                 :    Set search start position */
    1330                 : PHP_FUNCTION(mb_ereg_search_setpos)
    1331               0 : {
    1332                 :         long position;
    1333                 : 
    1334               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &position) == FAILURE) {
    1335               0 :                 return;
    1336                 :         }
    1337                 : 
    1338               0 :         if (position < 0 || (MBREX(search_str) != NULL && Z_TYPE_P(MBREX(search_str)) == IS_STRING && position >= Z_STRLEN_P(MBREX(search_str)))) {
    1339               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Position is out of range");
    1340               0 :                 MBREX(search_pos) = 0;
    1341               0 :                 RETURN_FALSE;
    1342                 :         }
    1343                 : 
    1344               0 :         MBREX(search_pos) = position;
    1345               0 :         RETURN_TRUE;
    1346                 : }
    1347                 : /* }}} */
    1348                 : 
    1349                 : /* {{{ php_mb_regex_set_options */
    1350                 : static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) 
    1351               6 : {
    1352               6 :         if (prev_options != NULL) {
    1353               0 :                 *prev_options = MBREX(regex_default_options);
    1354                 :         }
    1355               6 :         if (prev_syntax != NULL) {
    1356               0 :                 *prev_syntax = MBREX(regex_default_syntax);
    1357                 :         }
    1358               6 :         MBREX(regex_default_options) = options;
    1359               6 :         MBREX(regex_default_syntax) = syntax;
    1360               6 : }
    1361                 : /* }}} */
    1362                 : 
    1363                 : /* {{{ proto string mb_regex_set_options([string options])
    1364                 :    Set or get the default options for mbregex functions */
    1365                 : PHP_FUNCTION(mb_regex_set_options)
    1366               6 : {
    1367                 :         OnigOptionType opt;
    1368                 :         OnigSyntaxType *syntax;
    1369               6 :         char *string = NULL;
    1370                 :         int string_len;
    1371                 :         char buf[16];
    1372                 : 
    1373               6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
    1374                 :                                   &string, &string_len) == FAILURE) {
    1375               0 :                 RETURN_FALSE;
    1376                 :         }
    1377               6 :         if (string != NULL) {
    1378               6 :                 opt = 0;
    1379               6 :                 syntax = NULL;
    1380               6 :                 _php_mb_regex_init_options(string, string_len, &opt, &syntax, NULL);
    1381               6 :                 _php_mb_regex_set_options(opt, syntax, NULL, NULL TSRMLS_CC);
    1382                 :         } else {
    1383               0 :                 opt = MBREX(regex_default_options);
    1384               0 :                 syntax = MBREX(regex_default_syntax);
    1385                 :         }
    1386               6 :         _php_mb_regex_get_option_string(buf, sizeof(buf), opt, syntax);
    1387                 : 
    1388               6 :         RETVAL_STRING(buf, 1);
    1389                 : }
    1390                 : /* }}} */
    1391                 : 
    1392                 : #endif  /* HAVE_MBREGEX */
    1393                 : 
    1394                 : /*
    1395                 :  * Local variables:
    1396                 :  * tab-width: 4
    1397                 :  * c-basic-offset: 4
    1398                 :  * End:
    1399                 :  * vim600: fdm=marker
    1400                 :  * vim: noet sw=4 ts=4
    1401                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:02 +0000 (3 days ago)

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