Index: ext/standard/array.c
===================================================================
RCS file: /repository/php-src/ext/standard/array.c,v
retrieving revision 1.308.2.21.2.9
diff -u -r1.308.2.21.2.9 array.c
--- ext/standard/array.c	30 Jul 2006 03:31:18 -0000	1.308.2.21.2.9
+++ ext/standard/array.c	5 Aug 2006 10:32:00 -0000
@@ -2326,15 +2326,14 @@
 									Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC))
 						return 0;
 				} else {
-					(*src_entry)->refcount++;
-
+					ZVAL_ADDREF(*src_entry);
 					zend_hash_update(dest, string_key, string_key_len,
 									 src_entry, sizeof(zval *), NULL);
 				}
 				break;
 
 			case HASH_KEY_IS_LONG:
-				(*src_entry)->refcount++;
+				ZVAL_ADDREF(*src_entry);
 				zend_hash_next_index_insert(dest, src_entry, sizeof(zval *), NULL);
 				break;
 		}
@@ -2345,7 +2344,64 @@
 	return 1;
 }
 
-static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive)
+PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC)
+{
+	zval **src_entry, **dest_entry;
+	char *string_key;
+	uint string_key_len;
+	ulong num_key;
+	HashPosition pos;
+
+	zend_hash_internal_pointer_reset_ex(src, &pos);
+	while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
+		zend_bool recursive = 0;
+
+		switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
+			case HASH_KEY_IS_STRING:
+				if (Z_TYPE_PP(src_entry) == IS_ARRAY &&
+					zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS &&
+					Z_TYPE_PP(dest_entry) == IS_ARRAY) {
+
+					recursive = 1;
+				} else {
+					ZVAL_ADDREF(*src_entry);
+					zend_hash_update(dest, string_key, string_key_len,
+									 src_entry, sizeof(zval *), NULL);
+				}
+				break;
+
+			case HASH_KEY_IS_LONG:
+				if (Z_TYPE_PP(src_entry) == IS_ARRAY &&
+					zend_hash_index_find(dest, num_key, (void **)&dest_entry) == SUCCESS &&
+					Z_TYPE_PP(dest_entry) == IS_ARRAY) {
+
+					recursive = 1;
+				} else {
+					ZVAL_ADDREF(*src_entry);
+					zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
+				}
+				break;
+		}
+
+		if (recursive) {
+			if (*src_entry == *dest_entry && ((*dest_entry)->refcount % 2)) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
+				return 0;
+			}
+			SEPARATE_ZVAL(dest_entry);
+
+			if (!php_array_replace_recursive(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC)) {
+				return 0;
+			}
+		}
+
+		zend_hash_move_forward_ex(src, &pos);
+	}
+
+	return 1;
+}
+
+static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace)
 {
 	zval ***args = NULL;
 	int argc, i, params_ok = 1;
@@ -2376,10 +2432,15 @@
 
 	array_init(return_value);
 	
-	for (i=0; i<argc; i++) {
-		SEPARATE_ZVAL(args[i]);
-		convert_to_array_ex(args[i]);
-		php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC);
+	for (i = 0; i < argc; i++) {
+		if (!replace) {
+			php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC);
+		} else if (recursive && i > 0) { /* First array will be copied directly instead */
+			php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]) TSRMLS_CC);
+		} else {
+			zval *tmp;
+			zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		}
 	}
 	
 	efree(args);
@@ -2390,7 +2451,7 @@
    Merges elements from passed arrays into one array */
 PHP_FUNCTION(array_merge)
 {
-	php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+	php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
 }
 /* }}} */
 
@@ -2399,7 +2460,25 @@
    Recursively merges elements from passed arrays into one array */
 PHP_FUNCTION(array_merge_recursive)
 {
-	php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+	php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
+}
+/* }}} */
+
+
+/* {{{ proto array array_replace(array arr1, array arr2 [, array ...])
+   Replaces elements from passed arrays into one array */
+PHP_FUNCTION(array_replace)
+{
+	php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
+}
+/* }}} */
+
+
+/* {{{ proto array array_replace_recursive(array arr1, array arr2 [, array ...])
+   Recursively replaces elements from passed arrays into one array */
+PHP_FUNCTION(array_replace_recursive)
+{
+	php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
 }
 /* }}} */
 
Index: ext/standard/basic_functions.c
===================================================================
RCS file: /repository/php-src/ext/standard/basic_functions.c,v
retrieving revision 1.725.2.31.2.19
diff -u -r1.725.2.31.2.19 basic_functions.c
--- ext/standard/basic_functions.c	26 Jul 2006 08:57:44 -0000	1.725.2.31.2.19
+++ ext/standard/basic_functions.c	27 Jul 2006 07:34:07 -0000
@@ -458,6 +458,20 @@
 ZEND_END_ARG_INFO()
 
 static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_array_replace, 0, 0, 2)
+	ZEND_ARG_INFO(0, arr1) /* ARRAY_INFO(0, arg, 0) */
+	ZEND_ARG_INFO(0, arr2) /* ARRAY_INFO(0, arg, 0) */
+	ZEND_ARG_INFO(0, ...)  /* ARRAY_INFO(0, ..., 0) */
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_array_replace_recursive, 0, 0, 2)
+	ZEND_ARG_INFO(0, arr1) /* ARRAY_INFO(0, arg, 0) */
+	ZEND_ARG_INFO(0, arr2) /* ARRAY_INFO(0, arg, 0) */
+	ZEND_ARG_INFO(0, ...)  /* ARRAY_INFO(0, arg, 0) */
+ZEND_END_ARG_INFO()
+
+static
 ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys, 0, 0, 1)
 	ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
 	ZEND_ARG_INFO(0, search_value)
@@ -3700,6 +3714,8 @@
 	PHP_FE(array_slice,														arginfo_array_slice)
 	PHP_FE(array_merge,														arginfo_array_merge)
 	PHP_FE(array_merge_recursive,											arginfo_array_merge_recursive)
+	PHP_FE(array_replace,													arginfo_array_replace)
+	PHP_FE(array_replace_recursive,											arginfo_array_replace_recursive)
 	PHP_FE(array_keys,														arginfo_array_keys)
 	PHP_FE(array_values,													arginfo_array_values)
 	PHP_FE(array_count_values,												arginfo_array_count_values)
Index: ext/standard/php_array.h
===================================================================
RCS file: /repository/php-src/ext/standard/php_array.h,v
retrieving revision 1.50.2.2.2.2
diff -u -r1.50.2.2.2.2 php_array.h
--- ext/standard/php_array.h	15 Jul 2006 10:21:09 -0000	1.50.2.2.2.2
+++ ext/standard/php_array.h	27 Jul 2006 07:34:06 -0000
@@ -66,6 +66,8 @@
 PHP_FUNCTION(array_slice);
 PHP_FUNCTION(array_merge);
 PHP_FUNCTION(array_merge_recursive);
+PHP_FUNCTION(array_replace);
+PHP_FUNCTION(array_replace_recursive);
 PHP_FUNCTION(array_keys);
 PHP_FUNCTION(array_values);
 PHP_FUNCTION(array_count_values);
