Index: zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.296.2.27.2.32
diff -u -r1.296.2.27.2.32 zend_API.c
--- zend_API.c	6 Jul 2007 12:17:58 -0000	1.296.2.27.2.32
+++ zend_API.c	24 Jul 2007 15:40:47 -0000
@@ -2112,8 +2112,8 @@
 static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr TSRMLS_DC)
 {
 	int retval;
-	char *lcname, *lmname, *colon;
-	int clen, mlen;
+	char *lcname, *lmname, *colon, *fname;
+	int clen, mlen, fname_len;
 	zend_function *fptr;
 	zend_class_entry **pce;
 	HashTable *ftable;
@@ -2121,39 +2121,68 @@
 	*ce_ptr = NULL;
 	*fptr_ptr = NULL;
 
-	if ((colon = strstr(Z_STRVAL_P(callable), "::")) != NULL) {
-		clen = colon - Z_STRVAL_P(callable);
-		mlen = Z_STRLEN_P(callable) - clen - 2;
-		lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), clen);
+	fname_len = Z_STRLEN_P(callable);
+
+	/* Handle ::foo(), ::foo::bar() */
+	if (fname_len > 1 && ':' == Z_STRVAL_P(callable)[0] && ':' == Z_STRVAL_P(callable)[1]) {
+		fname_len-= 2;
+		fname = estrndup(Z_STRVAL_P(callable)+ 2, fname_len);
+	} else {
+		fname = estrndup(Z_STRVAL_P(callable), fname_len);
+	}
+
+	if ((colon= zend_memrchr(fname, ':', fname_len)) != NULL) {
+		clen = colon - fname - 1;
+		mlen = fname_len - clen - 2;
+		lcname = zend_str_tolower_dup(fname, clen);
+
 		/* caution: lcname is not '\0' terminated */
 		if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
 			*ce_ptr = EG(scope);
 		} else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
 			*ce_ptr = EG(scope) ? EG(scope)->parent : NULL;
-		} else if (zend_lookup_class(Z_STRVAL_P(callable), clen, &pce TSRMLS_CC) == SUCCESS) {
+		} else if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == SUCCESS) {
 			*ce_ptr = *pce;
 		}
+
 		efree(lcname);
 		if (!*ce_ptr) {
-			return 0;
-		}
-		ftable = &(*ce_ptr)->function_table;
-		if (ce_org && !instanceof_function(ce_org, *ce_ptr TSRMLS_CC)) {
-			return 0;
+			/* Resolve ambiguousity: test::foo() may be function foo in namespace 
+			 * test and not static method foo of class test 
+			 */
+			mlen = fname_len;
+			lmname = zend_str_tolower_dup(fname, mlen);
+
+			if (ce_org) {
+				ftable = &ce_org->function_table;
+				*ce_ptr = ce_org;
+			} else {
+				ftable = EG(function_table);
+			}
+			if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == FAILURE) {
+				return 0;
+			}
+			retval = 1;
+		} else {
+			ftable = &(*ce_ptr)->function_table;
+			if (ce_org && !instanceof_function(ce_org, *ce_ptr TSRMLS_CC)) {
+				return 0;
+			}
+			lmname = zend_str_tolower_dup(fname + clen + 2, mlen);
+			retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
 		}
-		lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen);
 	} else {
-		mlen = Z_STRLEN_P(callable);
-		lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
+		mlen = fname_len;
+		lmname = zend_str_tolower_dup(fname, mlen);
 		if (ce_org) {
 			ftable = &ce_org->function_table;
 			*ce_ptr = ce_org;
 		} else {
 			ftable = EG(function_table);
 		}
+		retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
 	}
-
-	retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
+	efree(fname);
 
 	if (!retval) {
 		if (*zobj_ptr_ptr && *ce_ptr && (*ce_ptr)->__call != 0) {
Index: zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.40
diff -u -r1.647.2.27.2.40 zend_compile.c
--- zend_compile.c	18 May 2007 13:12:03 -0000	1.647.2.27.2.40
+++ zend_compile.c	24 Jul 2007 15:40:51 -0000
@@ -149,6 +149,9 @@
 	CG(encoding_converter) = NULL;
 	CG(encoding_oddlen) = NULL;
 #endif /* ZEND_MULTIBYTE */
+
+	CG(current_namespace) = NULL;
+	CG(current_import) = NULL;
 }
 
 
@@ -384,13 +387,15 @@
 	fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
 }
 
-void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
+void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC)
 {
+	znode class_node;
 	zend_llist *fetch_list_ptr;
 	zend_llist_element *le;
 	zend_op *opline_ptr;
 	zend_op opline;
 
+	zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
 	zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
 	if (result->op_type == IS_CV) {
 		init_op(&opline TSRMLS_CC);
@@ -404,7 +409,7 @@
 		opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
 		opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
 		SET_UNUSED(opline.op2);
-		opline.op2 = *class_znode;
+		opline.op2 = class_node;
 		opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
 		*result = opline.result;
 
@@ -424,13 +429,13 @@
 			opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
 			opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
 			SET_UNUSED(opline.op2);
-			opline.op2 = *class_znode;
+			opline.op2 = class_node;
 			opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
 			opline_ptr->op1 = opline.result;
 
 			zend_llist_prepend_element(fetch_list_ptr, &opline);
 		} else {
-			opline_ptr->op2 = *class_znode;
+			opline_ptr->op2 = class_node;
 			opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
 		}
 	}
@@ -1170,6 +1175,18 @@
 	} else {
 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
+		if (CG(current_namespace)) {
+			znode tmp;
+
+			tmp.u.constant = *CG(current_namespace);
+			zval_copy_ctor(&tmp.u.constant);
+			zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
+			op_array.function_name = Z_STRVAL(tmp.u.constant);
+			efree(lcname);
+			lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
+			name_len+= CG(current_namespace)->value.str.len+ 2;   /* Not in original patch, should belong here though */
+		}
+
 		opline->opcode = ZEND_DECLARE_FUNCTION;
 		opline->op1.op_type = IS_CONST;
 		build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
@@ -1299,6 +1316,17 @@
 	if (class_type->op_type != IS_UNUSED) {
 		cur_arg_info->allow_null = 0;
 		if (class_type->u.constant.type == IS_STRING) {
+        
+			if (CG(current_namespace)) {
+    			znode tmp;
+
+    			tmp.op_type = IS_CONST;
+    			tmp.u.constant = *CG(current_namespace);
+    			zval_copy_ctor(&tmp.u.constant);
+    			zend_do_build_namespace_name(&tmp, &tmp, class_type TSRMLS_CC);
+    			*class_type = tmp;
+    		}
+
 			cur_arg_info->class_name = class_type->u.constant.value.str.val;
 			cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
 			if (op == ZEND_RECV_INIT) {
@@ -1328,11 +1356,21 @@
 }
 
 
-int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
+int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC)
 {
 	zend_function *function;
 	char *lcname;
-	
+
+	if (check_namespace && CG(current_namespace)) {
+		znode tmp;
+
+		tmp.op_type = IS_CONST;
+		tmp.u.constant = *CG(current_namespace);
+		zval_copy_ctor(&tmp.u.constant);
+		zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
+		*function_name = tmp;
+	}
+
 	lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
 	if (zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
 		zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
@@ -1419,11 +1457,75 @@
 	opline->extended_value = 0;
 
 	SET_UNUSED(opline->op1);
+	if (function_name->op_type == IS_CONST) {
+		char *p = zend_memrchr(Z_STRVAL(function_name->u.constant), ':', Z_STRLEN(function_name->u.constant));
+		if (p) {
+			opline->op1.op_type = IS_CONST;
+			ZVAL_LONG(&opline->op1.u.constant, p + 1 - Z_STRVAL(function_name->u.constant));
+		}		   
+	}
 
 	zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
 	zend_do_extended_fcall_begin(TSRMLS_C);
 }
 
+void zend_resolve_class_name(znode *class_name, ulong *fetch_type TSRMLS_DC)
+{
+   char* compound;
+   unsigned int lcname_len;
+   char* lcname;
+   zval **ns;
+   znode tmp;
+
+   compound = memchr(Z_STRVAL(class_name->u.constant), ':', Z_STRLEN(class_name->u.constant));
+   if (compound) {
+	   if (Z_TYPE(class_name->u.constant) == IS_STRING &&
+		   Z_STRVAL(class_name->u.constant)[0] == ':') {
+		   Z_STRLEN(class_name->u.constant) -= 2;
+		   memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+2, Z_STRLEN(class_name->u.constant)+1);
+		   Z_STRVAL(class_name->u.constant) = erealloc(
+			   Z_STRVAL(class_name->u.constant),
+			   Z_STRLEN(class_name->u.constant) + 1);
+	   } else if (CG(current_import)) {
+		   lcname_len = compound- Z_STRVAL(class_name->u.constant);
+		   lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), lcname_len);
+		   if (zend_hash_find(CG(current_import), lcname, lcname_len+1, (void**)&ns) == SUCCESS) {
+			   tmp.op_type = IS_CONST;
+			   tmp.u.constant = **ns;
+			   zval_copy_ctor(&tmp.u.constant);
+			   lcname_len += 2;
+			   Z_STRLEN(class_name->u.constant) -= lcname_len;
+			   memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+lcname_len, Z_STRLEN(class_name->u.constant)+1);
+			   zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
+			   *class_name = tmp;
+		   }
+		   efree(lcname);
+	   }   
+   } else if (CG(current_import) || CG(current_namespace)) {
+		lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+		lcname_len = Z_STRLEN(class_name->u.constant);
+
+		if (CG(current_import) &&
+			zend_hash_find(CG(current_import), lcname, lcname_len+1, (void**)&ns) == SUCCESS) {
+			zval_dtor(&class_name->u.constant);
+			class_name->u.constant = **ns;
+			zval_copy_ctor(&class_name->u.constant);
+		} else if (CG(current_namespace)) {
+			zend_class_entry **pce;
+
+			if (zend_hash_find(CG(class_table), lcname, lcname_len+1, (void**)&pce) == SUCCESS &&
+				(*pce)->type == ZEND_INTERNAL_CLASS) {
+				*fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
+			}
+			tmp.op_type = IS_CONST;
+			tmp.u.constant = *CG(current_namespace);
+			zval_copy_ctor(&tmp.u.constant);
+			zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
+			*class_name = tmp;
+		}
+		efree(lcname);
+	}
+}
 
 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
 {
@@ -1449,6 +1551,7 @@
 				zval_dtor(&class_name->u.constant);
 				break;
 			default:
+				zend_resolve_class_name(class_name, &opline->extended_value TSRMLS_CC);
 				opline->op2 = *class_name;
 				break;
 		}
@@ -1457,7 +1560,7 @@
 	}
 	opline->result.u.var = get_temporary_variable(CG(active_op_array));
 	opline->result.u.EA.type = opline->extended_value;
-	opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
+	opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
 	*result = opline->result;
 }
 
@@ -1482,17 +1585,33 @@
 
 void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC)
 {
+	znode class_node;
 	unsigned char *ptr = NULL;
-	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+	zend_op *opline;
+	ulong fetch_type;
 
+	if (class_name->op_type == IS_CONST &&
+		method_name->op_type == IS_CONST &&
+		ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
+		fetch_type = ZEND_FETCH_CLASS_GLOBAL;
+		zend_resolve_class_name(class_name, &fetch_type TSRMLS_CC);
+		class_node = *class_name;
+		fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
+	} else {
+		zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+		fetch_type = 0;
+	}
+	
+	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
-	opline->op1 = *class_name;
+	opline->op1 = class_node;
+	opline->extended_value = fetch_type;
 	opline->op2 = *method_name;
 
 	if (opline->op2.op_type == IS_CONST) {
 		char *lcname = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
 		if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
-		    memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
+			memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
 			zval_dtor(&opline->op2.u.constant);
 			SET_UNUSED(opline->op2);
 			efree(lcname);
@@ -1779,10 +1898,14 @@
 }
 
 
-void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC)
+void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC)
 {
-	long catch_op_number = get_next_op_number(CG(active_op_array));
+	long catch_op_number;
 	zend_op *opline;
+	znode catch_class;
+
+	zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
+	catch_op_number = get_next_op_number(CG(active_op_array));
 
 	if (catch_op_number > 0) {
 		opline = &CG(active_op_array)->opcodes[catch_op_number-1];
@@ -1791,9 +1914,13 @@
 		}
 	}
 
+	if (first_catch) {
+		first_catch->u.opline_num = catch_op_number;
+	}
+
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 	opline->opcode = ZEND_CATCH;
-	opline->op1 = *catch_class;
+	opline->op1 = catch_class;
 /*	SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
 	opline->op2 = *catch_var;
 	opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
@@ -2798,6 +2925,17 @@
 		zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
 	}
 
+	if (CG(current_namespace)) {
+		znode tmp;
+
+		tmp.u.constant = *CG(current_namespace);
+		zval_copy_ctor(&tmp.u.constant);
+		zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
+		class_name = &tmp;
+		efree(lcname);
+		lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+	}
+
 	new_class_entry = emalloc(sizeof(zend_class_entry));
 	new_class_entry->type = ZEND_USER_CLASS;
 	new_class_entry->name = class_name->u.constant.value.str.val;
@@ -2910,11 +3048,13 @@
 }
 
 
-void zend_do_implements_interface(znode *interface_znode TSRMLS_DC)
+void zend_do_implements_interface(znode *interface_name TSRMLS_DC)
 {
+	znode interface_node;
 	zend_op *opline;
 
-	switch (interface_znode->u.EA.type) {
+	zend_do_fetch_class(&interface_node, interface_name TSRMLS_CC);
+	switch (interface_node.u.EA.type) {
 		case ZEND_FETCH_CLASS_SELF:
 			zend_error(E_COMPILE_ERROR, "Cannot use 'self' as interface name as it is reserved");
 			break;
@@ -2934,7 +3074,7 @@
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 	opline->opcode = ZEND_ADD_INTERFACE;
 	opline->op1 = CG(implementing_class);
-	opline->op2 = *interface_znode;
+	opline->op2 = interface_node;
 	opline->extended_value = CG(active_class_entry)->num_interfaces++;
 }
 
@@ -3247,13 +3387,19 @@
 		case ZEND_RT:
 			if (constant_container ||
 			    !zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) {
-				zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+				zend_op *opline;
+				znode class_node;                
+                
+				if (constant_container) {
+    				zend_do_fetch_class(&class_node, constant_container TSRMLS_CC);
+    			}				
 
+                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 				opline->opcode = ZEND_FETCH_CONSTANT;
 				opline->result.op_type = IS_TMP_VAR;
 				opline->result.u.var = get_temporary_variable(CG(active_op_array));
 				if (constant_container) {
-					opline->op1 = *constant_container;
+					opline->op1 = class_node;
 				} else {
 					SET_UNUSED(opline->op1);
 				}
@@ -4240,6 +4386,121 @@
 	return op_array->vars[var].name;
 }
 
+void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC)
+{
+	int len;
+
+	if (prefix) {
+		len= Z_STRLEN(prefix->u.constant) + 2 + Z_STRLEN(name->u.constant);
+		*result = *prefix;
+		Z_STRVAL(result->u.constant)= (char*) erealloc(Z_STRVAL(result->u.constant), len+ 1);
+
+		Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)] = ':';
+		Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)+1] = ':';
+		memcpy(Z_STRVAL(result->u.constant)+Z_STRLEN(result->u.constant)+2,
+			Z_STRVAL(name->u.constant),
+			Z_STRLEN(name->u.constant)+1);
+	} else {
+		len= 2 + Z_STRLEN(name->u.constant);
+		Z_STRVAL(result->u.constant)= (char*) safe_emalloc(len+ 1, 1, 1);
+
+		result->op_type = IS_CONST;
+		Z_STRVAL(result->u.constant)[0]= ':';
+		Z_STRVAL(result->u.constant)[1]= ':';
+		memcpy(Z_STRVAL(result->u.constant)+2,
+			Z_STRVAL(name->u.constant),
+			Z_STRLEN(name->u.constant)+1);
+	}
+
+	Z_TYPE(result->u.constant) = IS_STRING;
+	Z_STRVAL(result->u.constant)[len]= '\0';  
+	Z_STRLEN(result->u.constant) = len;
+
+	zval_dtor(&name->u.constant);
+}
+
+void zend_do_namespace(znode *name TSRMLS_DC)
+{
+	unsigned int lcname_len;
+	char* lcname;
+
+	if (CG(active_op_array)->last > 0) {
+		zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
+	}
+	if (CG(current_namespace)) {
+		zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice");		
+	}
+	lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
+	lcname_len = Z_STRLEN(name->u.constant);
+	if (
+	  ((lcname_len == sizeof("self")-1) && memcmp(lcname, "self", sizeof("self") - 1) == 0) ||
+	  ((lcname_len == sizeof("parent")-1) && memcmp(lcname, "parent", sizeof("parent") - 1) == 0)
+	) {
+		zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
+	}
+	efree(lcname);
+
+	ALLOC_ZVAL(CG(current_namespace));
+	*CG(current_namespace) = name->u.constant;
+}
+
+void zend_do_import(znode *ns_name, znode *new_name TSRMLS_DC)
+{
+	unsigned int lcname_len;
+	char* lcname;
+	zval *name, *ns, tmp;
+
+	if (!CG(current_import)) {
+		CG(current_import) = emalloc(sizeof(HashTable));
+		zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
+	}
+
+	ALLOC_ZVAL(ns);
+	*ns = ns_name->u.constant;
+	if (new_name) {
+		name = &new_name->u.constant;
+	} else {
+		char *p;
+		name = &tmp;
+		p = strrchr(Z_STRVAL_P(ns), ':');
+		if (p) {
+			ZVAL_STRING(name, p+1, 1);
+		} else {
+			*name = *ns;
+			zval_copy_ctor(name);
+		}			
+	}
+
+	lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+	lcname_len = Z_STRLEN_P(name);
+	if (
+	  ((lcname_len == sizeof("self")-1) && memcmp(lcname, "self", sizeof("self") - 1) == 0) ||
+	  ((lcname_len == sizeof("parent")-1) && memcmp(lcname, "parent", sizeof("parent") - 1) == 0)
+	) {
+		zend_error(E_COMPILE_ERROR, "Cannot use '%s' as import name", Z_STRVAL_P(name));
+	}
+	
+	if (zend_hash_add(CG(current_import), lcname, lcname_len+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
+		zend_error(E_COMPILE_ERROR, "Cannot reuse import name");		
+	}
+	efree(lcname);
+	zval_dtor(name);
+}
+
+void zend_do_end_compilation(TSRMLS_D)
+{
+	if (CG(current_namespace)) {
+		zval_dtor(CG(current_namespace));
+		efree(CG(current_namespace));
+		CG(current_namespace) = NULL;
+	}
+	if (CG(current_import)) {
+		zend_hash_destroy(CG(current_import));
+		efree(CG(current_import));
+		CG(current_import) = NULL;
+	}
+}
+
 /*
  * Local variables:
  * tab-width: 4
Index: zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.12
diff -u -r1.316.2.8.2.12 zend_compile.h
--- zend_compile.h	18 May 2007 13:12:04 -0000	1.316.2.8.2.12
+++ zend_compile.h	24 Jul 2007 15:40:52 -0000
@@ -299,7 +299,7 @@
 	zval *object;
 	union _temp_variable *Ts;
 	zval ***CVs;
-	zend_bool original_in_execution;
+	int original_in_execution;
 	HashTable *symbol_table;
 	struct _zend_execute_data *prev_execute_data;
 	zval *old_error_reporting;
@@ -399,7 +399,7 @@
 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
 void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
 void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_bool pass_by_reference TSRMLS_DC);
-int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
+int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
 void zend_do_clone(znode *result, znode *expr TSRMLS_DC);
 void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC);
@@ -411,7 +411,7 @@
 void zend_do_handle_exception(TSRMLS_D);
 
 void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC);
+void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC);
 void zend_do_end_catch(znode *try_token TSRMLS_DC);
 void zend_do_throw(znode *expr TSRMLS_DC);
 
@@ -420,7 +420,7 @@
 ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
 ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC);
 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC);
-void zend_do_implements_interface(znode *interface_znode TSRMLS_DC);
+void zend_do_implements_interface(znode *interface_name TSRMLS_DC);
 
 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC);
 void zend_do_early_binding(TSRMLS_D);
@@ -504,6 +504,11 @@
 
 void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC);
 
+void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC);
+void zend_do_namespace(znode *name TSRMLS_DC);
+void zend_do_import(znode *name, znode *new_name TSRMLS_DC);
+void zend_do_end_compilation(TSRMLS_D);
+
 ZEND_API void function_add_ref(zend_function *function);
 
 #define INITIAL_OP_ARRAY_SIZE 64
@@ -591,6 +596,7 @@
 #define ZEND_FETCH_CLASS_GLOBAL		4
 #define ZEND_FETCH_CLASS_AUTO		5
 #define ZEND_FETCH_CLASS_INTERFACE	6
+#define ZEND_FETCH_CLASS_RT_NS_CHECK  0x20
 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
 
 /* variable parsing type (compile-time) */
Index: zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.24
diff -u -r1.331.2.20.2.24 zend_execute_API.c
--- zend_execute_API.c	21 Jul 2007 00:35:14 -0000	1.331.2.20.2.24
+++ zend_execute_API.c	24 Jul 2007 15:40:53 -0000
@@ -617,7 +617,6 @@
 	return zend_call_function(&fci, NULL TSRMLS_CC);
 }
 
-
 int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC)
 {
 	zend_uint i;
@@ -764,12 +763,21 @@
 			return FAILURE;
 		}
 
-		fname = Z_STRVAL_P(fci->function_name);
 		fname_len = Z_STRLEN_P(fci->function_name);
-		if ((colon = strstr(fname, "::")) != NULL) {
-			int clen = colon - fname;
+
+		/* Handle ::foo(), ::foo::bar() */
+		if (fname_len > 1 && ':' == Z_STRVAL_P(fci->function_name)[0] && ':' == Z_STRVAL_P(fci->function_name)[1]) {
+			fname_len-= 2;
+			fname = Z_STRVAL_P(fci->function_name)+ 2;
+    	} else {
+			fname = Z_STRVAL_P(fci->function_name);
+		}
+
+		if ((colon= zend_memrchr(fname, ':', fname_len)) != NULL) {
+			int clen = colon - fname - 1;
 			int mlen = fname_len - clen - 2;
 			zend_class_entry **pce, *ce_child = NULL;
+
 			if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
 				ce_child = *pce;
 			} else {
@@ -785,14 +793,24 @@
 				efree(lcname);
 			}
 			if (!ce_child) {
-				zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
-				return FAILURE;
+				/* Resolve ambiguousity: test::foo() may be function foo in namespace 
+				 * test and not static method foo of class test 
+				 */
+				char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
+				if (zend_hash_find(fci->function_table, function_name_lc, fname_len+ 1, (void **) &EX(function_state).function)==FAILURE) {
+					efree(function_name_lc);
+					zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
+					return FAILURE;
+				}
+				efree(function_name_lc);
+				
+			} else {
+				check_scope_or_static = calling_scope;
+				fci->function_table = &ce_child->function_table;
+				calling_scope = ce_child;
+				fname = fname + clen + 2;
+				fname_len = mlen;
 			}
-			check_scope_or_static = calling_scope;
-			fci->function_table = &ce_child->function_table;
-			calling_scope = ce_child;
-			fname = fname + clen + 2;
-			fname_len = mlen;
 		}
 
 		if (fci->object_pp) {
@@ -823,9 +841,8 @@
 			}
 		} else {
 			char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
-
 			if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
-			  EX(function_state).function = NULL;
+				EX(function_state).function = NULL;
 			}
 			efree(function_name_lc);
 		}
@@ -1021,6 +1038,7 @@
 	if (EG(exception)) {
 		zend_throw_exception_internal(NULL TSRMLS_CC);
 	}
+
 	return SUCCESS;
 }
 
@@ -1042,8 +1060,14 @@
 		return FAILURE;
 	}
 	
-	lc_name = do_alloca(name_length + 1);
-	zend_str_tolower_copy(lc_name, name, name_length);
+	if (name_length > 1 && name[0] == ':' && name[1] == ':') {
+		name_length-= 2;
+		lc_name = do_alloca(name_length + 1);
+		zend_str_tolower_copy(lc_name, name+ 2, name_length);
+    } else {
+		lc_name = do_alloca(name_length + 1);
+		zend_str_tolower_copy(lc_name, name, name_length);
+    }
 
 	if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
 		free_alloca(lc_name);
@@ -1475,8 +1499,11 @@
 {
 	zend_class_entry **pce;
 	int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
+	int rt_ns_check  = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0;
 
 	fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD;
+	fetch_type = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_CHECK;
+
 check_fetch_type:
 	switch (fetch_type) {
 		case ZEND_FETCH_CLASS_SELF:
@@ -1502,6 +1529,21 @@
 	}
 
 	if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) {
+
+		/* Check if we have internal class with the same name */
+		if (rt_ns_check) {
+        	char *php_name;
+
+			php_name = zend_memrchr(class_name, ':', class_name_len);
+			if (php_name) {
+				php_name++;
+				if (zend_lookup_class_ex(php_name, class_name_len-(php_name-class_name), use_autoload, &pce TSRMLS_CC)==SUCCESS &&
+					(*pce)->type == ZEND_INTERNAL_CLASS) {
+					return *pce;
+				}
+			}
+		}
+
 		if (use_autoload) {
 			if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
 				zend_error(E_ERROR, "Interface '%s' not found", class_name);
Index: zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.141.2.3.2.7
diff -u -r1.141.2.3.2.7 zend_globals.h
--- zend_globals.h	1 Jan 2007 09:35:46 -0000	1.141.2.3.2.7
+++ zend_globals.h	24 Jul 2007 15:40:53 -0000
@@ -147,6 +147,9 @@
 	HashTable **static_members;
 	int last_static_member;
 #endif
+
+	zval      *current_namespace;
+	HashTable *current_import;
 };
 
 
@@ -194,7 +197,7 @@
 
 	int ticks_count;
 
-	zend_bool in_execution;
+	int in_execution;
 	HashTable *in_autoload;
 	zend_function *autoload_func;
 	zend_bool full_tables_cleanup;
Index: zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.6
diff -u -r1.160.2.4.2.6 zend_language_parser.y
--- zend_language_parser.y	18 May 2007 18:36:04 -0000	1.160.2.4.2.6
+++ zend_language_parser.y	24 Jul 2007 15:40:54 -0000
@@ -143,11 +143,14 @@
 %token T_DOLLAR_OPEN_CURLY_BRACES
 %token T_CURLY_OPEN
 %token T_PAAMAYIM_NEKUDOTAYIM
+%token T_NAMESPACE
+%token T_IMPORT
+%token T_NS_C
 
 %% /* Rules */
 
 start:
-	top_statement_list
+	top_statement_list { zend_do_end_compilation(TSRMLS_C); }
 ;
 
 top_statement_list:
@@ -155,12 +158,20 @@
 	|	/* empty */
 ;
 
+namespace_name:
+       T_STRING { $$ = $1; }
+   |   namespace_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
 
 top_statement:
 		statement
 	|	function_declaration_statement	{ zend_do_early_binding(TSRMLS_C); }
 	|	class_declaration_statement		{ zend_do_early_binding(TSRMLS_C); }
-	|	T_HALT_COMPILER '(' ')' ';'   { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
+	|	T_HALT_COMPILER '(' ')' ';'   	{ zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
+	|   T_NAMESPACE namespace_name ';'  { zend_do_namespace(&$2 TSRMLS_CC); }
+	|   T_IMPORT namespace_name ';'     { zend_do_import(&$2, NULL TSRMLS_CC); }
+	|   T_IMPORT namespace_name T_AS T_STRING ';'   { zend_do_import(&$2, &$4 TSRMLS_CC); }
 ;
 
 
@@ -225,7 +236,7 @@
 	|	T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
 		T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
 		fully_qualified_class_name { zend_do_first_catch(&$7 TSRMLS_CC); }
-		T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, 1 TSRMLS_CC); }
+		T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, &$7 TSRMLS_CC); }
 		'{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
 		additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); }
 	|	T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
@@ -244,7 +255,7 @@
 
 
 additional_catch:
-	T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+	T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
 ;
 
 
@@ -307,7 +318,7 @@
 
 extends_from:
 		/* empty */					{ $$.op_type = IS_UNUSED; }
-	|	T_EXTENDS fully_qualified_class_name	{ $$ = $2; }
+	|	T_EXTENDS fully_qualified_class_name	{ zend_do_fetch_class(&$$, &$2 TSRMLS_CC); }
 ;
 
 interface_entry:
@@ -436,7 +447,7 @@
 
 optional_class_type:
 		/* empty */		{ $$.op_type = IS_UNUSED; }
-	|	T_STRING		{ $$ = $1; }
+	|	fully_qualified_class_name		{ $$ = $1; }
 	|	T_ARRAY		{ $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;}
 ;
 
@@ -621,9 +632,12 @@
 ;
 
 function_call:
-		T_STRING	'(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); }
+		T_STRING	'(' { $2.u.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
 				function_call_parameter_list
 				')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+	|   T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $3.u.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
+				function_call_parameter_list
+		')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 	|	fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
 			function_call_parameter_list
 			')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
@@ -636,11 +650,13 @@
 ;
 
 fully_qualified_class_name:
-		T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+		T_STRING { $$ = $1; }
+    |	T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
+    |	fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
 ;
 
 class_name_reference:
-		T_STRING				{ zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+		fully_qualified_class_name		{ zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
 	|	dynamic_class_name_reference	{ zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
 ;
 
@@ -685,6 +701,7 @@
 	|	T_CLASS_C					{ $$ = $1; }
 	|	T_METHOD_C					{ $$ = $1; }
 	|	T_FUNC_C					{ $$ = $1; }
+	|	T_NS_C  					{ $$ = $1; }
 ;
 
 
Index: zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.11.2.12
diff -u -r1.131.2.11.2.12 zend_language_scanner.l
--- zend_language_scanner.l	24 May 2007 08:56:35 -0000	1.131.2.11.2.12
+++ zend_language_scanner.l	24 Jul 2007 15:40:55 -0000
@@ -1190,6 +1190,14 @@
 	return T_REQUIRE_ONCE;
 }
 
+<ST_IN_SCRIPTING>"namespace" {
+	return T_NAMESPACE;
+}
+
+<ST_IN_SCRIPTING>"import" {
+	return T_IMPORT;
+}
+
 <ST_IN_SCRIPTING>"use" {
 	return T_USE;
 }
@@ -1535,6 +1543,19 @@
 	return T_FILE;
 }
 
+<ST_IN_SCRIPTING>"__NAMESPACE__" {
+	if (CG(current_namespace)) {
+        *zendlval = *CG(current_namespace);
+        zval_copy_ctor(zendlval);
+    } else {
+		zendlval->value.str.len = 0;
+		zendlval->value.str.val = estrndup("", 0);
+		zendlval->type = IS_STRING;
+    }
+    return T_NS_C;
+}
+
+
 <INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
 #ifdef ZEND_MULTIBYTE
 	if (SCNG(output_filter)) {
Index: zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.46
diff -u -r1.59.2.29.2.46 zend_vm_def.h
--- zend_vm_def.h	13 Jun 2007 14:50:12 -0000	1.59.2.29.2.46
+++ zend_vm_def.h	24 Jul 2007 15:40:58 -0000
@@ -1730,7 +1730,7 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
+ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUSED|CV)
 {
 	zend_op *opline = EX(opline);
 	zval *function_name;
@@ -1738,7 +1738,34 @@
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
 
-	ce = EX_T(opline->op1.u.var).class_entry;
+	if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+        
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */	  
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
 	if(OP2_TYPE != IS_UNUSED) {
 		char *function_name_strval;
 		int function_name_strlen;
@@ -1819,9 +1846,32 @@
 	}
 
 	lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+
+	/* ::function() -> global */
+	if (OP2_TYPE != IS_CONST && (
+		  Z_STRVAL_P(function_name)[0] == ':' &&
+		  Z_STRVAL_P(function_name)[1] == ':')) {
+		function_name_strlen-= 2;
+		lcname = zend_str_tolower_dup((Z_STRVAL_P(function_name)+2), function_name_strlen);
+	} else {
+		lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+	}
+
 	if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
 		efree(lcname);
-		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+		/* Try to find global function */
+		if (OP2_TYPE == IS_CONST && opline->op1.op_type == IS_CONST) {
+            int lcname_len= function_name_strlen-Z_LVAL(opline->op1.u.constant);
+			lcname = zend_str_tolower_dup(function_name_strval+Z_LVAL(opline->op1.u.constant), lcname_len);
+			if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void **) &function)==FAILURE ||
+			    function->type != ZEND_INTERNAL_FUNCTION) {
+				efree(lcname);
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+		} else {
+			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+		}
 	}
 
 	efree(lcname);
@@ -1945,8 +1995,14 @@
 		original_return_value = EG(return_value_ptr_ptr);
 		EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
 		EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+		EG(in_execution)++;
 
-		zend_execute(EG(active_op_array) TSRMLS_CC);
+		if (EG(in_execution) > 2000) {
+			zend_throw_exception_ex(zend_get_error_exception(TSRMLS_C), 0 TSRMLS_CC, "Stack overflow");
+		} else {
+			zend_execute(EG(active_op_array) TSRMLS_CC);
+		}
+		EG(in_execution)--;
 		EX_T(opline->result.u.var).var.fcall_returned_reference = EG(active_op_array)->return_reference;
 
 		if (return_value_used && !EX_T(opline->result.u.var).var.ptr) {
@@ -2582,7 +2638,7 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
+ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED, CONST)
 {
 	zend_op *opline = EX(opline);
 	zend_class_entry *ce = NULL;
Index: zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.47
diff -u -r1.62.2.30.2.47 zend_vm_execute.h
--- zend_vm_execute.h	21 Jul 2007 00:35:14 -0000	1.62.2.30.2.47
+++ zend_vm_execute.h	24 Jul 2007 15:41:20 -0000
@@ -57,7 +57,9 @@
 	EX(prev_execute_data) = EG(current_execute_data);
 	EG(current_execute_data) = &execute_data;
 
-	EG(in_execution) = 1;
+	if (!EG(in_execution)) {
+		EG(in_execution) = 1;
+	}
 	if (op_array->start_op) {
 		ZEND_VM_SET_OPCODE(op_array->start_op);
 	} else {
@@ -230,8 +232,14 @@
 		original_return_value = EG(return_value_ptr_ptr);
 		EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
 		EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+		EG(in_execution)++;
 
-		zend_execute(EG(active_op_array) TSRMLS_CC);
+		if (EG(in_execution) > 2000) {
+			zend_throw_exception_ex(zend_get_error_exception(TSRMLS_C), 0 TSRMLS_CC, "Stack overflow");
+		} else {
+			zend_execute(EG(active_op_array) TSRMLS_CC);
+		}
+		EG(in_execution)--;
 		EX_T(opline->result.u.var).var.fcall_returned_reference = EG(active_op_array)->return_reference;
 
 		if (return_value_used && !EX_T(opline->result.u.var).var.ptr) {
@@ -656,70 +664,6 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zval *function_name;
-	zend_class_entry *ce;
-
-	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
-
-	ce = EX_T(opline->op1.u.var).class_entry;
-	if(IS_CONST != IS_UNUSED) {
-		char *function_name_strval;
-		int function_name_strlen;
-		zend_bool is_const = (IS_CONST == IS_CONST);
-
-
-		if (is_const) {
-			function_name_strval = Z_STRVAL(opline->op2.u.constant);
-			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-		} else {
-			function_name = &opline->op2.u.constant;
-
-			if (Z_TYPE_P(function_name) != IS_STRING) {
-				zend_error_noreturn(E_ERROR, "Function name must be a string");
-			}
-			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-			function_name_strlen = function_name->value.str.len;
-		}
-
-		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-		if (!is_const) {
-			efree(function_name_strval);
-
-		}
-	} else {
-		if(!ce->constructor) {
-			zend_error_noreturn(E_ERROR, "Can not call constructor");
-		}
-		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
-			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
-		}
-		EX(fbc) = ce->constructor;
-	}
-
-	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
-		EX(object) = NULL;
-	} else {
-		if (IS_CONST != IS_UNUSED &&
-		    EG(This) &&
-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
-		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
-		    /* We are calling method of the other (incompatible) class,
-		       but passing $this. This is done for compatibility with php-4. */
-			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
-
-		}
-		if ((EX(object) = EG(This))) {
-			EX(object)->refcount++;
-		}
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
 static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -745,9 +689,32 @@
 	}
 
 	lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+
+	/* ::function() -> global */
+	if (IS_CONST != IS_CONST && (
+		  Z_STRVAL_P(function_name)[0] == ':' &&
+		  Z_STRVAL_P(function_name)[1] == ':')) {
+		function_name_strlen-= 2;
+		lcname = zend_str_tolower_dup((Z_STRVAL_P(function_name)+2), function_name_strlen);
+	} else {
+		lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+	}
+
 	if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
 		efree(lcname);
-		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+		/* Try to find global function */
+		if (IS_CONST == IS_CONST && opline->op1.op_type == IS_CONST) {
+            int lcname_len= function_name_strlen-Z_LVAL(opline->op1.u.constant);
+			lcname = zend_str_tolower_dup(function_name_strval+Z_LVAL(opline->op1.u.constant), lcname_len);
+			if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void **) &function)==FAILURE ||
+			    function->type != ZEND_INTERNAL_FUNCTION) {
+				efree(lcname);
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+		} else {
+			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+		}
 	}
 
 	efree(lcname);
@@ -860,70 +827,6 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zval *function_name;
-	zend_class_entry *ce;
-
-	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
-
-	ce = EX_T(opline->op1.u.var).class_entry;
-	if(IS_TMP_VAR != IS_UNUSED) {
-		char *function_name_strval;
-		int function_name_strlen;
-		zend_bool is_const = (IS_TMP_VAR == IS_CONST);
-		zend_free_op free_op2;
-
-		if (is_const) {
-			function_name_strval = Z_STRVAL(opline->op2.u.constant);
-			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-		} else {
-			function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
-			if (Z_TYPE_P(function_name) != IS_STRING) {
-				zend_error_noreturn(E_ERROR, "Function name must be a string");
-			}
-			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-			function_name_strlen = function_name->value.str.len;
-		}
-
-		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-		if (!is_const) {
-			efree(function_name_strval);
-			zval_dtor(free_op2.var);
-		}
-	} else {
-		if(!ce->constructor) {
-			zend_error_noreturn(E_ERROR, "Can not call constructor");
-		}
-		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
-			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
-		}
-		EX(fbc) = ce->constructor;
-	}
-
-	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
-		EX(object) = NULL;
-	} else {
-		if (IS_TMP_VAR != IS_UNUSED &&
-		    EG(This) &&
-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
-		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
-		    /* We are calling method of the other (incompatible) class,
-		       but passing $this. This is done for compatibility with php-4. */
-			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
-
-		}
-		if ((EX(object) = EG(This))) {
-			EX(object)->refcount++;
-		}
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
 static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -949,9 +852,32 @@
 	}
 
 	lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+
+	/* ::function() -> global */
+	if (IS_TMP_VAR != IS_CONST && (
+		  Z_STRVAL_P(function_name)[0] == ':' &&
+		  Z_STRVAL_P(function_name)[1] == ':')) {
+		function_name_strlen-= 2;
+		lcname = zend_str_tolower_dup((Z_STRVAL_P(function_name)+2), function_name_strlen);
+	} else {
+		lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+	}
+
 	if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
 		efree(lcname);
-		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+		/* Try to find global function */
+		if (IS_TMP_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
+            int lcname_len= function_name_strlen-Z_LVAL(opline->op1.u.constant);
+			lcname = zend_str_tolower_dup(function_name_strval+Z_LVAL(opline->op1.u.constant), lcname_len);
+			if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void **) &function)==FAILURE ||
+			    function->type != ZEND_INTERNAL_FUNCTION) {
+				efree(lcname);
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+		} else {
+			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+		}
 	}
 
 	efree(lcname);
@@ -1021,70 +947,6 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zval *function_name;
-	zend_class_entry *ce;
-
-	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
-
-	ce = EX_T(opline->op1.u.var).class_entry;
-	if(IS_VAR != IS_UNUSED) {
-		char *function_name_strval;
-		int function_name_strlen;
-		zend_bool is_const = (IS_VAR == IS_CONST);
-		zend_free_op free_op2;
-
-		if (is_const) {
-			function_name_strval = Z_STRVAL(opline->op2.u.constant);
-			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-		} else {
-			function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
-			if (Z_TYPE_P(function_name) != IS_STRING) {
-				zend_error_noreturn(E_ERROR, "Function name must be a string");
-			}
-			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-			function_name_strlen = function_name->value.str.len;
-		}
-
-		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-		if (!is_const) {
-			efree(function_name_strval);
-			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
-		}
-	} else {
-		if(!ce->constructor) {
-			zend_error_noreturn(E_ERROR, "Can not call constructor");
-		}
-		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
-			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
-		}
-		EX(fbc) = ce->constructor;
-	}
-
-	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
-		EX(object) = NULL;
-	} else {
-		if (IS_VAR != IS_UNUSED &&
-		    EG(This) &&
-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
-		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
-		    /* We are calling method of the other (incompatible) class,
-		       but passing $this. This is done for compatibility with php-4. */
-			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
-
-		}
-		if ((EX(object) = EG(This))) {
-			EX(object)->refcount++;
-		}
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
 static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -1110,9 +972,32 @@
 	}
 
 	lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+
+	/* ::function() -> global */
+	if (IS_VAR != IS_CONST && (
+		  Z_STRVAL_P(function_name)[0] == ':' &&
+		  Z_STRVAL_P(function_name)[1] == ':')) {
+		function_name_strlen-= 2;
+		lcname = zend_str_tolower_dup((Z_STRVAL_P(function_name)+2), function_name_strlen);
+	} else {
+		lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+	}
+
 	if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
 		efree(lcname);
-		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+		/* Try to find global function */
+		if (IS_VAR == IS_CONST && opline->op1.op_type == IS_CONST) {
+            int lcname_len= function_name_strlen-Z_LVAL(opline->op1.u.constant);
+			lcname = zend_str_tolower_dup(function_name_strval+Z_LVAL(opline->op1.u.constant), lcname_len);
+			if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void **) &function)==FAILURE ||
+			    function->type != ZEND_INTERNAL_FUNCTION) {
+				efree(lcname);
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+		} else {
+			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+		}
 	}
 
 	efree(lcname);
@@ -1181,162 +1066,34 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
-	zval *function_name;
-	zend_class_entry *ce;
+	zval *class_name;
 
-	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
 
-	ce = EX_T(opline->op1.u.var).class_entry;
-	if(IS_UNUSED != IS_UNUSED) {
-		char *function_name_strval;
-		int function_name_strlen;
-		zend_bool is_const = (IS_UNUSED == IS_CONST);
 
+	if (IS_CV == IS_UNUSED) {
+		EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+		ZEND_VM_NEXT_OPCODE();
+	}
 
-		if (is_const) {
-			function_name_strval = Z_STRVAL(opline->op2.u.constant);
-			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-		} else {
-			function_name = NULL;
+	class_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
 
-			if (Z_TYPE_P(function_name) != IS_STRING) {
-				zend_error_noreturn(E_ERROR, "Function name must be a string");
-			}
-			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-			function_name_strlen = function_name->value.str.len;
-		}
+	switch (Z_TYPE_P(class_name)) {
+		case IS_OBJECT:
+			EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+			break;
+		case IS_STRING:
+			EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+			break;
+		default:
+			zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
+			break;
+	}
 
-		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-		if (!is_const) {
-			efree(function_name_strval);
-
-		}
-	} else {
-		if(!ce->constructor) {
-			zend_error_noreturn(E_ERROR, "Can not call constructor");
-		}
-		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
-			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
-		}
-		EX(fbc) = ce->constructor;
-	}
-
-	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
-		EX(object) = NULL;
-	} else {
-		if (IS_UNUSED != IS_UNUSED &&
-		    EG(This) &&
-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
-		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
-		    /* We are calling method of the other (incompatible) class,
-		       but passing $this. This is done for compatibility with php-4. */
-			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
-
-		}
-		if ((EX(object) = EG(This))) {
-			EX(object)->refcount++;
-		}
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zval *class_name;
-
-
-
-	if (IS_CV == IS_UNUSED) {
-		EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
-		ZEND_VM_NEXT_OPCODE();
-	}
-
-	class_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-
-	switch (Z_TYPE_P(class_name)) {
-		case IS_OBJECT:
-			EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
-			break;
-		case IS_STRING:
-			EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
-			break;
-		default:
-			zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
-			break;
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zval *function_name;
-	zend_class_entry *ce;
-
-	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
-
-	ce = EX_T(opline->op1.u.var).class_entry;
-	if(IS_CV != IS_UNUSED) {
-		char *function_name_strval;
-		int function_name_strlen;
-		zend_bool is_const = (IS_CV == IS_CONST);
-
-
-		if (is_const) {
-			function_name_strval = Z_STRVAL(opline->op2.u.constant);
-			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
-		} else {
-			function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-
-			if (Z_TYPE_P(function_name) != IS_STRING) {
-				zend_error_noreturn(E_ERROR, "Function name must be a string");
-			}
-			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
-			function_name_strlen = function_name->value.str.len;
-		}
-
-		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
-
-		if (!is_const) {
-			efree(function_name_strval);
-
-		}
-	} else {
-		if(!ce->constructor) {
-			zend_error_noreturn(E_ERROR, "Can not call constructor");
-		}
-		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
-			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
-		}
-		EX(fbc) = ce->constructor;
-	}
-
-	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
-		EX(object) = NULL;
-	} else {
-		if (IS_CV != IS_UNUSED &&
-		    EG(This) &&
-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
-		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
-		    /* We are calling method of the other (incompatible) class,
-		       but passing $this. This is done for compatibility with php-4. */
-			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
-
-		}
-		if ((EX(object) = EG(This))) {
-			EX(object)->refcount++;
-		}
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
+	ZEND_VM_NEXT_OPCODE();
+}
 
 static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
@@ -1363,9 +1120,32 @@
 	}
 
 	lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+
+	/* ::function() -> global */
+	if (IS_CV != IS_CONST && (
+		  Z_STRVAL_P(function_name)[0] == ':' &&
+		  Z_STRVAL_P(function_name)[1] == ':')) {
+		function_name_strlen-= 2;
+		lcname = zend_str_tolower_dup((Z_STRVAL_P(function_name)+2), function_name_strlen);
+	} else {
+		lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+	}
+
 	if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
 		efree(lcname);
-		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+
+		/* Try to find global function */
+		if (IS_CV == IS_CONST && opline->op1.op_type == IS_CONST) {
+            int lcname_len= function_name_strlen-Z_LVAL(opline->op1.u.constant);
+			lcname = zend_str_tolower_dup(function_name_strval+Z_LVAL(opline->op1.u.constant), lcname_len);
+			if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void **) &function)==FAILURE ||
+			    function->type != ZEND_INTERNAL_FUNCTION) {
+				efree(lcname);
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+		} else {
+			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+		}
 	}
 
 	efree(lcname);
@@ -2632,6 +2412,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_CONST == IS_CONST && IS_CONST == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_CONST != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_CONST == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = &opline->op2.u.constant;
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_CONST != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -2663,51 +2534,6 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
-static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
-	zend_class_entry *ce = NULL;
-	zval **value;
-
-	if (IS_CONST == IS_UNUSED) {
-/* This seems to be a reminant of namespaces
-		if (EG(scope)) {
-			ce = EG(scope);
-			if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
-				zval_update_constant(value, (void *) 1 TSRMLS_CC);
-				EX_T(opline->result.u.var).tmp_var = **value;
-				zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-				ZEND_VM_NEXT_OPCODE();
-			}
-		}
-*/
-		if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
-			zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
-						opline->op2.u.constant.value.str.val,
-						opline->op2.u.constant.value.str.val);
-			EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
-			zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-		}
-		ZEND_VM_NEXT_OPCODE();
-	}
-
-	ce = EX_T(opline->op1.u.var).class_entry;
-
-	if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
-		zend_class_entry *old_scope = EG(scope);
-
-		EG(scope) = ce;
-		zval_update_constant(value, (void *) 1 TSRMLS_CC);
-		EG(scope) = old_scope;
-		EX_T(opline->result.u.var).tmp_var = **value;
-		zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-	} else {
-		zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
-	}
-
-	ZEND_VM_NEXT_OPCODE();
-}
-
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -3035,6 +2861,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_TMP_VAR != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_TMP_VAR == IS_CONST);
+		zend_free_op free_op2;
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+			zval_dtor(free_op2.var);
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_TMP_VAR != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -3394,6 +3311,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_CONST == IS_CONST && IS_VAR == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_VAR != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_VAR == IS_CONST);
+		zend_free_op free_op2;
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_VAR != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -3502,21 +3510,112 @@
 	} else {
 
 	}
-	ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
-	zend_op *opline = EX(opline);
+	ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+
+	array_init(&EX_T(opline->result.u.var).tmp_var);
+	if (IS_CONST == IS_UNUSED) {
+		ZEND_VM_NEXT_OPCODE();
+#if 0 || IS_CONST != IS_UNUSED
+	} else {
+		return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+#endif
+	}
+}
+
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_UNUSED != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_UNUSED == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = NULL;
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_UNUSED != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
 
-	array_init(&EX_T(opline->result.u.var).tmp_var);
-	if (IS_CONST == IS_UNUSED) {
-		ZEND_VM_NEXT_OPCODE();
-#if 0 || IS_CONST != IS_UNUSED
-	} else {
-		return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-#endif
-	}
+	ZEND_VM_NEXT_OPCODE();
 }
 
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -3846,6 +3945,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_CONST == IS_CONST && IS_CV == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_CV != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_CV == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_CV != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -9333,6 +9523,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_CONST != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_CONST == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = &opline->op2.u.constant;
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_CONST != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -9364,6 +9645,51 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zend_class_entry *ce = NULL;
+	zval **value;
+
+	if (IS_VAR == IS_UNUSED) {
+/* This seems to be a reminant of namespaces
+		if (EG(scope)) {
+			ce = EG(scope);
+			if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+				zval_update_constant(value, (void *) 1 TSRMLS_CC);
+				EX_T(opline->result.u.var).tmp_var = **value;
+				zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+				ZEND_VM_NEXT_OPCODE();
+			}
+		}
+*/
+		if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+			zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+						opline->op2.u.constant.value.str.val,
+						opline->op2.u.constant.value.str.val);
+			EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+			zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+		}
+		ZEND_VM_NEXT_OPCODE();
+	}
+
+	ce = EX_T(opline->op1.u.var).class_entry;
+
+	if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+		zend_class_entry *old_scope = EG(scope);
+
+		EG(scope) = ce;
+		zval_update_constant(value, (void *) 1 TSRMLS_CC);
+		EG(scope) = old_scope;
+		EX_T(opline->result.u.var).tmp_var = **value;
+		zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+	} else {
+		zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -10791,32 +11117,123 @@
 			zend_error_noreturn(E_ERROR, "Object does not support method calls");
 		}
 
-		/* First, locate the function. */
-		EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
-		if (!EX(fbc)) {
-			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+		/* First, locate the function. */
+		EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
+		if (!EX(fbc)) {
+			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+		}
+	} else {
+		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (!PZVAL_IS_REF(EX(object))) {
+			EX(object)->refcount++; /* For $this pointer */
+		} else {
+			zval *this_ptr;
+			ALLOC_ZVAL(this_ptr);
+			INIT_PZVAL_COPY(this_ptr, EX(object));
+			zval_copy_ctor(this_ptr);
+			EX(object) = this_ptr;
+		}
+	}
+
+	zval_dtor(free_op2.var);
+	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_TMP_VAR != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_TMP_VAR == IS_CONST);
+		zend_free_op free_op2;
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+			zval_dtor(free_op2.var);
 		}
 	} else {
-		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
 	}
 
 	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
 		EX(object) = NULL;
 	} else {
-		if (!PZVAL_IS_REF(EX(object))) {
-			EX(object)->refcount++; /* For $this pointer */
-		} else {
-			zval *this_ptr;
-			ALLOC_ZVAL(this_ptr);
-			INIT_PZVAL_COPY(this_ptr, EX(object));
-			zval_copy_ctor(this_ptr);
-			EX(object) = this_ptr;
+		if (IS_TMP_VAR != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
 		}
 	}
 
-	zval_dtor(free_op2.var);
-	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
-
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -12346,6 +12763,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_VAR == IS_CONST && IS_VAR == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_VAR != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_VAR == IS_CONST);
+		zend_free_op free_op2;
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_VAR != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -13075,6 +13583,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_UNUSED != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_UNUSED == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = NULL;
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_UNUSED != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -14302,6 +14901,97 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zval *function_name;
+	zend_class_entry *ce;
+
+	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
+
+	if (IS_VAR == IS_CONST && IS_CV == IS_CONST) {
+		char* fname;
+		unsigned int len;
+
+		len = Z_STRLEN(opline->op1.u.constant) + 2 + Z_STRLEN(opline->op2.u.constant);
+		fname = emalloc(len + 1);
+		memcpy(fname, Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant));
+		fname[Z_STRLEN(opline->op1.u.constant)] = ':';
+		fname[Z_STRLEN(opline->op1.u.constant)+1] = ':';
+		memcpy(fname+Z_STRLEN(opline->op1.u.constant)+2, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1);
+		fname[len]= '\0';
+
+        zend_str_tolower(fname, len);
+
+		/* try a function in namespace */
+		if (zend_hash_find(EG(function_table), fname, len+1, (void **) &EX(fbc))==SUCCESS) {
+		   efree(fname);
+		   EX(object) = NULL;
+		   ZEND_VM_NEXT_OPCODE();
+		}
+		efree(fname);
+
+		/* no function found. try a static method in class */
+		ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+	} else {
+		ce = EX_T(opline->op1.u.var).class_entry;
+	}
+
+	if(IS_CV != IS_UNUSED) {
+		char *function_name_strval;
+		int function_name_strlen;
+		zend_bool is_const = (IS_CV == IS_CONST);
+
+
+		if (is_const) {
+			function_name_strval = Z_STRVAL(opline->op2.u.constant);
+			function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+		} else {
+			function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+
+			if (Z_TYPE_P(function_name) != IS_STRING) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string");
+			}
+			function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+			function_name_strlen = function_name->value.str.len;
+		}
+
+		EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+
+		if (!is_const) {
+			efree(function_name_strval);
+
+		}
+	} else {
+		if(!ce->constructor) {
+			zend_error_noreturn(E_ERROR, "Can not call constructor");
+		}
+		if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+			zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+		}
+		EX(fbc) = ce->constructor;
+	}
+
+	if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
+		EX(object) = NULL;
+	} else {
+		if (IS_CV != IS_UNUSED &&
+		    EG(This) &&
+		    Z_OBJ_HT_P(EG(This))->get_class_entry &&
+		    !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
+		    /* We are calling method of the other (incompatible) class,
+		       but passing $this. This is done for compatibility with php-4. */
+			zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
+
+		}
+		if ((EX(object) = EG(This))) {
+			EX(object)->refcount++;
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -29055,7 +29745,6 @@
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
-  	ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
@@ -29066,6 +29755,7 @@
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
+  	ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
@@ -29405,31 +30095,31 @@
   	ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER,
-  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER,
+  	ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
   	ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
   	ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
   	ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
Index: zend_vm_execute.skl
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v
retrieving revision 1.2.2.2.2.1
diff -u -r1.2.2.2.2.1 zend_vm_execute.skl
--- zend_vm_execute.skl	21 Jul 2007 00:35:15 -0000	1.2.2.2.2.1
+++ zend_vm_execute.skl	24 Jul 2007 15:41:20 -0000
@@ -28,7 +28,9 @@
 	EX(prev_execute_data) = EG(current_execute_data);
 	EG(current_execute_data) = &execute_data;
 
-	EG(in_execution) = 1;
+	if (!EG(in_execution)) {
+		EG(in_execution) = 1;
+	}
 	if (op_array->start_op) {
 		ZEND_VM_SET_OPCODE(op_array->start_op);
 	} else {

