]> granicus.if.org Git - php/commitdiff
Implement preg_replace_callback_array function
authorWei Dai <demon@php.net>
Fri, 13 Mar 2015 03:52:36 +0000 (11:52 +0800)
committerWei Dai <demon@php.net>
Fri, 13 Mar 2015 03:52:36 +0000 (11:52 +0800)
Zend/zend_vm_gen.php
ext/pcre/php_pcre.c
ext/pcre/tests/preg_replace_callback_array.phpt [new file with mode: 0644]
ext/pcre/tests/preg_replace_callback_array2.phpt [new file with mode: 0644]
ext/pcre/tests/preg_replace_callback_array3.phpt [new file with mode: 0644]
ext/pcre/tests/preg_replace_callback_array4.phpt [new file with mode: 0644]
sapi/cli/tests/006.phpt

index 65b1c72c067df3b2078943126dd391f7557c0f6c..de663573636151f7c93ed94f086d288151b6ab5f 100644 (file)
@@ -519,67 +519,56 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
        // Updating code according to selected threading model
        switch($kind) {
                case ZEND_VM_KIND_CALL:
-                       $code = preg_replace_callback(
+                       $code = preg_replace_callback_array(
                                array(
-                                       "/EXECUTE_DATA/m",
-                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*[A-Za-z_]*\s*,\s*(.*)\s*\);/m",
-                               ),
-                               function($matches) use ($spec, $prefix, $op1, $op2) {
-                                       if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
-                                               return "execute_data";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
+                                       "/EXECUTE_DATA/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
+                                                return "execute_data";
+                                        },
+                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "return " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
-                                               return "return " . helper_name($matches[1], $spec, $op1, $op2) . "(" . $matches[2]. ", ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);";
-                                       } else {
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "return " . helper_name($matches[1], $spec, $op1, $op2) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)";
-                                       }
-                               },
-                               $code);
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*[A-Za-z_]*\s*,\s*(.*)\s*\);/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
+                                               return "return " . helper_name($matches[1], $spec, $op1, $op2) . "(" . $matches[2]. ", ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);";
+                                       },
+                               ), $code);
                        break;
                case ZEND_VM_KIND_SWITCH:
-                       $code = preg_replace_callback(
+                       $code = preg_replace_callback_array(
                                array(
-                                       "/EXECUTE_DATA/m",
-                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m",
-                               ),
-                               function($matches) use ($spec, $prefix, $op1, $op2) {
-                                       if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
+                                       "/EXECUTE_DATA/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "execute_data";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_LABEL";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
-                                               return $matches[2] . " = " . $matches[3] .  "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
-                                       } else {
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "goto " . helper_name($matches[1], $spec, $op1, $op2);
-                                       }
-                               },
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
+                                               return $matches[2] . " = " . $matches[3] .  "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
+                                       },
+                               ),
                                        $code);
                        break;
                case ZEND_VM_KIND_GOTO:
-                       $code = preg_replace_callback(
+                       $code = preg_replace_callback_array(
                                array(
-                                       "/EXECUTE_DATA/m",
-                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
-                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m",
-                               ),
-                               function($matches) use ($spec, $prefix, $op1, $op2) {
-                                       if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
-                                               return "execute_data";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
+                                       "/EXECUTE_DATA/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
+                                                return "execute_data";
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER";
-                                       } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
-                                               return $matches[2] . " = " . $matches[3] .  "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
-                                       } else {
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
                                                return "goto " . helper_name($matches[1], $spec, $op1, $op2);
-                                       }
-                               },
-                                       $code);
+                                       },
+                                       "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m" => function($matches) use ($spec, $prefix, $op1, $op2) {
+                                               return $matches[2] . " = " . $matches[3] .  "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
+                                       },
+                               ), $code);
                        break;
        }
 
index 27440bb49049400816243ccb1148f7a6553a0f0c..5f579e000410b48ddcd7fe020d4a9d902548fba3 100644 (file)
@@ -1353,37 +1353,16 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
 
 /* {{{ preg_replace_impl
  */
-static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_replace, int is_filter)
+static void preg_replace_impl(zval *return_value, int argc, zval *regex, zval *replace, zval *subject, zend_long limit, zval *zcount, int is_callable_replace, int is_filter)
 {
-       zval                *regex,
-                                   *replace,
-                                   *subject,
-                                   *subject_entry,
-                                   *zcount = NULL;
+       zval                    *subject_entry;
        int                              limit_val = -1;
-       zend_long                limit = -1;
        zend_string             *result;
        zend_string             *string_key;
        zend_ulong               num_key;
        zend_string             *callback_name;
        int                              replace_count=0, old_replace_count;
 
-#ifndef FAST_ZPP
-       /* Get function parameters and do error-checking. */
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
-               return;
-       }
-#else
-       ZEND_PARSE_PARAMETERS_START(3, 5)
-               Z_PARAM_ZVAL(regex)
-               Z_PARAM_ZVAL(replace)
-               Z_PARAM_ZVAL(subject)
-               Z_PARAM_OPTIONAL
-               Z_PARAM_LONG(limit)
-               Z_PARAM_ZVAL_EX(zcount, 0, 1)
-       ZEND_PARSE_PARAMETERS_END();
-#endif
-
        if (!is_callable_replace && Z_TYPE_P(replace) == IS_ARRAY && Z_TYPE_P(regex) != IS_ARRAY) {
                php_error_docref(NULL, E_WARNING, "Parameter mismatch, pattern is a string while replacement is an array");
                RETURN_FALSE;
@@ -1403,7 +1382,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
                zend_string_release(callback_name);
        }
 
-       if (ZEND_NUM_ARGS() > 3) {
+       if (argc > 3) {
                limit_val = (int)limit;
        }
 
@@ -1433,7 +1412,8 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
                                }
                        }
                } ZEND_HASH_FOREACH_END();
-       } else {        /* if subject is not an array */
+       } else {        
+               /* if subject is not an array */
                old_replace_count = replace_count;
                if ((result = php_replace_in_subject(regex, replace, subject, limit_val, is_callable_replace, &replace_count)) != NULL) {
                        if (!is_filter || replace_count > old_replace_count) {
@@ -1443,11 +1423,10 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
                        }
                }
        }
-       if (ZEND_NUM_ARGS() > 4) {
+       if (argc > 4) {
                zval_dtor(zcount);
                ZVAL_LONG(zcount, replace_count);
        }
-
 }
 /* }}} */
 
@@ -1455,7 +1434,26 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
    Perform Perl-style regular expression replacement. */
 static PHP_FUNCTION(preg_replace)
 {
-       preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
+       zval *regex, *replace, *subject, *zcount = NULL;
+       zend_long limit = -1;
+
+#ifndef FAST_ZPP
+       /* Get function parameters and do error-checking. */
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
+               return;
+       }
+#else
+       ZEND_PARSE_PARAMETERS_START(3, 5)
+               Z_PARAM_ZVAL(regex)
+               Z_PARAM_ZVAL(replace)
+               Z_PARAM_ZVAL(subject)
+               Z_PARAM_OPTIONAL
+               Z_PARAM_LONG(limit)
+               Z_PARAM_ZVAL_EX(zcount, 0, 1)
+       ZEND_PARSE_PARAMETERS_END();
+#endif
+
+       preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 0, 0);
 }
 /* }}} */
 
@@ -1463,7 +1461,84 @@ static PHP_FUNCTION(preg_replace)
    Perform Perl-style regular expression replacement using replacement callback. */
 static PHP_FUNCTION(preg_replace_callback)
 {
-       preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
+       zval *regex, *replace, *subject, *zcount = NULL;
+       zend_long limit = -1;
+
+#ifndef FAST_ZPP
+       /* Get function parameters and do error-checking. */
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
+               return;
+       }    
+#else
+       ZEND_PARSE_PARAMETERS_START(3, 5)
+               Z_PARAM_ZVAL(regex)
+               Z_PARAM_ZVAL(replace)
+               Z_PARAM_ZVAL(subject)
+               Z_PARAM_OPTIONAL
+               Z_PARAM_LONG(limit)
+               Z_PARAM_ZVAL_EX(zcount, 0, 1)
+       ZEND_PARSE_PARAMETERS_END();
+#endif
+
+       preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 1, 0);
+}
+/* }}} */
+
+/* {{{ proto mixed preg_replace_callback_array(array pattern, mixed subject [, int limit [, int &count]])
+   Perform Perl-style regular expression replacement using replacement callback. */
+static PHP_FUNCTION(preg_replace_callback_array)
+{
+       zval regex, tmp_ret, *replace, *subject, *pattern, *zcount = NULL;
+       zend_long limit = -1;
+       zend_ulong num_idx, count = 0;
+       zend_string *str_idx;
+       int argc;
+
+#ifndef FAST_ZPP
+       /* Get function parameters and do error-checking. */
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "az|lz/", &pattern, &subject, &limit, &zcount) == FAILURE) {
+               return;
+       }
+#else
+       ZEND_PARSE_PARAMETERS_START(2, 4)
+               Z_PARAM_ARRAY(pattern)
+               Z_PARAM_ZVAL(subject)
+               Z_PARAM_OPTIONAL
+               Z_PARAM_LONG(limit)
+               Z_PARAM_ZVAL_EX(zcount, 0, 1)
+       ZEND_PARSE_PARAMETERS_END();
+#endif
+       argc = ZEND_NUM_ARGS();
+       
+       ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(pattern), num_idx, str_idx, replace) {
+               if (str_idx) {
+                       ZVAL_STR_COPY(&regex, str_idx);
+               } else {
+                       php_error_docref(NULL, E_WARNING, "Delimiter must not be alphanumeric or backslash");
+                       zval_dtor(return_value);
+                       ZVAL_COPY(return_value, subject);
+                       break;
+               }               
+
+               if (Z_ISNULL_P(return_value)) {
+                       preg_replace_impl(&tmp_ret, argc + 1, &regex, replace, subject, limit, zcount, 1, 0);
+               } else {
+                       preg_replace_impl(&tmp_ret, argc + 1, &regex, replace, return_value, limit, zcount, 1, 0);
+                       zval_ptr_dtor(return_value);
+               }
+
+               if (zcount && Z_TYPE_P(zcount) == IS_LONG) {
+                       count += Z_LVAL_P(zcount);
+               }
+
+               ZVAL_COPY_VALUE(return_value, &tmp_ret);
+               zval_ptr_dtor(&regex);
+       } ZEND_HASH_FOREACH_END();
+
+       if (zcount && Z_TYPE_P(zcount) == IS_LONG) {
+               zval_dtor(zcount);
+               ZVAL_LONG(zcount, count);
+       }
 }
 /* }}} */
 
@@ -1471,7 +1546,26 @@ static PHP_FUNCTION(preg_replace_callback)
    Perform Perl-style regular expression replacement and only return matches. */
 static PHP_FUNCTION(preg_filter)
 {
-       preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
+       zval *regex, *replace, *subject, *zcount = NULL;
+       zend_long limit = -1;
+
+#ifndef FAST_ZPP
+       /* Get function parameters and do error-checking. */
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", &regex, &replace, &subject, &limit, &zcount) == FAILURE) {
+               return;
+       }    
+#else
+       ZEND_PARSE_PARAMETERS_START(3, 5)
+               Z_PARAM_ZVAL(regex)
+               Z_PARAM_ZVAL(replace)
+               Z_PARAM_ZVAL(subject)
+               Z_PARAM_OPTIONAL
+               Z_PARAM_LONG(limit)
+               Z_PARAM_ZVAL_EX(zcount, 0, 1)
+       ZEND_PARSE_PARAMETERS_END();
+#endif
+
+       preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 0, 1);
 }
 /* }}} */
 
@@ -1780,7 +1874,7 @@ static PHP_FUNCTION(preg_quote)
 
        /* Reallocate string and return it */
        out_str = zend_string_realloc(out_str, q - out_str->val, 0);
-       RETURN_STR(out_str);
+       RETURN_NEW_STR(out_str);
 }
 /* }}} */
 
@@ -1953,6 +2047,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_replace_callback, 0, 0, 3)
     ZEND_ARG_INFO(1, count)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_replace_callback_array, 0, 0, 2)
+    ZEND_ARG_INFO(0, pattern)
+    ZEND_ARG_INFO(0, subject)
+    ZEND_ARG_INFO(0, limit)
+    ZEND_ARG_INFO(1, count)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_split, 0, 0, 2)
     ZEND_ARG_INFO(0, pattern)
     ZEND_ARG_INFO(0, subject)
@@ -1980,6 +2081,7 @@ static const zend_function_entry pcre_functions[] = {
        PHP_FE(preg_match_all,                  arginfo_preg_match_all)
        PHP_FE(preg_replace,                    arginfo_preg_replace)
        PHP_FE(preg_replace_callback,   arginfo_preg_replace_callback)
+       PHP_FE(preg_replace_callback_array,     arginfo_preg_replace_callback_array)
        PHP_FE(preg_filter,                             arginfo_preg_replace)
        PHP_FE(preg_split,                              arginfo_preg_split)
        PHP_FE(preg_quote,                              arginfo_preg_quote)
diff --git a/ext/pcre/tests/preg_replace_callback_array.phpt b/ext/pcre/tests/preg_replace_callback_array.phpt
new file mode 100644 (file)
index 0000000..04ee846
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+preg_replace_callback_array()
+--FILE--
+<?php
+
+function f() {
+       throw new Exception();
+}
+
+try {
+var_dump(preg_replace_callback_array(array('/\w/' => 'f'), 'z'));
+} catch(Exception $e) {}
+
+function g($x) {
+       return "'$x[0]'";
+}
+
+var_dump(preg_replace_callback_array(array('@\b\w{1,2}\b@' => 'g'), array('a b3 bcd', 'v' => 'aksfjk', 12 => 'aa bb')));
+
+var_dump(preg_replace_callback_array(array('~\A.~' => 'g'), array(array('xyz'))));
+
+var_dump(preg_replace_callback_array(array('~\A.~' => create_function('$m', 'return strtolower($m[0]);')), 'ABC'));
+?>
+--EXPECTF--
+array(3) {
+  [0]=>
+  string(12) "'a' 'b3' bcd"
+  ["v"]=>
+  string(6) "aksfjk"
+  [12]=>
+  string(9) "'aa' 'bb'"
+}
+
+Notice: Array to string conversion in %spreg_replace_callback_array.php on line %d
+array(1) {
+  [0]=>
+  string(7) "'A'rray"
+}
+string(3) "aBC"
diff --git a/ext/pcre/tests/preg_replace_callback_array2.phpt b/ext/pcre/tests/preg_replace_callback_array2.phpt
new file mode 100644 (file)
index 0000000..dc6cbde
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+preg_replace_callback_array() 2
+--FILE--
+<?php
+
+var_dump(preg_replace_callback_array());
+var_dump(preg_replace_callback_array(1));
+var_dump(preg_replace_callback_array(1,2));
+var_dump(preg_replace_callback_array(1,2,3));
+$a = 5;
+var_dump(preg_replace_callback_array(1,2,3,$a));
+$a = "";
+var_dump(preg_replace_callback_array(array("" => ""),"","",$a));
+$a = array();
+var_dump(preg_replace_callback($a,$a,$a,$a));
+
+echo "Done\n";
+?>
+--EXPECTF--    
+Warning: preg_replace_callback_array() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: preg_replace_callback_array() expects at least 2 parameters, 1 given in %s on line %d
+NULL
+
+Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
+NULL
+
+Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
+NULL
+
+Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
+NULL
+
+Warning: preg_replace_callback_array() expects parameter 3 to be integer, string given in %s on line %d
+NULL
+
+Warning: preg_replace_callback() expects parameter 4 to be integer, array given in %s on line %d
+NULL
+Done
diff --git a/ext/pcre/tests/preg_replace_callback_array3.phpt b/ext/pcre/tests/preg_replace_callback_array3.phpt
new file mode 100644 (file)
index 0000000..b083432
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+preg_replace_callback_array() 3
+--FILE--
+<?php
+$code = "test-EXECUTE_DATA-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER";
+
+$code = preg_replace_callback_array(
+                array(
+                    "/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
+                    "/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
+                    "/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
+                    "/ZEND_VM_DISPATCH_TO_HELPER_EX/m" => function($matches) { return "helper_ex"; },
+                ),
+                $code);
+
+var_dump($code);
+$code = array("test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test",
+                "test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test");
+
+$code = preg_replace_callback_array(
+                array(
+                    "/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
+                    "/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
+                    "/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
+                ),
+                $code, -1, $count);
+
+var_dump($code, $count);
+
+?>
+--EXPECTF--    
+string(31) "test-execute_data-xcvxcv-helper"
+array(2) {
+  [0]=>
+  string(32) "test-execute_data-helper_EX-test"
+  [1]=>
+  string(48) "test-sdf-xcvxcv-helper_EX-test-execute_data-test"
+}
+int(4)
diff --git a/ext/pcre/tests/preg_replace_callback_array4.phpt b/ext/pcre/tests/preg_replace_callback_array4.phpt
new file mode 100644 (file)
index 0000000..12065ab
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+preg_replace_callback_array() 4
+--FILE--
+<?php
+$code = "test-EXECUTE_DATA-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER";
+
+$code = preg_replace_callback_array(
+                array(
+                    "/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
+                    "/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
+                    "/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
+                    "/ZEND_VM_DISPATCH_TO_HELPER_EX/m" => function($matches) { return "helper_ex"; },
+                ),
+                $code);
+
+var_dump($code);
+$code = array("test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test",
+                "test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test");
+
+$code = preg_replace_callback_array(
+                array(
+                    "/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
+                    23234 => function($matches) { return "execute_data";},
+                    "/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
+                ),
+                $code, -1, $count);
+
+var_dump($code, $count);
+?>
+--EXPECTF--    
+string(31) "test-execute_data-xcvxcv-helper"
+
+Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric or backslash in %s on line %d
+array(2) {
+  [0]=>
+  string(52) "test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test"
+  [1]=>
+  string(68) "test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test"
+}
+int(0)
index e9e8b7e2193165a0cbe387d622de76f5ce97afaf..516ccfd806d00c8b6558012fe8c3e71c9ecc2163 100644 (file)
@@ -97,6 +97,15 @@ string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] {
         Parameter #4 [ <optional> &$count ]
       }
     }
+    Function [ <internal:pcre> preg_replace_callback_array ] {
+
+      - Parameters [4] {
+        Parameter #0 [ <required> $pattern ]
+        Parameter #1 [ <required> $subject ]
+        Parameter #2 [ <optional> $limit ]
+        Parameter #3 [ <optional> &$count ]
+      }
+    }
     Function [ <internal:pcre> function preg_filter ] {
 
       - Parameters [5] {