From 4f4b983a39be26e7a94ebcffb6948e040b57de0f Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Wed, 12 Jun 2002 20:04:20 +0000 Subject: [PATCH] This patch adds ability to capture string offsets in the preg_match_*() results. --- NEWS | 2 + ext/pcre/php_pcre.c | 99 ++++++++++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/NEWS b/NEWS index 4cf55b3041..19929f98c9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP 4 NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2002, Version 4.3.0 +- Added ability to capture string offsets in preg_match_*() results. + (David Brown, Andrei) - Fixed set_error_handler() to accept methods as callbacks and also report invalid callbacks. (Andrei) - Fixed a memory corruption bug in overload extension. (Andrei) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 30646f6464..d8a4df8e5d 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -32,8 +32,9 @@ #include "ext/standard/php_string.h" -#define PREG_PATTERN_ORDER 0 -#define PREG_SET_ORDER 1 +#define PREG_PATTERN_ORDER 1 +#define PREG_SET_ORDER 2 +#define PREG_OFFSET_CAPTURE (1<<8) #define PREG_SPLIT_NO_EMPTY (1<<0) #define PREG_SPLIT_DELIM_CAPTURE (1<<1) @@ -99,6 +100,7 @@ static PHP_MINIT_FUNCTION(pcre) REGISTER_LONG_CONSTANT("PREG_PATTERN_ORDER", PREG_PATTERN_ORDER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PREG_SET_ORDER", PREG_SET_ORDER, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PREG_OFFSET_CAPTURE", PREG_OFFSET_CAPTURE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PREG_SPLIT_NO_EMPTY", PREG_SPLIT_NO_EMPTY, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PREG_SPLIT_DELIM_CAPTURE", PREG_SPLIT_DELIM_CAPTURE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PREG_SPLIT_OFFSET_CAPTURE", PREG_SPLIT_OFFSET_CAPTURE, CONST_CS | CONST_PERSISTENT); @@ -310,6 +312,21 @@ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_ } /* }}} */ +static inline void add_offset_pair(zval *result, char *str, int len, int offset) +{ + zval *match_pair; + + ALLOC_ZVAL(match_pair); + array_init(match_pair); + INIT_PZVAL(match_pair); + + /* Add (match, offset) to the return value */ + add_next_index_stringl(match_pair, str, len, 1); + add_next_index_long(match_pair, offset); + + zend_hash_next_index_insert(Z_ARRVAL_P(result), &match_pair, sizeof(zval *), NULL); +} + /* {{{ php_pcre_match */ static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) @@ -317,8 +334,7 @@ static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) zval **regex, /* Regular expression */ **subject, /* String to match against */ **subpats = NULL, /* Array for subpatterns */ - **subpats_order, /* Order of the results in the subpatterns - array for global match */ + **flags, /* Match control flags */ *result_set, /* Holds a set of subpatterns after a global match */ **match_sets = NULL; /* An array of sets of matches for each @@ -334,7 +350,8 @@ static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) int start_offset; /* Where the new search starts */ int matched; /* Has anything matched */ int i; - int subpats_order_val = 0; /* Integer value of subpats_order */ + int subpats_order = 0; /* Order of subpattern matches */ + int offset_capture = 0;/* Capture match offsets: yes/no */ int g_notempty = 0; /* If the match should not be empty */ const char **stringlist; /* Used to hold list of subpatterns */ char *match; /* The current match */ @@ -353,20 +370,21 @@ static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) WRONG_PARAM_COUNT; } if (global) - subpats_order_val = PREG_PATTERN_ORDER; + subpats_order = PREG_PATTERN_ORDER; break; case 4: - if (zend_get_parameters_ex(4, ®ex, &subject, &subpats, &subpats_order) == FAILURE) { + if (zend_get_parameters_ex(4, ®ex, &subject, &subpats, &flags) == FAILURE) { WRONG_PARAM_COUNT; } - /* Make sure subpats_order is a number */ - convert_to_long_ex(subpats_order); - subpats_order_val = Z_LVAL_PP(subpats_order); - if (subpats_order_val < PREG_PATTERN_ORDER || - subpats_order_val > PREG_SET_ORDER) { - zend_error(E_WARNING, "Wrong value for parameter 4 in call to preg_match_all()"); + convert_to_long_ex(flags); + offset_capture = Z_LVAL_PP(flags) & PREG_OFFSET_CAPTURE; + subpats_order = Z_LVAL_PP(flags) & 0xff; + if ((global && (subpats_order < PREG_PATTERN_ORDER || subpats_order > PREG_SET_ORDER)) || + (!global && subpats_order != 0)) { + zend_error(E_WARNING, "Wrong value for parameter 4 in call to %s()", get_active_function_name()); + return; } break; @@ -396,7 +414,7 @@ static void php_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) offsets = (int *)emalloc(size_offsets * sizeof(int)); /* Allocate match sets array and initialize the values */ - if (global && subpats_order_val == PREG_PATTERN_ORDER) { + if (global && subpats_order == PREG_PATTERN_ORDER) { match_sets = (zval **)emalloc(num_subpats * sizeof(zval *)); for (i=0; i