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 - ereg - ereg.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 301
Code covered: 87.4 % Executed lines: 263
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                 :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16                 :    |          Jim Winstead <jimw@php.net>                                 |
      17                 :    |          Jaakko Hyvätti <jaakko@hyvatti.iki.fi>                      | 
      18                 :    +----------------------------------------------------------------------+
      19                 :  */
      20                 : /* $Id: ereg.c 281350 2009-05-28 21:57:24Z scottmac $ */
      21                 : 
      22                 : #include <stdio.h>
      23                 : #include <ctype.h>
      24                 : #include "php.h"
      25                 : #include "ext/standard/php_string.h"
      26                 : #include "php_ereg.h"
      27                 : #include "ext/standard/info.h"
      28                 : 
      29                 : /* {{{ arginfo */
      30                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_ereg, 0, 0, 2)
      31                 :         ZEND_ARG_INFO(0, pattern)
      32                 :         ZEND_ARG_INFO(0, string) 
      33                 :         ZEND_ARG_INFO(1, registers) /* ARRAY_INFO(1, registers, 1) */
      34                 : ZEND_END_ARG_INFO()
      35                 : 
      36                 : ZEND_BEGIN_ARG_INFO(arginfo_ereg_replace, 0)
      37                 :         ZEND_ARG_INFO(0, pattern)
      38                 :         ZEND_ARG_INFO(0, replacement)
      39                 :         ZEND_ARG_INFO(0, string)
      40                 : ZEND_END_ARG_INFO()
      41                 : 
      42                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_split, 0, 0, 2)
      43                 :         ZEND_ARG_INFO(0, pattern)
      44                 :         ZEND_ARG_INFO(0, string) 
      45                 :         ZEND_ARG_INFO(0, limit)  
      46                 : ZEND_END_ARG_INFO()
      47                 : 
      48                 : ZEND_BEGIN_ARG_INFO(arginfo_sql_regcase, 0)
      49                 :         ZEND_ARG_INFO(0, string)
      50                 : ZEND_END_ARG_INFO()
      51                 : /* }}} */
      52                 : 
      53                 : /* {{{ Function table */
      54                 : const zend_function_entry ereg_functions[] = {
      55                 :         PHP_DEP_FE(ereg,                        arginfo_ereg)
      56                 :         PHP_DEP_FE(ereg_replace,        arginfo_ereg_replace)
      57                 :         PHP_DEP_FE(eregi,                       arginfo_ereg)
      58                 :         PHP_DEP_FE(eregi_replace,       arginfo_ereg_replace)
      59                 :         PHP_DEP_FE(split,                       arginfo_split)
      60                 :         PHP_DEP_FE(spliti,                      arginfo_split)
      61                 :         PHP_DEP_FE(sql_regcase,         arginfo_sql_regcase)
      62                 :         {NULL, NULL, NULL}
      63                 : };
      64                 : /* }}} */
      65                 : 
      66                 : /* {{{ reg_cache */
      67                 : typedef struct {
      68                 :         regex_t preg;
      69                 :         int cflags;
      70                 :         unsigned long lastuse;
      71                 : } reg_cache;
      72                 : static int reg_magic = 0;
      73                 : #define EREG_CACHE_SIZE 4096
      74                 : /* }}} */
      75                 : 
      76                 : ZEND_DECLARE_MODULE_GLOBALS(ereg)
      77                 : 
      78                 : /* {{{ Module entry */
      79                 : zend_module_entry ereg_module_entry = {
      80                 :         STANDARD_MODULE_HEADER,
      81                 :         "ereg",
      82                 :         ereg_functions,
      83                 :         PHP_MINIT(ereg),
      84                 :         PHP_MSHUTDOWN(ereg),
      85                 :         NULL,
      86                 :         NULL,
      87                 :         PHP_MINFO(ereg),
      88                 :         NO_VERSION_YET,
      89                 :         STANDARD_MODULE_PROPERTIES
      90                 : };
      91                 : /* }}} */
      92                 : 
      93                 : /* {{{ ereg_lru_cmp */
      94                 : static int ereg_lru_cmp(const void *a, const void *b TSRMLS_DC)
      95               0 : {
      96               0 :         Bucket *f = *((Bucket **) a);
      97               0 :         Bucket *s = *((Bucket **) b);
      98                 : 
      99               0 :         if (((reg_cache *)f->pData)->lastuse <
     100                 :                                 ((reg_cache *)s->pData)->lastuse) {
     101               0 :                 return -1;
     102               0 :         } else if (((reg_cache *)f->pData)->lastuse ==
     103                 :                                 ((reg_cache *)s->pData)->lastuse) {
     104               0 :                 return 0;
     105                 :         } else {
     106               0 :                 return 1;
     107                 :         }
     108                 : }
     109                 : /* }}} */
     110                 : 
     111                 : /* {{{ static ereg_clean_cache */
     112                 : static int ereg_clean_cache(void *data, void *arg TSRMLS_DC)
     113               0 : {
     114               0 :         int *num_clean = (int *)arg;
     115                 : 
     116               0 :         if (*num_clean > 0) {
     117               0 :                 (*num_clean)--;
     118               0 :                 return ZEND_HASH_APPLY_REMOVE;
     119                 :         } else {
     120               0 :                 return ZEND_HASH_APPLY_STOP;
     121                 :         }
     122                 : }
     123                 : /* }}} */
     124                 : 
     125                 : /* {{{ _php_regcomp
     126                 :  */
     127                 : static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
     128             670 : {
     129             670 :         int r = 0;
     130             670 :         int patlen = strlen(pattern);
     131             670 :         reg_cache *rc = NULL;
     132                 :         TSRMLS_FETCH();
     133                 : 
     134             670 :         if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) {
     135                 :                 /* easier than dealing with overflow as it happens */
     136               0 :                 if (EREG(lru_counter) >= (1 << 31) || zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0 TSRMLS_CC) == FAILURE) {
     137               0 :                         zend_hash_clean(&EREG(ht_rc));
     138               0 :                         EREG(lru_counter) = 0;
     139                 :                 } else {
     140               0 :                         int num_clean = EREG_CACHE_SIZE / 4;
     141               0 :                         zend_hash_apply_with_argument(&EREG(ht_rc), ereg_clean_cache, &num_clean TSRMLS_CC);
     142                 :                 }
     143                 :         }
     144                 : 
     145             670 :         if(zend_hash_find(&EREG(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS
     146                 :            && rc->cflags == cflags) {
     147                 : #ifdef HAVE_REGEX_T_RE_MAGIC
     148                 :                 /*
     149                 :                  * We use a saved magic number to see whether cache is corrupted, and if it
     150                 :                  * is, we flush it and compile the pattern from scratch.
     151                 :                  */
     152             275 :                 if (rc->preg.re_magic != reg_magic) {
     153               0 :                         zend_hash_clean(&EREG(ht_rc));
     154               0 :                         EREG(lru_counter) = 0;
     155                 :                 } else {
     156             275 :                         memcpy(preg, &rc->preg, sizeof(*preg));
     157             275 :                         return r;
     158                 :                 }
     159                 :         }
     160                 : 
     161             395 :         r = regcomp(preg, pattern, cflags);
     162             395 :         if(!r) {
     163                 :                 reg_cache rcp;
     164                 : 
     165             253 :                 rcp.cflags = cflags;
     166             253 :                 rcp.lastuse = ++(EREG(lru_counter));
     167             253 :                 memcpy(&rcp.preg, preg, sizeof(*preg));
     168                 :                 /*
     169                 :                  * Since we don't have access to the actual MAGIC1 definition in the private
     170                 :                  * header file, we save the magic value immediately after compilation. Hopefully,
     171                 :                  * it's good.
     172                 :                  */
     173             253 :                 if (!reg_magic) reg_magic = preg->re_magic;
     174             253 :                 zend_hash_update(&EREG(ht_rc), (char *) pattern, patlen+1,
     175                 :                                                  (void *) &rcp, sizeof(rcp), NULL);
     176                 :         }
     177                 : #else
     178                 :                 memcpy(preg, &rc->preg, sizeof(*preg));
     179                 :         } else {
     180                 :                 r = regcomp(preg, pattern, cflags);
     181                 :                 if(!r) {
     182                 :                         reg_cache rcp;
     183                 : 
     184                 :                         rcp.cflags = cflags;
     185                 :                         rcp.lastuse = ++(EREG(lru_counter));
     186                 :                         memcpy(&rcp.preg, preg, sizeof(*preg));
     187                 :                         zend_hash_update(&EREG(ht_rc), (char *) pattern, patlen+1,
     188                 :                                                          (void *) &rcp, sizeof(rcp), NULL);
     189                 :                 }
     190                 :         }
     191                 : #endif
     192             395 :         return r;
     193                 : }
     194                 : /* }}} */
     195                 : 
     196                 : static void _free_ereg_cache(reg_cache *rc) 
     197             253 : {
     198             253 :         regfree(&rc->preg);
     199             253 : }
     200                 : 
     201                 : #undef regfree
     202                 : #define regfree(a);
     203                 : #undef regcomp
     204                 : #define regcomp(a, b, c) _php_regcomp(a, b, c)
     205                 :         
     206                 : static void php_ereg_init_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
     207           17633 : {
     208           17633 :         zend_hash_init(&ereg_globals->ht_rc, 0, NULL, (void (*)(void *)) _free_ereg_cache, 1);
     209           17633 :         ereg_globals->lru_counter = 0;
     210           17633 : }
     211                 : 
     212                 : static void php_ereg_destroy_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
     213           17665 : {
     214           17665 :         zend_hash_destroy(&ereg_globals->ht_rc);
     215           17665 : }
     216                 : 
     217                 : PHP_MINIT_FUNCTION(ereg)
     218           17633 : {
     219           17633 :         ZEND_INIT_MODULE_GLOBALS(ereg, php_ereg_init_globals, php_ereg_destroy_globals);
     220           17633 :         return SUCCESS;
     221                 : }
     222                 : 
     223                 : PHP_MSHUTDOWN_FUNCTION(ereg)
     224           17665 : {
     225                 : #ifndef ZTS
     226           17665 :         php_ereg_destroy_globals(&ereg_globals TSRMLS_CC);
     227                 : #endif
     228                 : 
     229           17665 :         return SUCCESS;
     230                 : }
     231                 : 
     232                 : PHP_MINFO_FUNCTION(ereg)
     233              42 : {
     234              42 :         php_info_print_table_start();
     235                 : #if HSREGEX
     236              42 :         php_info_print_table_row(2, "Regex Library", "Bundled library enabled");
     237                 : #else
     238                 :         php_info_print_table_row(2, "Regex Library", "System library enabled");
     239                 : #endif
     240              42 :         php_info_print_table_end();
     241              42 : }
     242                 : 
     243                 : 
     244                 : /* {{{ php_ereg_eprint
     245                 :  * php_ereg_eprint - convert error number to name
     246                 :  */
     247             142 : static void php_ereg_eprint(int err, regex_t *re) {
     248             142 :         char *buf = NULL, *message = NULL;
     249                 :         size_t len;
     250                 :         size_t buf_len;
     251                 : 
     252                 : #ifdef REG_ITOA
     253                 :         /* get the length of the message */
     254             142 :         buf_len = regerror(REG_ITOA | err, re, NULL, 0);
     255             142 :         if (buf_len) {
     256             142 :                 buf = (char *)safe_emalloc(buf_len, sizeof(char), 0);
     257             142 :                 if (!buf) return; /* fail silently */
     258                 :                 /* finally, get the error message */
     259             142 :                 regerror(REG_ITOA | err, re, buf, buf_len);
     260                 :         }
     261                 : #else
     262                 :         buf_len = 0;
     263                 : #endif
     264             142 :         len = regerror(err, re, NULL, 0);
     265             142 :         if (len) {
     266                 :                 TSRMLS_FETCH();
     267                 : 
     268             142 :                 message = (char *)safe_emalloc((buf_len + len + 2), sizeof(char), 0);
     269             142 :                 if (!message) {
     270               0 :                         return; /* fail silently */
     271                 :                 }
     272             142 :                 if (buf_len) {
     273             142 :                         snprintf(message, buf_len, "%s: ", buf);
     274             142 :                         buf_len += 1; /* so pointer math below works */
     275                 :                 }
     276                 :                 /* drop the message into place */
     277             142 :                 regerror(err, re, message + buf_len, len);
     278                 : 
     279             142 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
     280                 :         }
     281                 : 
     282             142 :         STR_FREE(buf);
     283             142 :         STR_FREE(message);
     284                 : }
     285                 : /* }}} */
     286                 : 
     287                 : /* {{{ php_ereg
     288                 :  */
     289                 : static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
     290             253 : {
     291                 :         zval **regex,                   /* Regular expression */
     292             253 :                 **array = NULL;         /* Optional register array */
     293                 :         char *findin;           /* String to apply expression to */
     294                 :         int findin_len;
     295                 :         regex_t re;
     296                 :         regmatch_t *subs;
     297                 :         int err, match_len, string_len;
     298                 :         uint i;
     299             253 :         int copts = 0;
     300                 :         off_t start, end;
     301             253 :         char *buf = NULL;
     302             253 :         char *string = NULL;
     303             253 :         int   argc = ZEND_NUM_ARGS();
     304                 : 
     305             253 :         if (zend_parse_parameters(argc TSRMLS_CC, "Zs|Z", &regex, &findin, &findin_len, &array) == FAILURE) {
     306              16 :                 return;
     307                 :         }
     308                 : 
     309             237 :         if (icase) {
     310             117 :                 copts |= REG_ICASE;
     311                 :         }
     312                 :         
     313             237 :         if (argc == 2) {
     314              57 :                 copts |= REG_NOSUB;
     315                 :         }
     316                 : 
     317                 :         /* compile the regular expression from the supplied regex */
     318             237 :         if (Z_TYPE_PP(regex) == IS_STRING) {
     319             191 :                 err = regcomp(&re, Z_STRVAL_PP(regex), REG_EXTENDED | copts);
     320                 :         } else {
     321                 :                 /* we convert numbers to integers and treat them as a string */
     322              46 :                 if (Z_TYPE_PP(regex) == IS_DOUBLE) {
     323              10 :                         convert_to_long_ex(regex);      /* get rid of decimal places */
     324                 :                 }
     325              46 :                 convert_to_string_ex(regex);
     326                 :                 /* don't bother doing an extended regex with just a number */
     327              46 :                 err = regcomp(&re, Z_STRVAL_PP(regex), copts);
     328                 :         }
     329                 : 
     330             237 :         if (err) {
     331              46 :                 php_ereg_eprint(err, &re);
     332              46 :                 RETURN_FALSE;
     333                 :         }
     334                 : 
     335                 :         /* make a copy of the string we're looking in */
     336             191 :         string = estrndup(findin, findin_len);
     337                 : 
     338                 :         /* allocate storage for (sub-)expression-matches */
     339             191 :         subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1);
     340                 :         
     341                 :         /* actually execute the regular expression */
     342             191 :         err = regexec(&re, string, re.re_nsub+1, subs, 0);
     343             191 :         if (err && err != REG_NOMATCH) {
     344               0 :                 php_ereg_eprint(err, &re);
     345                 :                 regfree(&re);
     346               0 :                 efree(subs);
     347               0 :                 RETURN_FALSE;
     348                 :         }
     349             191 :         match_len = 1;
     350                 : 
     351             191 :         if (array && err != REG_NOMATCH) {
     352              99 :                 match_len = (int) (subs[0].rm_eo - subs[0].rm_so);
     353              99 :                 string_len = findin_len + 1;
     354                 : 
     355              99 :                 buf = emalloc(string_len);
     356                 : 
     357              99 :                 zval_dtor(*array);      /* start with clean array */
     358              99 :                 array_init(*array);
     359                 : 
     360            4358 :                 for (i = 0; i <= re.re_nsub; i++) {
     361            4259 :                         start = subs[i].rm_so;
     362            4259 :                         end = subs[i].rm_eo;
     363            8510 :                         if (start != -1 && end > 0 && start < string_len && end < string_len && start < end) {
     364            4251 :                                 add_index_stringl(*array, i, string+start, end-start, 1);
     365                 :                         } else {
     366               8 :                                 add_index_bool(*array, i, 0);
     367                 :                         }
     368                 :                 }
     369              99 :                 efree(buf);
     370                 :         }
     371                 : 
     372             191 :         efree(subs);
     373             191 :         efree(string);
     374             191 :         if (err == REG_NOMATCH) {
     375              63 :                 RETVAL_FALSE;
     376                 :         } else {
     377             128 :                 if (match_len == 0)
     378               4 :                         match_len = 1;
     379             128 :                 RETVAL_LONG(match_len);
     380                 :         }
     381                 :         regfree(&re);
     382                 : }
     383                 : /* }}} */
     384                 : 
     385                 : /* {{{ proto int ereg(string pattern, string string [, array registers])
     386                 :    Regular expression match */
     387                 : PHP_FUNCTION(ereg)
     388             128 : {
     389             128 :         php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     390             128 : }
     391                 : /* }}} */
     392                 : 
     393                 : /* {{{ proto int eregi(string pattern, string string [, array registers])
     394                 :    Case-insensitive regular expression match */
     395                 : PHP_FUNCTION(eregi)
     396             125 : {
     397             125 :         php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     398             125 : }
     399                 : /* }}} */
     400                 : 
     401                 : /* {{{ php_ereg_replace
     402                 :  * this is the meat and potatoes of regex replacement! */
     403                 : PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended)
     404             222 : {
     405                 :         regex_t re;
     406                 :         regmatch_t *subs;
     407                 : 
     408                 :         char *buf,      /* buf is where we build the replaced string */
     409                 :                  *nbuf, /* nbuf is used when we grow the buffer */
     410                 :                  *walkbuf; /* used to walk buf when replacing backrefs */
     411                 :         const char *walk; /* used to walk replacement string for backrefs */
     412                 :         int buf_len;
     413                 :         int pos, tmp, string_len, new_l;
     414             222 :         int err, copts = 0;
     415                 : 
     416             222 :         string_len = strlen(string);
     417                 : 
     418             222 :         if (icase) {
     419             103 :                 copts = REG_ICASE;
     420                 :         }
     421             222 :         if (extended) {
     422             222 :                 copts |= REG_EXTENDED;
     423                 :         }
     424                 : 
     425             222 :         err = regcomp(&re, pattern, copts);
     426             222 :         if (err) {
     427              54 :                 php_ereg_eprint(err, &re);
     428              54 :                 return ((char *) -1);
     429                 :         }
     430                 : 
     431                 : 
     432                 :         /* allocate storage for (sub-)expression-matches */
     433             168 :         subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1);
     434                 : 
     435                 :         /* start with a buffer that is twice the size of the stringo
     436                 :            we're doing replacements in */
     437             168 :         buf_len = 2 * string_len + 1;
     438             168 :         buf = safe_emalloc(buf_len, sizeof(char), 0);
     439                 : 
     440             168 :         err = pos = 0;
     441             168 :         buf[0] = '\0';
     442             865 :         while (!err) {
     443             536 :                 err = regexec(&re, &string[pos], re.re_nsub+1, subs, (pos ? REG_NOTBOL : 0));
     444                 : 
     445             536 :                 if (err && err != REG_NOMATCH) {
     446               0 :                         php_ereg_eprint(err, &re);
     447               0 :                         efree(subs);
     448               0 :                         efree(buf);
     449                 :                         regfree(&re);
     450               0 :                         return ((char *) -1);
     451                 :                 }
     452                 : 
     453             536 :                 if (!err) {
     454                 :                         /* backref replacement is done in two passes:
     455                 :                            1) find out how long the string will be, and allocate buf
     456                 :                            2) copy the part before match, replacement and backrefs to buf
     457                 : 
     458                 :                            Jaakko Hyvätti <Jaakko.Hyvatti@iki.fi>
     459                 :                            */
     460                 : 
     461             375 :                         new_l = strlen(buf) + subs[0].rm_so; /* part before the match */
     462             375 :                         walk = replace;
     463            7533 :                         while (*walk) {
     464            6793 :                                 if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
     465              10 :                                         if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1) {
     466              10 :                                                 new_l += subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
     467                 :                                         }
     468              10 :                                         walk += 2;
     469                 :                                 } else {
     470            6773 :                                         new_l++;
     471            6773 :                                         walk++;
     472                 :                                 }
     473                 :                         }
     474             375 :                         if (new_l + 1 > buf_len) {
     475              37 :                                 buf_len = 1 + buf_len + 2 * new_l;
     476              37 :                                 nbuf = emalloc(buf_len);
     477              37 :                                 strcpy(nbuf, buf);
     478              37 :                                 efree(buf);
     479              37 :                                 buf = nbuf;
     480                 :                         }
     481             375 :                         tmp = strlen(buf);
     482                 :                         /* copy the part of the string before the match */
     483             375 :                         strncat(buf, &string[pos], subs[0].rm_so);
     484                 : 
     485                 :                         /* copy replacement and backrefs */
     486             375 :                         walkbuf = &buf[tmp + subs[0].rm_so];
     487             375 :                         walk = replace;
     488            7533 :                         while (*walk) {
     489            6793 :                                 if ('\\' == *walk && isdigit(walk[1]) && walk[1] - '0' <= (int)re.re_nsub) {
     490              10 :                                         if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1
     491                 :                                                 /* this next case shouldn't happen. it does. */
     492                 :                                                 && subs[walk[1] - '0'].rm_so <= subs[walk[1] - '0'].rm_eo) {
     493                 :                                                 
     494              10 :                                                 tmp = subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
     495              10 :                                                 memcpy (walkbuf, &string[pos + subs[walk[1] - '0'].rm_so], tmp);
     496              10 :                                                 walkbuf += tmp;
     497                 :                                         }
     498              10 :                                         walk += 2;
     499                 :                                 } else {
     500            6773 :                                         *walkbuf++ = *walk++;
     501                 :                                 }
     502                 :                         }
     503             375 :                         *walkbuf = '\0';
     504                 : 
     505                 :                         /* and get ready to keep looking for replacements */
     506             375 :                         if (subs[0].rm_so == subs[0].rm_eo) {
     507             144 :                                 if (subs[0].rm_so + pos >= string_len) {
     508               7 :                                         break;
     509                 :                                 }
     510             137 :                                 new_l = strlen (buf) + 1;
     511             137 :                                 if (new_l + 1 > buf_len) {
     512               0 :                                         buf_len = 1 + buf_len + 2 * new_l;
     513               0 :                                         nbuf = safe_emalloc(buf_len, sizeof(char), 0);
     514               0 :                                         strcpy(nbuf, buf);
     515               0 :                                         efree(buf);
     516               0 :                                         buf = nbuf;
     517                 :                                 }
     518             137 :                                 pos += subs[0].rm_eo + 1;
     519             137 :                                 buf [new_l-1] = string [pos-1];
     520             137 :                                 buf [new_l] = '\0';
     521                 :                         } else {
     522             231 :                                 pos += subs[0].rm_eo;
     523                 :                         }
     524                 :                 } else { /* REG_NOMATCH */
     525             161 :                         new_l = strlen(buf) + strlen(&string[pos]);
     526             161 :                         if (new_l + 1 > buf_len) {
     527               8 :                                 buf_len = new_l + 1; /* now we know exactly how long it is */
     528               8 :                                 nbuf = safe_emalloc(buf_len, sizeof(char), 0);
     529               8 :                                 strcpy(nbuf, buf);
     530               8 :                                 efree(buf);
     531               8 :                                 buf = nbuf;
     532                 :                         }
     533                 :                         /* stick that last bit of string on our output */
     534             161 :                         strlcat(buf, &string[pos], buf_len);
     535                 :                 }
     536                 :         }
     537                 : 
     538                 :         /* don't want to leak memory .. */
     539             168 :         efree(subs);
     540                 :         regfree(&re);
     541                 : 
     542                 :         /* whew. */
     543             168 :         return (buf);
     544                 : }
     545                 : /* }}} */
     546                 : 
     547                 : /* {{{ php_do_ereg_replace
     548                 :  */
     549                 : static void php_do_ereg_replace(INTERNAL_FUNCTION_PARAMETERS, int icase)
     550             238 : {
     551                 :         zval **arg_pattern,
     552                 :                 **arg_replace;
     553                 :         char *pattern, *arg_string;
     554                 :         char *string;
     555                 :         char *replace;
     556                 :         char *ret;
     557                 :         int arg_string_len;
     558                 :         
     559             238 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZs", &arg_pattern, &arg_replace, &arg_string, &arg_string_len) == FAILURE) {
     560              16 :                 return;
     561                 :         }
     562                 : 
     563             222 :         if (Z_TYPE_PP(arg_pattern) == IS_STRING) {
     564             346 :                 if (Z_STRVAL_PP(arg_pattern) && Z_STRLEN_PP(arg_pattern)) {
     565             170 :                         pattern = estrndup(Z_STRVAL_PP(arg_pattern), Z_STRLEN_PP(arg_pattern));
     566                 :                 } else {
     567               6 :                         pattern = STR_EMPTY_ALLOC();
     568                 :                 }
     569                 :         } else {
     570              46 :                 convert_to_long_ex(arg_pattern);
     571              46 :                 pattern = emalloc(2);
     572              46 :                 pattern[0] = (char) Z_LVAL_PP(arg_pattern);
     573              46 :                 pattern[1] = '\0';
     574                 :         }
     575                 : 
     576             222 :         if (Z_TYPE_PP(arg_replace) == IS_STRING) {
     577             346 :                 if (Z_STRVAL_PP(arg_replace) && Z_STRLEN_PP(arg_replace)) {
     578             170 :                         replace = estrndup(Z_STRVAL_PP(arg_replace), Z_STRLEN_PP(arg_replace));
     579                 :                 } else {
     580               6 :                         replace = STR_EMPTY_ALLOC();
     581                 :                 }
     582                 :         } else {
     583              46 :                 convert_to_long_ex(arg_replace);
     584              46 :                 replace = emalloc(2);
     585              46 :                 replace[0] = (char) Z_LVAL_PP(arg_replace);
     586              46 :                 replace[1] = '\0';
     587                 :         }
     588                 : 
     589             428 :         if (arg_string && arg_string_len) {
     590             206 :                 string = estrndup(arg_string, arg_string_len);
     591                 :         } else {
     592              16 :                 string = STR_EMPTY_ALLOC();
     593                 :         }
     594                 : 
     595                 :         /* do the actual work */
     596             222 :         ret = php_ereg_replace(pattern, replace, string, icase, 1);
     597             222 :         if (ret == (char *) -1) {
     598              54 :                 RETVAL_FALSE;
     599                 :         } else {
     600             168 :                 RETVAL_STRING(ret, 1);
     601             168 :                 STR_FREE(ret);
     602                 :         }
     603                 : 
     604             222 :         STR_FREE(string);
     605             222 :         STR_FREE(replace);
     606             222 :         STR_FREE(pattern);
     607                 : }
     608                 : /* }}} */
     609                 : 
     610                 : /* {{{ proto string ereg_replace(string pattern, string replacement, string string)
     611                 :    Replace regular expression */
     612                 : PHP_FUNCTION(ereg_replace)
     613             127 : {
     614             127 :         php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     615             127 : }
     616                 : /* }}} */
     617                 : 
     618                 : /* {{{ proto string eregi_replace(string pattern, string replacement, string string)
     619                 :    Case insensitive replace regular expression */
     620                 : PHP_FUNCTION(eregi_replace)
     621             111 : {
     622             111 :         php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     623             111 : }
     624                 : /* }}} */
     625                 : 
     626                 : /* {{{ php_split
     627                 :  */
     628                 : static void php_split(INTERNAL_FUNCTION_PARAMETERS, int icase)
     629             263 : {
     630             263 :         long count = -1;
     631                 :         regex_t re;
     632                 :         regmatch_t subs[1];
     633                 :         char *spliton, *str, *strp, *endp;
     634                 :         int spliton_len, str_len;
     635             263 :         int err, size, copts = 0;
     636                 : 
     637             263 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &spliton, &spliton_len, &str, &str_len, &count) == FAILURE) {
     638              52 :                 return;
     639                 :         }
     640                 : 
     641             211 :         if (icase) {
     642             101 :                 copts = REG_ICASE;
     643                 :         }
     644                 : 
     645             211 :         strp = str;
     646             211 :         endp = strp + str_len;
     647                 : 
     648             211 :         err = regcomp(&re, spliton, REG_EXTENDED | copts);
     649             211 :         if (err) {
     650              42 :                 php_ereg_eprint(err, &re);
     651              42 :                 RETURN_FALSE;
     652                 :         }
     653                 : 
     654             169 :         array_init(return_value);
     655                 : 
     656                 :         /* churn through str, generating array entries as we go */
     657             529 :         while ((count == -1 || count > 1) && !(err = regexec(&re, strp, 1, subs, 0))) {
     658             301 :                 if (subs[0].rm_so == 0 && subs[0].rm_eo) {
     659                 :                         /* match is at start of string, return empty string */
     660             102 :                         add_next_index_stringl(return_value, "", 0, 1);
     661                 :                         /* skip ahead the length of the regex match */
     662             102 :                         strp += subs[0].rm_eo;
     663              97 :                 } else if (subs[0].rm_so == 0 && subs[0].rm_eo == 0) {
     664                 :                         /* No more matches */
     665                 :                         regfree(&re);
     666                 :                         
     667               8 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Regular Expression");
     668                 :                         
     669               8 :                         zend_hash_destroy(Z_ARRVAL_P(return_value));
     670               8 :                         efree(Z_ARRVAL_P(return_value));
     671               8 :                         RETURN_FALSE;
     672                 :                 } else {
     673                 :                         /* On a real match */
     674                 : 
     675                 :                         /* make a copy of the substring */
     676              89 :                         size = subs[0].rm_so;
     677                 :                 
     678                 :                         /* add it to the array */
     679              89 :                         add_next_index_stringl(return_value, strp, size, 1);
     680                 : 
     681                 :                         /* point at our new starting point */
     682              89 :                         strp = strp + subs[0].rm_eo;
     683                 :                 }
     684                 : 
     685                 :                 /* if we're only looking for a certain number of points,
     686                 :                    stop looking once we hit it */
     687             191 :                 if (count != -1) {
     688              60 :                         count--;
     689                 :                 }
     690                 :         }
     691                 : 
     692                 :         /* see if we encountered an error */
     693             161 :         if (err && err != REG_NOMATCH) {
     694               0 :                 php_ereg_eprint(err, &re);
     695                 :                 regfree(&re);
     696               0 :                 zend_hash_destroy(Z_ARRVAL_P(return_value));
     697               0 :                 efree(Z_ARRVAL_P(return_value));
     698               0 :                 RETURN_FALSE;
     699                 :         }
     700                 : 
     701                 :         /* otherwise we just have one last element to add to the array */
     702             161 :         size = endp - strp;
     703                 :         
     704             161 :         add_next_index_stringl(return_value, strp, size, 1);
     705                 : 
     706                 :         regfree(&re);
     707                 : }
     708                 : /* }}} */
     709                 : 
     710                 : /* {{{ proto array split(string pattern, string string [, int limit])
     711                 :    Split string into array by regular expression */
     712                 : PHP_FUNCTION(split)
     713             136 : {
     714             136 :         php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     715             136 : }
     716                 : /* }}} */
     717                 : 
     718                 : /* {{{ proto array spliti(string pattern, string string [, int limit])
     719                 :    Split string into array by regular expression case-insensitive */
     720                 : 
     721                 : PHP_FUNCTION(spliti)
     722             127 : {
     723             127 :         php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     724             127 : }
     725                 : 
     726                 : /* }}} */
     727                 : 
     728                 : /* {{{ proto string sql_regcase(string string)
     729                 :    Make regular expression for case insensitive match */
     730                 : PHPAPI PHP_FUNCTION(sql_regcase)
     731              28 : {
     732                 :         char *string, *tmp;
     733                 :         int string_len;
     734                 :         unsigned char c;
     735                 :         register int i, j;
     736                 : 
     737              28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) {
     738               8 :                 return;
     739                 :         }
     740                 :         
     741              20 :         tmp = safe_emalloc(string_len, 4, 1);
     742                 :         
     743              83 :         for (i = j = 0; i < string_len; i++) {
     744              63 :                 c = (unsigned char) string[i];
     745              63 :                 if (isalpha(c)) {
     746              10 :                         tmp[j++] = '[';
     747              10 :                         tmp[j++] = toupper(c);
     748              10 :                         tmp[j++] = tolower(c);
     749              10 :                         tmp[j++] = ']';
     750                 :                 } else {
     751              53 :                         tmp[j++] = c;
     752                 :                 }
     753                 :         }
     754              20 :         tmp[j] = 0;
     755                 : 
     756              20 :         RETVAL_STRINGL(tmp, j, 1);
     757              20 :         efree(tmp);
     758                 : }
     759                 : /* }}} */
     760                 : 
     761                 : /*
     762                 :  * Local variables:
     763                 :  * tab-width: 4
     764                 :  * c-basic-offset: 4
     765                 :  * End:
     766                 :  * vim600: noet sw=4 ts=4 fdm=marker
     767                 :  * vim<600: noet sw=4 ts=4
     768                 :  */

Generated by: LTP GCOV extension version 1.5

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

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