📄 reg.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | | Jim Winstead <jimw@php.net> | | Jaakko Hyv鋞ti <jaakko@hyvatti.iki.fi> | +----------------------------------------------------------------------+ *//* $Id: reg.c,v 1.66.2.8.2.3 2007/01/01 09:46:48 sebastian Exp $ */#include <stdio.h>#include <ctype.h>#include "php.h"#include "php_string.h"#include "reg.h"#include "ext/standard/info.h"ZEND_DECLARE_MODULE_GLOBALS(reg)typedef struct { regex_t preg; int cflags;} reg_cache;static int reg_magic = 0;/* {{{ _php_regcomp */static int _php_regcomp(regex_t *preg, const char *pattern, int cflags){ int r = 0; int patlen = strlen(pattern); reg_cache *rc = NULL; TSRMLS_FETCH(); if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS && rc->cflags == cflags) {#ifdef HAVE_REGEX_T_RE_MAGIC /* * We use a saved magic number to see whether cache is corrupted, and if it * is, we flush it and compile the pattern from scratch. */ if (rc->preg.re_magic != reg_magic) { zend_hash_clean(®(ht_rc)); } else { memcpy(preg, &rc->preg, sizeof(*preg)); return r; } } r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; rcp.cflags = cflags; memcpy(&rcp.preg, preg, sizeof(*preg)); /* * Since we don't have access to the actual MAGIC1 definition in the private * header file, we save the magic value immediately after compilation. Hopefully, * it's good. */ if (!reg_magic) reg_magic = preg->re_magic; zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, (void *) &rcp, sizeof(rcp), NULL); }#else memcpy(preg, &rc->preg, sizeof(*preg)); } else { r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; rcp.cflags = cflags; memcpy(&rcp.preg, preg, sizeof(*preg)); zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, (void *) &rcp, sizeof(rcp), NULL); } }#endif return r;}/* }}} */static void _free_reg_cache(reg_cache *rc) { regfree(&rc->preg);}#undef regfree#define regfree(a);#undef regcomp#define regcomp(a, b, c) _php_regcomp(a, b, c) static void php_reg_init_globals(zend_reg_globals *reg_globals TSRMLS_DC){ zend_hash_init(®_globals->ht_rc, 0, NULL, (void (*)(void *)) _free_reg_cache, 1);}static void php_reg_destroy_globals(zend_reg_globals *reg_globals TSRMLS_DC){ zend_hash_destroy(®_globals->ht_rc);}PHP_MINIT_FUNCTION(regex){ ZEND_INIT_MODULE_GLOBALS(reg, php_reg_init_globals, php_reg_destroy_globals); return SUCCESS;}PHP_MSHUTDOWN_FUNCTION(regex){#ifndef ZTS php_reg_destroy_globals(®_globals TSRMLS_CC);#endif return SUCCESS;}PHP_MINFO_FUNCTION(regex){#if HSREGEX php_info_print_table_row(2, "Regex Library", "Bundled library enabled");#else php_info_print_table_row(2, "Regex Library", "System library enabled");#endif}/* {{{ php_reg_eprint * php_reg_eprint - convert error number to name */static void php_reg_eprint(int err, regex_t *re) { char *buf = NULL, *message = NULL; size_t len; size_t buf_len;#ifdef REG_ITOA /* get the length of the message */ buf_len = regerror(REG_ITOA | err, re, NULL, 0); if (buf_len) { buf = (char *)safe_emalloc(buf_len, sizeof(char), 0); if (!buf) return; /* fail silently */ /* finally, get the error message */ regerror(REG_ITOA | err, re, buf, buf_len); }#else buf_len = 0;#endif len = regerror(err, re, NULL, 0); if (len) { TSRMLS_FETCH(); message = (char *)safe_emalloc((buf_len + len + 2), sizeof(char), 0); if (!message) { return; /* fail silently */ } if (buf_len) { snprintf(message, buf_len, "%s: ", buf); buf_len += 1; /* so pointer math below works */ } /* drop the message into place */ regerror(err, re, message + buf_len, len); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message); } STR_FREE(buf); STR_FREE(message);}/* }}} *//* {{{ php_ereg */static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase){ pval **regex, /* Regular expression */ **findin, /* String to apply expression to */ **array = NULL; /* Optional register array */ regex_t re; regmatch_t *subs; int err, match_len, string_len; uint i; int copts = 0; off_t start, end; char *buf = NULL; char *string = NULL; int argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, ®ex, &findin, &array) == FAILURE) { WRONG_PARAM_COUNT; } if (icase) copts |= REG_ICASE; if (argc == 2) copts |= REG_NOSUB; /* compile the regular expression from the supplied regex */ if (Z_TYPE_PP(regex) == IS_STRING) { err = regcomp(&re, Z_STRVAL_PP(regex), REG_EXTENDED | copts); } else { /* we convert numbers to integers and treat them as a string */ if (Z_TYPE_PP(regex) == IS_DOUBLE) convert_to_long_ex(regex); /* get rid of decimal places */ convert_to_string_ex(regex); /* don't bother doing an extended regex with just a number */ err = regcomp(&re, Z_STRVAL_PP(regex), copts); } if (err) { php_reg_eprint(err, &re); RETURN_FALSE; } /* make a copy of the string we're looking in */ convert_to_string_ex(findin); string = estrndup(Z_STRVAL_PP(findin), Z_STRLEN_PP(findin)); /* allocate storage for (sub-)expression-matches */ subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1); /* actually execute the regular expression */ err = regexec(&re, string, re.re_nsub+1, subs, 0); if (err && err != REG_NOMATCH) { php_reg_eprint(err, &re); regfree(&re); efree(subs); RETURN_FALSE; } match_len = 1; if (array && err != REG_NOMATCH) { match_len = (int) (subs[0].rm_eo - subs[0].rm_so); string_len = Z_STRLEN_PP(findin) + 1; buf = emalloc(string_len); zval_dtor(*array); /* start with clean array */ array_init(*array); for (i = 0; i <= re.re_nsub; i++) { start = subs[i].rm_so; end = subs[i].rm_eo; if (start != -1 && end > 0 && start < string_len && end < string_len && start < end) { add_index_stringl(*array, i, string+start, end-start, 1); } else { add_index_bool(*array, i, 0); } } efree(buf); } efree(subs); efree(string); if (err == REG_NOMATCH) { RETVAL_FALSE; } else { if (match_len == 0) match_len = 1; RETVAL_LONG(match_len); } regfree(&re);}/* }}} *//* {{{ proto int ereg(string pattern, string string [, array registers]) Regular expression match */PHP_FUNCTION(ereg){ php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);}/* }}} *//* {{{ proto int eregi(string pattern, string string [, array registers]) Case-insensitive regular expression match */PHP_FUNCTION(eregi){ php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);}/* }}} *//* {{{ php_reg_replace * this is the meat and potatoes of regex replacement! */PHPAPI char *php_reg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended){ regex_t re; regmatch_t *subs; char *buf, /* buf is where we build the replaced string */ *nbuf, /* nbuf is used when we grow the buffer */ *walkbuf; /* used to walk buf when replacing backrefs */ const char *walk; /* used to walk replacement string for backrefs */ int buf_len; int pos, tmp, string_len, new_l; int err, copts = 0; string_len = strlen(string); if (icase) { copts = REG_ICASE; } if (extended) { copts |= REG_EXTENDED; } err = regcomp(&re, pattern, copts); if (err) { php_reg_eprint(err, &re); return ((char *) -1); } /* allocate storage for (sub-)expression-matches */ subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1); /* start with a buffer that is twice the size of the stringo we're doing replacements in */ buf_len = 2 * string_len + 1; buf = safe_emalloc(buf_len, sizeof(char), 0); err = pos = 0; buf[0] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -