Annotation of embedaddon/php/ext/ereg/ereg.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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 321634 2012-01-01 13:15:04Z felipe $ */
! 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: PHP_FE_END
! 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: {
! 96: Bucket *f = *((Bucket **) a);
! 97: Bucket *s = *((Bucket **) b);
! 98:
! 99: if (((reg_cache *)f->pData)->lastuse <
! 100: ((reg_cache *)s->pData)->lastuse) {
! 101: return -1;
! 102: } else if (((reg_cache *)f->pData)->lastuse ==
! 103: ((reg_cache *)s->pData)->lastuse) {
! 104: return 0;
! 105: } else {
! 106: return 1;
! 107: }
! 108: }
! 109: /* }}} */
! 110:
! 111: /* {{{ static ereg_clean_cache */
! 112: static int ereg_clean_cache(void *data, void *arg TSRMLS_DC)
! 113: {
! 114: int *num_clean = (int *)arg;
! 115:
! 116: if (*num_clean > 0) {
! 117: (*num_clean)--;
! 118: return ZEND_HASH_APPLY_REMOVE;
! 119: } else {
! 120: 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: {
! 129: int r = 0;
! 130: int patlen = strlen(pattern);
! 131: reg_cache *rc = NULL;
! 132: TSRMLS_FETCH();
! 133:
! 134: if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) {
! 135: /* easier than dealing with overflow as it happens */
! 136: if (EREG(lru_counter) >= (1 << 31) || zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0 TSRMLS_CC) == FAILURE) {
! 137: zend_hash_clean(&EREG(ht_rc));
! 138: EREG(lru_counter) = 0;
! 139: } else {
! 140: int num_clean = EREG_CACHE_SIZE / 4;
! 141: zend_hash_apply_with_argument(&EREG(ht_rc), ereg_clean_cache, &num_clean TSRMLS_CC);
! 142: }
! 143: }
! 144:
! 145: 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: if (rc->preg.re_magic != reg_magic) {
! 153: zend_hash_clean(&EREG(ht_rc));
! 154: EREG(lru_counter) = 0;
! 155: } else {
! 156: memcpy(preg, &rc->preg, sizeof(*preg));
! 157: return r;
! 158: }
! 159: }
! 160:
! 161: r = regcomp(preg, pattern, cflags);
! 162: if(!r) {
! 163: reg_cache rcp;
! 164:
! 165: rcp.cflags = cflags;
! 166: rcp.lastuse = ++(EREG(lru_counter));
! 167: 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: if (!reg_magic) reg_magic = preg->re_magic;
! 174: 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: return r;
! 193: }
! 194: /* }}} */
! 195:
! 196: static void _free_ereg_cache(reg_cache *rc)
! 197: {
! 198: regfree(&rc->preg);
! 199: }
! 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: {
! 208: zend_hash_init(&ereg_globals->ht_rc, 0, NULL, (void (*)(void *)) _free_ereg_cache, 1);
! 209: ereg_globals->lru_counter = 0;
! 210: }
! 211:
! 212: static void php_ereg_destroy_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
! 213: {
! 214: zend_hash_destroy(&ereg_globals->ht_rc);
! 215: }
! 216:
! 217: PHP_MINIT_FUNCTION(ereg)
! 218: {
! 219: ZEND_INIT_MODULE_GLOBALS(ereg, php_ereg_init_globals, php_ereg_destroy_globals);
! 220: return SUCCESS;
! 221: }
! 222:
! 223: PHP_MSHUTDOWN_FUNCTION(ereg)
! 224: {
! 225: #ifndef ZTS
! 226: php_ereg_destroy_globals(&ereg_globals TSRMLS_CC);
! 227: #endif
! 228:
! 229: return SUCCESS;
! 230: }
! 231:
! 232: PHP_MINFO_FUNCTION(ereg)
! 233: {
! 234: php_info_print_table_start();
! 235: #if HSREGEX
! 236: 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: php_info_print_table_end();
! 241: }
! 242:
! 243:
! 244: /* {{{ php_ereg_eprint
! 245: * php_ereg_eprint - convert error number to name
! 246: */
! 247: static void php_ereg_eprint(int err, regex_t *re) {
! 248: 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: buf_len = regerror(REG_ITOA | err, re, NULL, 0);
! 255: if (buf_len) {
! 256: buf = (char *)safe_emalloc(buf_len, sizeof(char), 0);
! 257: if (!buf) return; /* fail silently */
! 258: /* finally, get the error message */
! 259: regerror(REG_ITOA | err, re, buf, buf_len);
! 260: }
! 261: #else
! 262: buf_len = 0;
! 263: #endif
! 264: len = regerror(err, re, NULL, 0);
! 265: if (len) {
! 266: TSRMLS_FETCH();
! 267:
! 268: message = (char *)safe_emalloc((buf_len + len + 2), sizeof(char), 0);
! 269: if (!message) {
! 270: return; /* fail silently */
! 271: }
! 272: if (buf_len) {
! 273: snprintf(message, buf_len, "%s: ", buf);
! 274: buf_len += 1; /* so pointer math below works */
! 275: }
! 276: /* drop the message into place */
! 277: regerror(err, re, message + buf_len, len);
! 278:
! 279: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
! 280: }
! 281:
! 282: STR_FREE(buf);
! 283: STR_FREE(message);
! 284: }
! 285: /* }}} */
! 286:
! 287: /* {{{ php_ereg
! 288: */
! 289: static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
! 290: {
! 291: zval **regex, /* Regular expression */
! 292: **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: int copts = 0;
! 300: off_t start, end;
! 301: char *buf = NULL;
! 302: char *string = NULL;
! 303: int argc = ZEND_NUM_ARGS();
! 304:
! 305: if (zend_parse_parameters(argc TSRMLS_CC, "Zs|Z", ®ex, &findin, &findin_len, &array) == FAILURE) {
! 306: return;
! 307: }
! 308:
! 309: if (icase) {
! 310: copts |= REG_ICASE;
! 311: }
! 312:
! 313: if (argc == 2) {
! 314: copts |= REG_NOSUB;
! 315: }
! 316:
! 317: /* compile the regular expression from the supplied regex */
! 318: if (Z_TYPE_PP(regex) == IS_STRING) {
! 319: 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: if (Z_TYPE_PP(regex) == IS_DOUBLE) {
! 323: convert_to_long_ex(regex); /* get rid of decimal places */
! 324: }
! 325: convert_to_string_ex(regex);
! 326: /* don't bother doing an extended regex with just a number */
! 327: err = regcomp(&re, Z_STRVAL_PP(regex), copts);
! 328: }
! 329:
! 330: if (err) {
! 331: php_ereg_eprint(err, &re);
! 332: RETURN_FALSE;
! 333: }
! 334:
! 335: /* make a copy of the string we're looking in */
! 336: string = estrndup(findin, findin_len);
! 337:
! 338: /* allocate storage for (sub-)expression-matches */
! 339: subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1);
! 340:
! 341: /* actually execute the regular expression */
! 342: err = regexec(&re, string, re.re_nsub+1, subs, 0);
! 343: if (err && err != REG_NOMATCH) {
! 344: php_ereg_eprint(err, &re);
! 345: regfree(&re);
! 346: efree(subs);
! 347: RETURN_FALSE;
! 348: }
! 349: match_len = 1;
! 350:
! 351: if (array && err != REG_NOMATCH) {
! 352: match_len = (int) (subs[0].rm_eo - subs[0].rm_so);
! 353: string_len = findin_len + 1;
! 354:
! 355: buf = emalloc(string_len);
! 356:
! 357: zval_dtor(*array); /* start with clean array */
! 358: array_init(*array);
! 359:
! 360: for (i = 0; i <= re.re_nsub; i++) {
! 361: start = subs[i].rm_so;
! 362: end = subs[i].rm_eo;
! 363: if (start != -1 && end > 0 && start < string_len && end < string_len && start < end) {
! 364: add_index_stringl(*array, i, string+start, end-start, 1);
! 365: } else {
! 366: add_index_bool(*array, i, 0);
! 367: }
! 368: }
! 369: efree(buf);
! 370: }
! 371:
! 372: efree(subs);
! 373: efree(string);
! 374: if (err == REG_NOMATCH) {
! 375: RETVAL_FALSE;
! 376: } else {
! 377: if (match_len == 0)
! 378: match_len = 1;
! 379: 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: {
! 389: php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 390: }
! 391: /* }}} */
! 392:
! 393: /* {{{ proto int eregi(string pattern, string string [, array registers])
! 394: Case-insensitive regular expression match */
! 395: PHP_FUNCTION(eregi)
! 396: {
! 397: php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 398: }
! 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: {
! 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: int err, copts = 0;
! 415:
! 416: string_len = strlen(string);
! 417:
! 418: if (icase) {
! 419: copts = REG_ICASE;
! 420: }
! 421: if (extended) {
! 422: copts |= REG_EXTENDED;
! 423: }
! 424:
! 425: err = regcomp(&re, pattern, copts);
! 426: if (err) {
! 427: php_ereg_eprint(err, &re);
! 428: return ((char *) -1);
! 429: }
! 430:
! 431:
! 432: /* allocate storage for (sub-)expression-matches */
! 433: 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: buf_len = 2 * string_len + 1;
! 438: buf = safe_emalloc(buf_len, sizeof(char), 0);
! 439:
! 440: err = pos = 0;
! 441: buf[0] = '\0';
! 442: while (!err) {
! 443: err = regexec(&re, &string[pos], re.re_nsub+1, subs, (pos ? REG_NOTBOL : 0));
! 444:
! 445: if (err && err != REG_NOMATCH) {
! 446: php_ereg_eprint(err, &re);
! 447: efree(subs);
! 448: efree(buf);
! 449: regfree(&re);
! 450: return ((char *) -1);
! 451: }
! 452:
! 453: 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: new_l = strlen(buf) + subs[0].rm_so; /* part before the match */
! 462: walk = replace;
! 463: while (*walk) {
! 464: if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
! 465: if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1) {
! 466: new_l += subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
! 467: }
! 468: walk += 2;
! 469: } else {
! 470: new_l++;
! 471: walk++;
! 472: }
! 473: }
! 474: if (new_l + 1 > buf_len) {
! 475: buf_len = 1 + buf_len + 2 * new_l;
! 476: nbuf = emalloc(buf_len);
! 477: strncpy(nbuf, buf, buf_len-1);
! 478: nbuf[buf_len - 1] = '\0';
! 479: efree(buf);
! 480: buf = nbuf;
! 481: }
! 482: tmp = strlen(buf);
! 483: /* copy the part of the string before the match */
! 484: strncat(buf, &string[pos], subs[0].rm_so);
! 485:
! 486: /* copy replacement and backrefs */
! 487: walkbuf = &buf[tmp + subs[0].rm_so];
! 488: walk = replace;
! 489: while (*walk) {
! 490: if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
! 491: if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1
! 492: /* this next case shouldn't happen. it does. */
! 493: && subs[walk[1] - '0'].rm_so <= subs[walk[1] - '0'].rm_eo) {
! 494:
! 495: tmp = subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
! 496: memcpy (walkbuf, &string[pos + subs[walk[1] - '0'].rm_so], tmp);
! 497: walkbuf += tmp;
! 498: }
! 499: walk += 2;
! 500: } else {
! 501: *walkbuf++ = *walk++;
! 502: }
! 503: }
! 504: *walkbuf = '\0';
! 505:
! 506: /* and get ready to keep looking for replacements */
! 507: if (subs[0].rm_so == subs[0].rm_eo) {
! 508: if (subs[0].rm_so + pos >= string_len) {
! 509: break;
! 510: }
! 511: new_l = strlen (buf) + 1;
! 512: if (new_l + 1 > buf_len) {
! 513: buf_len = 1 + buf_len + 2 * new_l;
! 514: nbuf = safe_emalloc(buf_len, sizeof(char), 0);
! 515: strncpy(nbuf, buf, buf_len-1);
! 516: efree(buf);
! 517: buf = nbuf;
! 518: }
! 519: pos += subs[0].rm_eo + 1;
! 520: buf [new_l-1] = string [pos-1];
! 521: buf [new_l] = '\0';
! 522: } else {
! 523: pos += subs[0].rm_eo;
! 524: }
! 525: } else { /* REG_NOMATCH */
! 526: new_l = strlen(buf) + strlen(&string[pos]);
! 527: if (new_l + 1 > buf_len) {
! 528: buf_len = new_l + 1; /* now we know exactly how long it is */
! 529: nbuf = safe_emalloc(buf_len, sizeof(char), 0);
! 530: strncpy(nbuf, buf, buf_len-1);
! 531: efree(buf);
! 532: buf = nbuf;
! 533: }
! 534: /* stick that last bit of string on our output */
! 535: strlcat(buf, &string[pos], buf_len);
! 536: }
! 537: }
! 538:
! 539: /* don't want to leak memory .. */
! 540: efree(subs);
! 541: regfree(&re);
! 542:
! 543: /* whew. */
! 544: return (buf);
! 545: }
! 546: /* }}} */
! 547:
! 548: /* {{{ php_do_ereg_replace
! 549: */
! 550: static void php_do_ereg_replace(INTERNAL_FUNCTION_PARAMETERS, int icase)
! 551: {
! 552: zval **arg_pattern,
! 553: **arg_replace;
! 554: char *pattern, *arg_string;
! 555: char *string;
! 556: char *replace;
! 557: char *ret;
! 558: int arg_string_len;
! 559:
! 560: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZs", &arg_pattern, &arg_replace, &arg_string, &arg_string_len) == FAILURE) {
! 561: return;
! 562: }
! 563:
! 564: if (Z_TYPE_PP(arg_pattern) == IS_STRING) {
! 565: if (Z_STRVAL_PP(arg_pattern) && Z_STRLEN_PP(arg_pattern)) {
! 566: pattern = estrndup(Z_STRVAL_PP(arg_pattern), Z_STRLEN_PP(arg_pattern));
! 567: } else {
! 568: pattern = STR_EMPTY_ALLOC();
! 569: }
! 570: } else {
! 571: convert_to_long_ex(arg_pattern);
! 572: pattern = emalloc(2);
! 573: pattern[0] = (char) Z_LVAL_PP(arg_pattern);
! 574: pattern[1] = '\0';
! 575: }
! 576:
! 577: if (Z_TYPE_PP(arg_replace) == IS_STRING) {
! 578: if (Z_STRVAL_PP(arg_replace) && Z_STRLEN_PP(arg_replace)) {
! 579: replace = estrndup(Z_STRVAL_PP(arg_replace), Z_STRLEN_PP(arg_replace));
! 580: } else {
! 581: replace = STR_EMPTY_ALLOC();
! 582: }
! 583: } else {
! 584: convert_to_long_ex(arg_replace);
! 585: replace = emalloc(2);
! 586: replace[0] = (char) Z_LVAL_PP(arg_replace);
! 587: replace[1] = '\0';
! 588: }
! 589:
! 590: if (arg_string && arg_string_len) {
! 591: string = estrndup(arg_string, arg_string_len);
! 592: } else {
! 593: string = STR_EMPTY_ALLOC();
! 594: }
! 595:
! 596: /* do the actual work */
! 597: ret = php_ereg_replace(pattern, replace, string, icase, 1);
! 598: if (ret == (char *) -1) {
! 599: RETVAL_FALSE;
! 600: } else {
! 601: RETVAL_STRING(ret, 1);
! 602: STR_FREE(ret);
! 603: }
! 604:
! 605: STR_FREE(string);
! 606: STR_FREE(replace);
! 607: STR_FREE(pattern);
! 608: }
! 609: /* }}} */
! 610:
! 611: /* {{{ proto string ereg_replace(string pattern, string replacement, string string)
! 612: Replace regular expression */
! 613: PHP_FUNCTION(ereg_replace)
! 614: {
! 615: php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 616: }
! 617: /* }}} */
! 618:
! 619: /* {{{ proto string eregi_replace(string pattern, string replacement, string string)
! 620: Case insensitive replace regular expression */
! 621: PHP_FUNCTION(eregi_replace)
! 622: {
! 623: php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 624: }
! 625: /* }}} */
! 626:
! 627: /* {{{ php_split
! 628: */
! 629: static void php_split(INTERNAL_FUNCTION_PARAMETERS, int icase)
! 630: {
! 631: long count = -1;
! 632: regex_t re;
! 633: regmatch_t subs[1];
! 634: char *spliton, *str, *strp, *endp;
! 635: int spliton_len, str_len;
! 636: int err, size, copts = 0;
! 637:
! 638: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &spliton, &spliton_len, &str, &str_len, &count) == FAILURE) {
! 639: return;
! 640: }
! 641:
! 642: if (icase) {
! 643: copts = REG_ICASE;
! 644: }
! 645:
! 646: strp = str;
! 647: endp = strp + str_len;
! 648:
! 649: err = regcomp(&re, spliton, REG_EXTENDED | copts);
! 650: if (err) {
! 651: php_ereg_eprint(err, &re);
! 652: RETURN_FALSE;
! 653: }
! 654:
! 655: array_init(return_value);
! 656:
! 657: /* churn through str, generating array entries as we go */
! 658: while ((count == -1 || count > 1) && !(err = regexec(&re, strp, 1, subs, 0))) {
! 659: if (subs[0].rm_so == 0 && subs[0].rm_eo) {
! 660: /* match is at start of string, return empty string */
! 661: add_next_index_stringl(return_value, "", 0, 1);
! 662: /* skip ahead the length of the regex match */
! 663: strp += subs[0].rm_eo;
! 664: } else if (subs[0].rm_so == 0 && subs[0].rm_eo == 0) {
! 665: /* No more matches */
! 666: regfree(&re);
! 667:
! 668: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Regular Expression");
! 669:
! 670: zend_hash_destroy(Z_ARRVAL_P(return_value));
! 671: efree(Z_ARRVAL_P(return_value));
! 672: RETURN_FALSE;
! 673: } else {
! 674: /* On a real match */
! 675:
! 676: /* make a copy of the substring */
! 677: size = subs[0].rm_so;
! 678:
! 679: /* add it to the array */
! 680: add_next_index_stringl(return_value, strp, size, 1);
! 681:
! 682: /* point at our new starting point */
! 683: strp = strp + subs[0].rm_eo;
! 684: }
! 685:
! 686: /* if we're only looking for a certain number of points,
! 687: stop looking once we hit it */
! 688: if (count != -1) {
! 689: count--;
! 690: }
! 691: }
! 692:
! 693: /* see if we encountered an error */
! 694: if (err && err != REG_NOMATCH) {
! 695: php_ereg_eprint(err, &re);
! 696: regfree(&re);
! 697: zend_hash_destroy(Z_ARRVAL_P(return_value));
! 698: efree(Z_ARRVAL_P(return_value));
! 699: RETURN_FALSE;
! 700: }
! 701:
! 702: /* otherwise we just have one last element to add to the array */
! 703: size = endp - strp;
! 704:
! 705: add_next_index_stringl(return_value, strp, size, 1);
! 706:
! 707: regfree(&re);
! 708: }
! 709: /* }}} */
! 710:
! 711: /* {{{ proto array split(string pattern, string string [, int limit])
! 712: Split string into array by regular expression */
! 713: PHP_FUNCTION(split)
! 714: {
! 715: php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 716: }
! 717: /* }}} */
! 718:
! 719: /* {{{ proto array spliti(string pattern, string string [, int limit])
! 720: Split string into array by regular expression case-insensitive */
! 721:
! 722: PHP_FUNCTION(spliti)
! 723: {
! 724: php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 725: }
! 726:
! 727: /* }}} */
! 728:
! 729: /* {{{ proto string sql_regcase(string string)
! 730: Make regular expression for case insensitive match */
! 731: PHPAPI PHP_FUNCTION(sql_regcase)
! 732: {
! 733: char *string, *tmp;
! 734: int string_len;
! 735: unsigned char c;
! 736: register int i, j;
! 737:
! 738: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) {
! 739: return;
! 740: }
! 741:
! 742: tmp = safe_emalloc(string_len, 4, 1);
! 743:
! 744: for (i = j = 0; i < string_len; i++) {
! 745: c = (unsigned char) string[i];
! 746: if (isalpha(c)) {
! 747: tmp[j++] = '[';
! 748: tmp[j++] = toupper(c);
! 749: tmp[j++] = tolower(c);
! 750: tmp[j++] = ']';
! 751: } else {
! 752: tmp[j++] = c;
! 753: }
! 754: }
! 755: tmp[j] = 0;
! 756:
! 757: RETVAL_STRINGL(tmp, j, 1);
! 758: efree(tmp);
! 759: }
! 760: /* }}} */
! 761:
! 762: /*
! 763: * Local variables:
! 764: * tab-width: 4
! 765: * c-basic-offset: 4
! 766: * End:
! 767: * vim600: noet sw=4 ts=4 fdm=marker
! 768: * vim<600: noet sw=4 ts=4
! 769: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>