Hello all,

I saw the notes regarding namespaces, and it really suprised me that the namespace patch was not looked at in detail, discarded, and then the approach that was agreed on was _THE EXACT SAME ONE_ that my patch uses. To add insult to injury, it's mentioned that Marcus was going to provide a patch (my problem is not with Marcus, in fact, he was very supportive and helpful when I was writing the patch and the __autoload mechanism I'm using is thanks to his input. My problem is that my patch was completely ignored and someone else was assigned to write a patch, when the one I already wrote can be used).

My patch meets all the requirements, except for the following items:

1) "The suggested separator is "\" as this is the only free choice." - I currently use the ':' separator, but this can be easily changed.

2) "Functions in name spaces are allowed." - I added this once and posted the patch to the list, but many (including Andi himself) agreed that we should just stick to classes inside namespaces. The only thing I accomplished was having the function be used as namespace_name:my_function. If a namespace import for functions were to work, then an __autoload for functions would need to be supported in the engine. This has been suggested before, as having a global __call function. With a global __call function, namespace imports can also import functions.

3) "Constants in name spaces are allowed unless we find problems with the implementation." - I have not tried this, but if all agree, I can check to see how easy it would be to add this to my patch.


The attached patch is identical to what I had since August 9th, but was updated to apply cleanly to the latest PHP 5.1 CVS version (it must be applied before running buildconf).

I do not mean to offend anyone or point fingers, and I am sorry if my tone is a bit harsh, but please understand that I have reason to have felt ignored in this whole manner. If you need more information about the "inner workings of my patch", then please email me or post your questions to the list, and I'll be more than happy to explain.


Regards,

Jessie Hernandez


Derick Rethans wrote:
Hello folks!

On 11 and 12 November a bunch of us had a developers meeting in Paris, discussing the things we want to do for PHP 6. Partly because of the Unicode support, but we also discussed the items on "Rasmus' wishlist" and a lot of other items. I made a report of the discussions we had and placed the notes here:

http://php.net/~derick/meeting-notes.html

regards,
Derick

? tests/classes/namespace
Index: ext/spl/php_spl.c
===================================================================
RCS file: /repository/php-src/ext/spl/php_spl.c,v
retrieving revision 1.52.2.15
diff -u -r1.52.2.15 php_spl.c
--- ext/spl/php_spl.c	7 Nov 2005 13:08:24 -0000	1.52.2.15
+++ ext/spl/php_spl.c	22 Nov 2005 03:50:42 -0000
@@ -209,7 +209,21 @@
 	zend_op_array *new_op_array;
 	zval *result = NULL;
 
-	class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension);
+	/* if the class name contains one or more colons, then replace these with
+	   the directory separators */
+	if (strchr(lc_name, ':') != NULL) {
+		char *lc_name_cpy = estrndup(lc_name, class_name_len);
+		char *lc_name_bak = lc_name_cpy;
+
+		while((lc_name_bak = strchr(lc_name_bak, ':')) != NULL) {
+			*lc_name_bak++ = DEFAULT_SLASH;
+		}
+
+		class_file_len = spprintf(&class_file, 0, "%s%s", lc_name_cpy, file_extension);
+		efree(lc_name_cpy);
+	} else {
+		class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension);
+	}
 
 	if (zend_stream_open(class_file, &file_handle TSRMLS_CC) == SUCCESS) {
 		if (!file_handle.opened_path) {
Index: tests/classes/namespace_001.phpt
===================================================================
RCS file: tests/classes/namespace_001.phpt
diff -N tests/classes/namespace_001.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_001.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,25 @@
+--TEST--
+Namespace: Simple Compile-Time Import
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_autoload.php' );
+
+import ns:class1;
+import ns:class2 as ns_class2;
+
+$full = new ns:class1();
+var_dump( $full->mem1 );
+
+$alias = new class1();
+var_dump( $alias->mem1 );
+
+$alias2 = new ns_class2();
+var_dump( $alias2->mem2 );
+
+var_dump( ns_class2::$my_static );
+?>
+--EXPECT--
+int(1)
+int(1)
+int(2)
+string(14) "this is static"
Index: tests/classes/namespace_002.phpt
===================================================================
RCS file: tests/classes/namespace_002.phpt
diff -N tests/classes/namespace_002.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_002.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,17 @@
+--TEST--
+Namespace: Runtime-Resolved Import
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_autoload.php' );
+
+import ns:class1;
+
+$class1_str = 'class1';
+$c1 = new $class1_str();
+var_dump( $c1 );
+?>
+--EXPECT--
+object(ns:class1)#1 (1) {
+  ["mem1"]=>
+  int(1)
+}
Index: tests/classes/namespace_003.phpt
===================================================================
RCS file: tests/classes/namespace_003.phpt
diff -N tests/classes/namespace_003.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_003.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,14 @@
+--TEST--
+Namespace: Private Classes
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_autoload.php' );
+
+import ns:class3;
+
+$class3_str = 'class3';
+$c3 = new $class3_str();
+var_dump( $c3 );
+?>
+--EXPECTREGEX--
+Fatal error: Cannot use class 'ns:class3' outside of its namespace, as it is private.*
Index: tests/classes/namespace_004.phpt
===================================================================
RCS file: tests/classes/namespace_004.phpt
diff -N tests/classes/namespace_004.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_004.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,16 @@
+--TEST--
+Namespace: Public Derived/Private Base
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_autoload.php' );
+
+import ns:class3_child;
+
+$c3 = new class3_child();
+$c3->printValue();
+$c3->callStatic();
+?>
+--EXPECT--
+3
+static called
+
Index: tests/classes/namespace_005.phpt
===================================================================
RCS file: tests/classes/namespace_005.phpt
diff -N tests/classes/namespace_005.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_005.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,16 @@
+--TEST--
+Namespace: Namespace Import
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_autoload.php' );
+
+import namespace ns;
+
+$c1 = new class1();
+var_dump( $c1 );
+?>
+--EXPECT--
+object(ns:class1)#1 (1) {
+  ["mem1"]=>
+  int(1)
+}
Index: tests/classes/namespace_006.phpt
===================================================================
RCS file: tests/classes/namespace_006.phpt
diff -N tests/classes/namespace_006.phpt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_006.phpt	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,12 @@
+--TEST--
+Namespace: Anonymous Namespace
+--FILE--
+<?php
+require_once( dirname( __FILE__ ) . '/namespace_anonymous.php' );
+
+$c = new anon_class();
+var_dump( $c );
+?>
+--EXPECTREGEX--
+inside anonymous namespace
+.*Fatal error: Class \'anon_class\' not found.*
Index: tests/classes/namespace_anonymous.php
===================================================================
RCS file: tests/classes/namespace_anonymous.php
diff -N tests/classes/namespace_anonymous.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_anonymous.php	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,12 @@
+<?php
+namespace
+{
+	class anon_class
+	{
+		public $member = 'inside anonymous namespace';
+	}
+}
+
+$a = new anon_class();
+echo $a->member;
+?>
Index: tests/classes/namespace_autoload.php
===================================================================
RCS file: tests/classes/namespace_autoload.php
diff -N tests/classes/namespace_autoload.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/classes/namespace_autoload.php	22 Nov 2005 03:50:42 -0000
@@ -0,0 +1,25 @@
+<?php
+function __autoload($className)
+{
+	$directoryPrefix = dirname( __FILE__ ) . '/namespace/';
+
+	if( strpos( $className, ':' ) !== false )
+	{
+		require_once( $directoryPrefix . str_replace( ':', '/', $className ) . '.php' );
+	}
+	else
+	{
+		foreach( get_imported_namespaces( $className ) as $importNS )
+		{
+			$tryPath = $directoryPrefix . str_replace( ':', '/', $importNS ) . "/${className}.php";
+
+			if( file_exists( $tryPath ) )
+			{
+				require_once( $tryPath );
+				autoload_import_class( $className, $importNS );
+				break;
+			}
+		}
+	}
+}
+?>
Index: ZendEngine2/zend.c
===================================================================
RCS file: /repository/ZendEngine2/zend.c,v
retrieving revision 1.308.2.4
diff -u -r1.308.2.4 zend.c
--- ZendEngine2/zend.c	15 Nov 2005 13:29:28 -0000	1.308.2.4
+++ ZendEngine2/zend.c	22 Nov 2005 03:50:43 -0000
@@ -34,11 +34,15 @@
 #   define GLOBAL_CLASS_TABLE       global_class_table
 #   define GLOBAL_CONSTANTS_TABLE   global_constants_table
 #   define GLOBAL_AUTO_GLOBALS_TABLE    global_auto_globals_table
+#   define GLOBAL_IMPORT_CLASS_TABLE    global_import_class_table
+#   define GLOBAL_IMPORT_NAMESPACE_TABLE    global_import_namespace_table
 #else
 #   define GLOBAL_FUNCTION_TABLE    CG(function_table)
 #   define GLOBAL_CLASS_TABLE       CG(class_table)
 #   define GLOBAL_AUTO_GLOBALS_TABLE    CG(auto_globals)
 #   define GLOBAL_CONSTANTS_TABLE   EG(zend_constants)
+#   define GLOBAL_IMPORT_CLASS_TABLE    CG(import_class_table)
+#   define GLOBAL_IMPORT_NAMESPACE_TABLE    CG(import_namespace_table)
 #endif
 
 #if defined(ZEND_WIN32) && ZEND_DEBUG
@@ -92,6 +96,8 @@
 HashTable *global_class_table;
 HashTable *global_constants_table;
 HashTable *global_auto_globals_table;
+HashTable *global_import_class_table;
+HashTable *global_import_namespace_table;
 static HashTable *global_persistent_list = NULL;
 #endif
 
@@ -435,6 +441,7 @@
 {
 	zend_function tmp_func;
 	zend_class_entry *tmp_class;
+	HashTable tmp_hash;
 
 	compiler_globals->compiled_filename = NULL;
 
@@ -448,6 +455,25 @@
 
 	zend_set_default_compile_time_values(TSRMLS_C);
 
+	/* initialize namespace variables */
+	compiler_globals->in_anonymous_namespace = 0;
+	compiler_globals->namespace_prefix = NULL;
+	compiler_globals->namespace_prefix_lc = NULL;
+	compiler_globals->namespace_prefix_len = 0;
+	INIT_ZVAL(compiler_globals->extending_child);
+
+	/* initialize the import class table */
+	compiler_globals->import_class_table = (HashTable *) malloc(sizeof(HashTable));
+	compiler_globals->current_import_class_table = NULL;
+	zend_hash_init_ex(compiler_globals->import_class_table, 10, NULL, (dtor_func_t) zend_hash_destroy, , 0);
+	zend_hash_copy(compiler_globals->import_class_table, global_import_class_table, NULL, &tmp_hash, sizeof(tmp_hash));
+
+	/* initialize the import namespace table */
+	compiler_globals->import_namespace_table = (HashTable *) malloc(sizeof(HashTable));
+	compiler_globals->current_import_namespace_table = NULL;
+	zend_hash_init_ex(compiler_globals->import_namespace_table, 10, NULL, (dtor_func_t) zend_hash_destroy, 1, 0);
+	zend_hash_copy(compiler_globals->import_namespace_table, global_import_namespace_table, NULL, &tmp_hash, sizeof(tmp_hash));
+
 	CG(interactive) = 0;
 
 	compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
@@ -470,6 +496,14 @@
 		zend_hash_destroy(compiler_globals->auto_globals);
 		free(compiler_globals->auto_globals);
 	}
+	if (compiler_globals->import_class_table != GLOBAL_IMPORT_CLASS_TABLE) {
+		zend_hash_destroy(compiler_globals->import_class_table);
+		free(compiler_globals->import_class_table);
+	}
+	if (compiler_globals->import_namespace_table != GLOBAL_IMPORT_NAMESPACE_TABLE) {
+		zend_hash_destroy(compiler_globals->import_namespace_table);
+		free(compiler_globals->import_namespace_table);
+	}
 }
 
 
@@ -600,11 +634,15 @@
  	GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
  	GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
  	GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
+ 	GLOBAL_IMPORT_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
+ 	GLOBAL_IMPORT_NAMESPACE_TABLE = (HashTable *) malloc(sizeof(HashTable));
 #ifdef ZTS
  	GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
 #endif
 	zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
 	zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
+	zend_hash_init_ex(GLOBAL_IMPORT_CLASS_TABLE, 10, NULL, (dtor_func_t) zend_hash_destroy, 1, 0);
+	zend_hash_init_ex(GLOBAL_IMPORT_NAMESPACE_TABLE, 10, NULL, (dtor_func_t) zend_hash_destroy, 1, 0);
 
 	zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
 	zend_init_rsrc_list_dtors();
@@ -630,10 +668,18 @@
 	compiler_globals->in_compilation = 0;
 	compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
 	compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
+	compiler_globals->import_class_table = (HashTable *) malloc(sizeof(HashTable));
+	compiler_globals->import_namespace_table = (HashTable *) malloc(sizeof(HashTable));
+	compiler_globals->in_anonymous_namespace = 0;
+	compiler_globals->current_import_class_table = NULL;
+	compiler_globals->current_import_namespace_table = NULL;
+	INIT_ZVAL(compiler_globals->extending_child);
 
 	*compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE;
 	*compiler_globals->class_table = *GLOBAL_CLASS_TABLE;
 	compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE;
+	*compiler_globals->import_class_table = *GLOBAL_IMPORT_CLASS_TABLE;
+	*compiler_globals->import_namespace_table = *GLOBAL_IMPORT_NAMESPACE_TABLE;
 
 	zend_hash_destroy(executor_globals->zend_constants);
 	*executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE;
@@ -688,9 +734,13 @@
 	*GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
 	*GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
 	*GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
+	*GLOBAL_IMPORT_CLASS_TABLE = *compiler_globals->import_class_table;
+	*GLOBAL_IMPORT_NAMESPACE_TABLE = *compiler_globals->import_namespace_table;
 	zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
 	free(compiler_globals->function_table);
 	free(compiler_globals->class_table);
+	free(compiler_globals->import_class_table);
+	free(compiler_globals->import_namespace_table);
 	compiler_globals_ctor(compiler_globals, tsrm_ls);
 	free(EG(zend_constants));
 	executor_globals_ctor(executor_globals, tsrm_ls);
@@ -710,6 +760,8 @@
 
 	zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
 	zend_hash_destroy(GLOBAL_CLASS_TABLE);
+	zend_hash_destroy(GLOBAL_IMPORT_CLASS_TABLE);
+	zend_hash_destroy(GLOBAL_IMPORT_NAMESPACE_TABLE);
 
 	zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
 	free(GLOBAL_AUTO_GLOBALS_TABLE);
@@ -719,6 +771,8 @@
 
 	free(GLOBAL_FUNCTION_TABLE);
 	free(GLOBAL_CLASS_TABLE);
+	free(GLOBAL_IMPORT_CLASS_TABLE);
+	free(GLOBAL_IMPORT_NAMESPACE_TABLE);
 
 	zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
 	free(GLOBAL_CONSTANTS_TABLE);
@@ -727,6 +781,8 @@
 	GLOBAL_FUNCTION_TABLE = NULL;
 	GLOBAL_CLASS_TABLE = NULL;
 	GLOBAL_AUTO_GLOBALS_TABLE = NULL;
++	GLOBAL_IMPORT_CLASS_TABLE = NULL;
++	GLOBAL_IMPORT_NAMESPACE_TABLE = NULL;
 	GLOBAL_CONSTANTS_TABLE = NULL;
 #endif
 	zend_destroy_rsrc_list_dtors();
Index: ZendEngine2/zend_builtin_functions.c
===================================================================
RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v
retrieving revision 1.277.2.5
diff -u -r1.277.2.5 zend_builtin_functions.c
--- ZendEngine2/zend_builtin_functions.c	16 Sep 2005 17:05:06 -0000	1.277.2.5
+++ ZendEngine2/zend_builtin_functions.c	22 Nov 2005 03:50:43 -0000
@@ -76,6 +76,8 @@
 static ZEND_FUNCTION(get_defined_constants);
 static ZEND_FUNCTION(debug_backtrace);
 static ZEND_FUNCTION(debug_print_backtrace);
+static ZEND_FUNCTION(get_imported_namespaces);
+static ZEND_FUNCTION(autoload_import_class);
 #if ZEND_DEBUG
 static ZEND_FUNCTION(zend_test_func);
 #ifdef ZTS
@@ -138,6 +140,8 @@
 	ZEND_FE(get_defined_constants,		NULL)
 	ZEND_FE(debug_backtrace, NULL)
 	ZEND_FE(debug_print_backtrace, NULL)
+	ZEND_FE(get_imported_namespaces, NULL)
+	ZEND_FE(autoload_import_class, NULL)
 #if ZEND_DEBUG
 	ZEND_FE(zend_test_func,		NULL)
 #ifdef ZTS
@@ -1998,6 +2002,113 @@
 }
 /* }}} */
 
+static int copy_namespace_name(zval *name, void *return_array)
+{
+	add_next_index_stringl((zval *) return_array, Z_STRVAL_P(name), Z_STRLEN_P(name), 1);
+	return ZEND_HASH_APPLY_KEEP;
+}
+
+/* {{{ proto array get_imported_namespaces([$className])
+   Returns an array of all imported namespaces. */
+ZEND_FUNCTION(get_imported_namespaces)
+{
+	char *class_name = NULL;
+	char *class_name_lc = NULL;
+	int class_name_len = 0;
+	HashTable *import_table = NULL;
+	zval *referencing_file = NULL;
+ 
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &class_name, &class_name_len) == FAILURE) {
+		return;
+	}
+
+	if (class_name != NULL) {
+		/* lowercase the class name */
+		class_name_lc = zend_str_tolower_dup(class_name, class_name_len);
+
+		if (zend_hash_find(&EG(autoload_class_file_map), class_name_lc, class_name_len + 1, (void **) &referencing_file) == SUCCESS) {
+			zend_hash_find(EG(import_namespace_table), Z_STRVAL_P(referencing_file), Z_STRLEN_P(referencing_file) + 1, (void **) &import_table);
+		}
+	
+		efree(class_name_lc);
+	} else {
+		zend_hash_find(EG(import_namespace_table), zend_get_executed_filename(TSRMLS_C), strlen(zend_get_executed_filename(TSRMLS_C)) + 1, (void **) &import_table);
+	}
+
+	array_init(return_value);
+
+	if (import_table != NULL) {
+		zend_hash_apply_with_argument(import_table, (apply_func_arg_t) copy_namespace_name, return_value TSRMLS_CC);
+	}
+}
+/* }}} */
+
+/* {{{ proto boolean autoload_import_class($className, $namespaceName)
+   Registers a class with its namespace that has been fully imported (can only be used while in an __autoload operation). */
+ZEND_FUNCTION(autoload_import_class)
+{
+	char *class_name = NULL;
+	int class_name_len = 0;
+	char *class_name_lc = NULL;
+	HashTable *current_import_table = NULL;
+	char *full_name = NULL;
+	int full_name_len = 0;
+	zval import_val;
+	char *namespace_name = NULL;
+	int namespace_name_len = 0;
+	zval *referencing_file = NULL;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &class_name, &class_name_len, &namespace_name, &namespace_name_len) == FAILURE) {
+		RETURN_FALSE;
+	}
+
+	/* get lowercased class name */
+	class_name_lc = zend_str_tolower_dup(class_name, class_name_len);
+
+	if (zend_hash_exists(EG(in_autoload), class_name_lc, class_name_len + 1)) {
+		/* get the referencing file name */
+		zend_hash_find(&EG(autoload_class_file_map), class_name_lc, class_name_len + 1, (void **) &referencing_file);
+
+		if (zend_hash_find(EG(import_class_table), Z_STRVAL_P(referencing_file), Z_STRLEN_P(referencing_file) + 1, (void **)&current_import_table) == SUCCESS) {
+			/* make sure this import alias has not been used before */
+			if (zend_hash_exists(current_import_table, class_name_lc, class_name_len + 1)) {
+				zend_error(E_ERROR, "An import was already done with the %s alias", class_name);
+				efree(class_name_lc);
+				RETURN_FALSE;
+			}
+
+			/* get the full class name */
+			full_name_len = namespace_name_len + class_name_len + 1;
+			full_name = malloc(full_name_len + 1);
+			strncpy(full_name, namespace_name, namespace_name_len + 1);
+			strcat(full_name, ":");
+			strcat(full_name, class_name);
+
+			/* initialize the full class name zval */
+			INIT_ZVAL(import_val);
+			Z_STRVAL(import_val) = full_name;
+			Z_STRLEN(import_val) = full_name_len;
+
+			/* add the import alias */
+			if (zend_hash_add(current_import_table, class_name_lc, class_name_len + 1, &import_val, sizeof(import_val), NULL) == FAILURE) {
+				zend_error(E_ERROR, "Could not import %s", class_name);
+				efree(class_name_lc);
+				RETURN_FALSE;
+			}
+
+			efree(class_name_lc);
+			RETURN_TRUE;
+		}
+	} else {
+		zend_error(E_ERROR, "Class %s is not being autoloaded", class_name);
+		RETURN_FALSE;
+	}
+
+	efree(class_name_lc);
+	RETURN_FALSE;
+}
+/* }}} */
+
 /* {{{ proto bool extension_loaded(string extension_name)
    Returns true if the named extension is loaded */
 ZEND_FUNCTION(extension_loaded)
Index: ZendEngine2/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.14
diff -u -r1.647.2.14 zend_compile.c
--- ZendEngine2/zend_compile.c	16 Nov 2005 15:10:56 -0000	1.647.2.14
+++ ZendEngine2/zend_compile.c	22 Nov 2005 03:50:44 -0000
@@ -182,11 +182,34 @@
 }
 
 
+void import_zval_dtor(zval *zv)
+{
+	free(Z_STRVAL_P(zv));
+}
+
 ZEND_API char *zend_set_compiled_filename(char *new_compiled_filename TSRMLS_DC)
 {
 	char **pp, *p;
+	HashTable file_class_imports;
+	HashTable file_namespace_imports;
 	int length = strlen(new_compiled_filename);
 
+	/* make sure the import class hashtable for this file exists */
+	if (!zend_hash_exists(CG(import_class_table), new_compiled_filename, length+1)) {
+		zend_hash_init(&file_class_imports, 10, NULL, (dtor_func_t) import_zval_dtor, 1);
+		zend_hash_add(CG(import_class_table), new_compiled_filename, length + 1, &file_class_imports, sizeof(file_class_imports), NULL);
+	}
+
+	/* make sure the import namespace hashtable for this file exists */
+	if (!zend_hash_exists(CG(import_namespace_table), new_compiled_filename, length+1)) {
+		zend_hash_init(&file_namespace_imports, 10, NULL, (dtor_func_t) import_zval_dtor, 1);
+		zend_hash_add(CG(import_namespace_table), new_compiled_filename, length + 1, &file_namespace_imports, sizeof(file_namespace_imports), NULL);
+	}
+
+	 /* get the import hashtables for this file */
+	zend_hash_find(CG(import_class_table), new_compiled_filename, length + 1, (void **)&CG(current_import_class_table));
+	zend_hash_find(CG(import_namespace_table), new_compiled_filename, length + 1, (void **)&CG(current_import_namespace_table));
+
 	if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
 		CG(compiled_filename) = *pp;
 		return *pp;
@@ -1411,7 +1434,18 @@
 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
 	opline->opcode = ZEND_FETCH_CLASS;
-	SET_UNUSED(opline->op1);
+
+	if (CG(extending_child).type == IS_NULL) {
+		SET_UNUSED(opline->op1);
+	} else {
+		/* copy the child name */
+		INIT_ZVAL(opline->op1.u.constant);
+		opline->op1.op_type = IS_CONST;
+		opline->op1.u.constant.type = IS_STRING;
+		opline->op1.u.constant.value.str.val = estrndup(CG(extending_child).value.str.val, CG(extending_child).value.str.len);
+		opline->op1.u.constant.value.str.len = CG(extending_child).value.str.len;
+	}
+
 	opline->extended_value = ZEND_FETCH_CLASS_GLOBAL;
 	CG(catch_begin) = fetch_class_op_number;
 	if (class_name->op_type == IS_CONST) {
@@ -2689,6 +2723,11 @@
 		zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
 	}
 
+	/* fully prefix the class name */
+	efree(lcname);
+	zend_prefix_class_name_node(class_name TSRMLS_CC);
+	lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+
 	new_class_entry->type = ZEND_USER_CLASS;
 	new_class_entry->name = class_name->u.constant.value.str.val;
 	new_class_entry->name_length = class_name->u.constant.value.str.len;
@@ -2737,6 +2776,11 @@
 	opline->result.op_type = IS_CONST;
 	CG(implementing_class) = opline->result;
 
+	/* if we are in an anonymous namespace, then immediately import this class */
+	if (CG(in_anonymous_namespace)) {
+		zend_do_import(NULL, class_name, NULL, 0 TSRMLS_CC);
+	}
+
 	if (CG(doc_comment)) {
 		CG(active_class_entry)->doc_comment = CG(doc_comment);
 		CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
@@ -2745,6 +2789,191 @@
 	}
 }
 
+/*****************************
+ * BEGIN NAMESPACE FUNCTIONS *
+ *****************************/
+
+void zend_do_begin_extending(znode *child_name TSRMLS_DC)
+{
+	int name_len = Z_STRLEN(child_name->u.constant);
+
+	/* add the namespace prefix length, if applicable */
+	if (CG(namespace_prefix) != NULL) {
+		name_len += CG(namespace_prefix_len);
+	}
+
+	INIT_ZVAL(CG(extending_child));
+	CG(extending_child).type = IS_STRING;
+	Z_STRVAL(CG(extending_child)) = emalloc(name_len + 1);
+	Z_STRLEN(CG(extending_child)) = name_len;
+
+	if (CG(namespace_prefix) != NULL) {
+		/* copy the namespace prefix, then the child name */
+		strncpy(Z_STRVAL(CG(extending_child)), CG(namespace_prefix), CG(namespace_prefix_len) + 1);
+		strcat(Z_STRVAL(CG(extending_child)), Z_STRVAL(child_name->u.constant));
+	} else {
+		/* copy just the class name */
+		strncpy(Z_STRVAL(CG(extending_child)), Z_STRVAL(child_name->u.constant), Z_STRLEN(child_name->u.constant) + 1);
+	}
+}
+
+void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC)
+{
+	char *namespace_name = NULL;
+	int namespace_name_len = 0;
+
+	if (ns_name != NULL) {
+		namespace_name = Z_STRVAL(ns_name->u.constant);
+		namespace_name_len = Z_STRLEN(ns_name->u.constant);
+	} else {
+		/* this is an anonymous namespace */
+		CG(in_anonymous_namespace) = 1;
+		namespace_name = zend_get_compiled_filename(TSRMLS_C);
+		namespace_name_len = strlen(namespace_name);
+	}
+
+	/* allocate space for the namespace prefix */
+	CG(namespace_prefix) = emalloc(namespace_name_len + 2);
+
+	/* get the namespace prefix */
+	strncpy(CG(namespace_prefix), namespace_name, namespace_name_len + 1);
+	strcat(CG(namespace_prefix), ":");
+
+	/* get the lowercased namespace prefix */
+	CG(namespace_prefix_lc) = zend_str_tolower_dup(CG(namespace_prefix), namespace_name_len + 1);
+
+	/* save the prefix length */
+	CG(namespace_prefix_len) = namespace_name_len + 1;
+
+	/* we don't need the namespace name anymore, so free it */
+	if (ns_name != NULL) {
+		zval_dtor(&ns_name->u.constant);
+	}
+}
+
+void zend_do_end_extending(TSRMLS_D)
+{
+	efree(Z_STRVAL(CG(extending_child)));
+	CG(extending_child).type = IS_NULL;
+	Z_STRLEN(CG(extending_child)) = 0;
+	Z_STRVAL(CG(extending_child)) = NULL;
+}
+
+void zend_do_end_namespace(znode *ns_token TSRMLS_DC)
+{
+	/* free the string memory */
+	efree(CG(namespace_prefix));
+	efree(CG(namespace_prefix_lc));
+	CG(namespace_prefix_len) = 0;
+
+	/* set the prefixes to null */
+	CG(namespace_prefix) = NULL;
+	CG(namespace_prefix_lc) = NULL;
+
+	CG(in_anonymous_namespace) = 0;
+}
+
+void zend_do_verify_private_class(TSRMLS_D)
+{
+	if (CG(namespace_prefix) == NULL) {
+		zend_error(E_COMPILE_ERROR, "Cannot declare a private class in the global namespace");
+	}
+}
+
+void zend_do_import(znode *result, znode *class_name, znode *alias_name, zend_bool free_class_name TSRMLS_DC)
+{
+	char *alias_name_lc = NULL;
+	zend_uint alias_name_len = 0;
+	zval alias_val;
+	/* 'colon_pos' is the position of the last colon in the full class name */
+	char *colon_pos = strrchr(Z_STRVAL(class_name->u.constant), ':');
+	/* 'last_pos' is the position of the null terminator in the full class name */
+	char *last_pos = Z_STRVAL(class_name->u.constant) + Z_STRLEN(class_name->u.constant);
+
+	if (colon_pos == NULL) {
+		zend_error(E_COMPILE_ERROR, "Cannot import non-namespace class: %s!", Z_STRVAL(class_name->u.constant));
+		return;
+	}
+
+	if (alias_name == NULL) {
+		/* advance to the first character of the class name */
+		++colon_pos;
+
+		/* get the lowercased class name as the alias */
+		alias_name_len = last_pos - colon_pos;
+		alias_name_lc = zend_str_tolower_dup(colon_pos, alias_name_len);
+	} else /* alias_name != NULL */ {
+		alias_name_lc = zend_str_tolower_dup(Z_STRVAL(alias_name->u.constant), Z_STRLEN(alias_name->u.constant));
+		alias_name_len = Z_STRLEN(alias_name->u.constant);
+		zval_dtor(&alias_name->u.constant);
+	}
+
+	/* make sure this import alias has not been used before */
+	if (zend_hash_exists(CG(current_import_class_table), alias_name_lc, alias_name_len + 1)) {
+		zend_error(E_COMPILE_ERROR, "An import was already done with the %s alias", alias_name_lc);
+		return;
+	}
+
+	/* create the alias value */
+	INIT_ZVAL(alias_val);
+	Z_STRVAL(alias_val) = zend_strndup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+	Z_STRLEN(alias_val) = Z_STRLEN(class_name->u.constant);
+
+	/* add the alias */
+	if (zend_hash_add(CG(current_import_class_table), alias_name_lc, alias_name_len + 1, &alias_val, sizeof(zval), NULL) == FAILURE) {
+		zend_error(E_COMPILE_ERROR, "Could not import %s as %s!", Z_STRVAL(class_name->u.constant), alias_name_lc);
+	}
+
+	if (free_class_name) {
+		zval_dtor(&class_name->u.constant);
+	}
+
+	efree(alias_name_lc);
+}
+
+void zend_do_namespace_import(znode *ns_name TSRMLS_DC)
+{
+	zval name_val;
+
+	INIT_ZVAL(name_val);
+	name_val.type = IS_STRING;
+	Z_STRVAL(name_val) = zend_strndup(Z_STRVAL(ns_name->u.constant), Z_STRLEN(ns_name->u.constant));
+	Z_STRLEN(name_val) = Z_STRLEN(ns_name->u.constant);
+
+	/* we don't need the namespace name anymore, so free it */
+	zval_dtor(&ns_name->u.constant);
+
+	if (zend_hash_next_index_insert(CG(current_import_namespace_table), &name_val, sizeof(name_val), NULL) == FAILURE) {
+		zend_error(E_COMPILE_ERROR, "Could not import namespace %s!", Z_STRVAL(ns_name->u.constant));
+		return;
+	}
+}
+
+void zend_prefix_class_name_node(znode *class_name TSRMLS_DC)
+{
+	zend_uint new_length = 0;
+	char *org_class_name = NULL;
+
+	if (CG(namespace_prefix) != NULL) {
+		new_length = CG(namespace_prefix_len) + Z_STRLEN(class_name->u.constant);
+		org_class_name = estrdup(Z_STRVAL(class_name->u.constant));
+
+		STR_REALLOC(Z_STRVAL(class_name->u.constant), new_length + 1);
+
+		/* get the full class name */
+		strncpy(Z_STRVAL(class_name->u.constant), CG(namespace_prefix), CG(namespace_prefix_len) + 1);
+		strcat(Z_STRVAL(class_name->u.constant), org_class_name);
+
+		/* get the new string length */
+		Z_STRLEN(class_name->u.constant) = new_length;
+
+		efree(org_class_name);
+	}
+}
+
+/***************************
+ * END NAMESPACE FUNCTIONS *
+ ***************************/
 
 static void do_verify_abstract_class(TSRMLS_D)
 {
Index: ZendEngine2/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.5
diff -u -r1.316.2.5 zend_compile.h
--- ZendEngine2/zend_compile.h	20 Oct 2005 07:30:42 -0000	1.316.2.5
+++ ZendEngine2/zend_compile.h	22 Nov 2005 03:50:45 -0000
@@ -387,6 +387,7 @@
 void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 
 int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier);
+void zend_do_verify_private_class(TSRMLS_D);
 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);
@@ -438,6 +439,15 @@
 void zend_do_declare_implicit_property(TSRMLS_D);
 void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC);
 
+void zend_do_begin_extending(znode *child_name TSRMLS_DC);
+void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC);
+void zend_do_end_extending(TSRMLS_D);
+void zend_do_end_namespace(znode *ns_token TSRMLS_DC);
+void zend_do_import(znode *result, znode *class_name, znode *alias_name, zend_bool free_class_name TSRMLS_DC);
+void zend_do_namespace_import(znode *ns_name TSRMLS_DC);
+void zend_do_unimport_all(TSRMLS_D);
+void zend_prefix_class_name_node(znode *class_name TSRMLS_DC);
+
 void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC);
 
 
Index: ZendEngine2/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.4
diff -u -r1.331.2.4 zend_execute_API.c
--- ZendEngine2/zend_execute_API.c	27 Oct 2005 19:25:48 -0000	1.331.2.4
+++ ZendEngine2/zend_execute_API.c	22 Nov 2005 03:50:45 -0000
@@ -135,6 +135,8 @@
 
 	EG(function_table) = CG(function_table);
 	EG(class_table) = CG(class_table);
+	EG(import_class_table) = CG(import_class_table);
+	EG(import_namespace_table) = CG(import_namespace_table);
 
 	EG(in_execution) = 0;
 	EG(in_autoload) = NULL;
@@ -156,6 +158,8 @@
 	}
 	EG(active_symbol_table) = &EG(symbol_table);
 
+	zend_hash_init(&EG(autoload_class_file_map), 1, NULL, ZVAL_PTR_DTOR, 0);
+
 	zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
 	EG(opline_ptr) = NULL;
 
@@ -292,6 +296,8 @@
 			zend_hash_destroy(EG(in_autoload));
 			FREE_HASHTABLE(EG(in_autoload));
 		}
+
+		zend_hash_destroy(&EG(autoload_class_file_map));
 	} zend_end_try();
 }
 
@@ -915,6 +921,112 @@
 }
 
 
+char* zend_get_class_namespace(const char *class_name)
+{
+	int namespace_length = 0;
+	char *result = NULL;
+	char *tmp = strrchr(class_name, ':');
+ 
+	if (tmp != NULL) {
+		namespace_length = tmp - class_name;
+
+		/* get the namespace name, which is everything before the last colon */
+		result = estrndup(class_name, namespace_length);
+		zend_str_tolower(result, namespace_length);
+	}
+ 
+	return result;
+}
+
+
+zval *zend_resolve_class_name_string(char *name, int name_len TSRMLS_DC)
+{
+	HashTable *current_import_table = NULL;
+	char *executed_filename = zend_get_executed_filename(TSRMLS_C);
+	int executed_filename_len = strlen(executed_filename);
+	char *lc_name = NULL;
+	zval* mapped_class_name = NULL;
+
+	if (zend_hash_find(EG(import_class_table), executed_filename, executed_filename_len + 1, (void **)&current_import_table) == SUCCESS) {
+		/* get the lowercased class name */
+		lc_name = zend_str_tolower_dup(name, name_len);
+
+		/* check to see if this class name is actually an import alias */
+		zend_hash_find(current_import_table, lc_name, name_len + 1, (void **)&mapped_class_name);
+
+		/* free the class name string */
+		efree(lc_name);
+	}
+
+	return mapped_class_name;
+}
+
+
+int zend_verify_can_use_class(zend_class_entry *ce TSRMLS_DC)
+{
+	int result = SUCCESS;
+ 
+	/* exit immediately if this is not a private class */
+	if ((ce->ce_flags & ZEND_ACC_PRIVATE) == 0) {
+		return SUCCESS;
+	}
+
+	/* check if we are in compilation mode */
+	if (zend_is_compiling(TSRMLS_C)) {
+		char *class_namespace = zend_get_class_namespace(ce->name);
+		char *current_namespace = NULL;
+
+		if (CG(namespace_prefix) != NULL) {
+			/* copy the namespace prefix minus the last character, which is a colon */
+			current_namespace = estrndup(CG(namespace_prefix), CG(namespace_prefix_len) - 1);
+		}
+
+		/* check if the namespaces match */
+		if (class_namespace != NULL
+			&& (current_namespace == NULL
+			|| strcmp(class_namespace, current_namespace) != 0)) {
+			/* the namespaces don't match, so don't allow use of this class */
+			result = FAILURE;
+		}
+
+		efree(class_namespace);
+		efree(current_namespace);
+	} else /* zend_is_executing */ {
+		char *class_namespace = zend_get_class_namespace(ce->name);
+		char *current_namespace = NULL;
+
+		if (active_opline->opcode == ZEND_FETCH_CLASS && active_opline->op1.op_type == IS_CONST) {
+			current_namespace = zend_get_class_namespace(active_opline->op1.u.constant.value.str.val);
+		} else if (EG(scope) != NULL) {
+			current_namespace = zend_get_class_namespace(EG(scope)->name);
+		}
+
+		/* check if the namespaces match */
+		if (class_namespace != NULL
+			&& (current_namespace == NULL
+			|| strcmp(class_namespace, current_namespace) != 0)) {
+			/* the namespaces don't match, so don't allow use of this class */
+			result = FAILURE;
+		}
+
+		if (class_namespace != NULL) {
+			efree(class_namespace);
+		}
+
+		if (current_namespace != NULL) {
+			efree(current_namespace);
+		}
+	}
+
+	/* generate the error message, if needed */
+	if (result == FAILURE) {
+		zend_error(E_ERROR, "Cannot use class '%s' outside of its namespace, as it is private", ce->name);
+	}
+
+	return result;
+}
+
+
 ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC)
 {
 	zval **args[1];
@@ -927,6 +1039,8 @@
 	char dummy = 1;
 	zend_fcall_info fcall_info;
 	zend_fcall_info_cache fcall_cache;
+	zval executed_filename_val;
+	zval *resolved_name = NULL;
 
 	if (name == NULL) {
 		return FAILURE;
@@ -937,7 +1051,26 @@
 
 	if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
 		free_alloca(lc_name);
-		return SUCCESS;
+		return zend_verify_can_use_class(**ce TSRMLS_CC);
+	}
+
+	/* try to resolve the class name and try again */
+	if ((resolved_name = zend_resolve_class_name_string(name, name_length TSRMLS_CC)) != NULL) {
+		/* get the new name */
+		name = estrndup(Z_STRVAL_P(resolved_name), Z_STRLEN_P(resolved_name));
+		name_length = Z_STRLEN_P(resolved_name);
+
+		/* get the lowercased version of the resolved name */
+		free_alloca(lc_name);
+		lc_name = do_alloca(name_length + 1);
+		zend_str_tolower_copy(lc_name, name, name_length);
+
+		/* try the search with the resolved name */
+		if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
+			free_alloca(lc_name);
+			efree(name);
+			return zend_verify_can_use_class(**ce TSRMLS_CC);
+		}
 	}
 
 	/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
@@ -945,6 +1078,11 @@
 	*/
 	if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
 		free_alloca(lc_name);
+
+		if (resolved_name != NULL) {
+			efree(name);
+		}
+
 		return FAILURE;
 	}
 
@@ -955,9 +1093,19 @@
 	
 	if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
 		free_alloca(lc_name);
+
+		if (resolved_name != NULL) {
+			efree(name);
+		}
+
 		return FAILURE;
 	}
 
+	/* insert the autoload class -> file mapping */
+	INIT_ZVAL(executed_filename_val);
+	ZVAL_STRINGL(&executed_filename_val, zend_get_executed_filename(TSRMLS_C), strlen(zend_get_executed_filename(TSRMLS_C)), 1);
+	zend_hash_add(&EG(autoload_class_file_map), lc_name, name_length + 1, &executed_filename_val, sizeof(executed_filename_val), NULL);
+
 	ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1,  0);
 
 	ALLOC_ZVAL(class_name_ptr);
@@ -988,16 +1136,30 @@
 
 	zval_ptr_dtor(&class_name_ptr);
 
+	/* remove the autoload class -> file mapping */
+	zend_hash_del(&EG(autoload_class_file_map), name, name_length + 1);
+	zval_dtor(&executed_filename_val);
+
 	zend_hash_del(EG(in_autoload), lc_name, name_length+1);
 
 	if (retval == FAILURE) {
 		EG(exception) = exception;
 		free_alloca(lc_name);
+
+		if (resolved_name != NULL) {
+			efree(name);
+		}
+
 		return FAILURE;
 	}
 
 	if (EG(exception) && exception) {
 		free_alloca(lc_name);
+
+		if (resolved_name != NULL) {
+			efree(name);
+		}
+
 		zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
 		return FAILURE;
 	}
@@ -1007,7 +1169,32 @@
 	}
 
 	retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
+
+	/* try to resolve the class name after the autoload and try again */
+	if (retval == FAILURE && (resolved_name = zend_resolve_class_name_string(name, name_length TSRMLS_CC)) != NULL) {
+		/* get the new name */
+		name = estrndup(Z_STRVAL_P(resolved_name), Z_STRLEN_P(resolved_name));
+		name_length = Z_STRLEN_P(resolved_name);
+
+		/* get the lowercased version of the resolved name */
+		free_alloca(lc_name);
+		lc_name = do_alloca(name_length + 1);
+		zend_str_tolower_copy(lc_name, name, name_length);
+
+		/* try the search with the resolved name */
+		retval = zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce);
+	}
+
 	free_alloca(lc_name);
+
+	if (resolved_name != NULL) {
+		efree(name);
+	}
+
+	if (retval == SUCCESS) {
+		retval = zend_verify_can_use_class(**ce TSRMLS_CC);
+	}
+	
 	return retval;
 }
 
Index: ZendEngine2/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.141.2.1
diff -u -r1.141.2.1 zend_globals.h
--- ZendEngine2/zend_globals.h	15 Nov 2005 13:29:28 -0000	1.141.2.1
+++ ZendEngine2/zend_globals.h	22 Nov 2005 03:50:45 -0000
@@ -144,6 +144,17 @@
 	zend_encoding_converter encoding_converter;
 	zend_encoding_oddlen encoding_oddlen;
 #endif /* ZEND_MULTIBYTE */
+
+	/* namespace-related variables */
+	zend_bool in_anonymous_namespace;
+	char *namespace_prefix;
+	char *namespace_prefix_lc;
+	zend_uint namespace_prefix_len;
+	HashTable *import_class_table;
+	HashTable *import_namespace_table;
+	HashTable *current_import_class_table;
+	HashTable *current_import_namespace_table;
+	zval extending_child;
 };
 
 
@@ -233,6 +244,10 @@
 
 	zend_property_info std_property_info;
 
+	HashTable autoload_class_file_map;
+	HashTable *import_class_table;
+	HashTable *import_namespace_table;
+
 	void *reserved[ZEND_MAX_RESERVED_RESOURCES];
 };
 
Index: ZendEngine2/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.2
diff -u -r1.160.2.2 zend_language_parser.y
--- ZendEngine2/zend_language_parser.y	17 Oct 2005 07:57:00 -0000	1.160.2.2
+++ ZendEngine2/zend_language_parser.y	22 Nov 2005 03:50:46 -0000
@@ -145,6 +145,10 @@
 %token T_DOLLAR_OPEN_CURLY_BRACES
 %token T_CURLY_OPEN
 %token T_PAAMAYIM_NEKUDOTAYIM
+%token T_IMPORT
+%token T_NAMESPACE_NAME
+%token T_NAMESPACE
+%token T_NAMESPACE_C
 
 %% /* Rules */
 
@@ -162,6 +166,7 @@
 		statement
 	|	function_declaration_statement	{ zend_do_early_binding(TSRMLS_C); }
 	|	class_declaration_statement		{ zend_do_early_binding(TSRMLS_C); }
+	|	namespace_declaration_statement
 	|	T_HALT_COMPILER '(' ')' ';'   { REGISTER_MAIN_LONG_CONSTANT("__COMPILER_HALT_OFFSET__", zend_get_scanned_file_offset(TSRMLS_C), CONST_CS); YYACCEPT; }
 ;
 
@@ -231,6 +236,8 @@
 		'{' 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); }
+	|	T_IMPORT T_NAMESPACE_NAME ';' { zend_do_import(&$$, &$2, NULL, 1 TSRMLS_CC); }
+	|	T_IMPORT T_NAMESPACE_NAME T_AS T_STRING ';' { zend_do_import(&$$, &$2, &$4, 1 TSRMLS_CC); }
 ;
 
 
@@ -286,8 +293,8 @@
 ;
 
 unticked_class_declaration_statement:
-		class_entry_type T_STRING extends_from
-			{ zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } 
+		class_entry_type T_STRING { zend_do_begin_extending(&$2 TSRMLS_CC); } extends_from { zend_do_end_extending(TSRMLS_C); }
+			{ zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } 
 			implements_list
 			'{'
 				class_statement_list
@@ -305,6 +312,23 @@
 		T_CLASS			{ $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = 0; }
 	|	T_ABSTRACT T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
 	|	T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_FINAL_CLASS; }
+	|	T_PRIVATE T_CLASS { $$.u.opline_num = CG(zend_lineno); zend_do_verify_private_class(TSRMLS_C); $$.u.EA.type = ZEND_ACC_PRIVATE; }
+	|	T_PRIVATE T_ABSTRACT T_CLASS { $$.u.opline_num = CG(zend_lineno); zend_do_verify_private_class(TSRMLS_C); $$.u.EA.type = ZEND_ACC_PRIVATE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
+	|	T_PRIVATE T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); zend_do_verify_private_class(TSRMLS_C); $$.u.EA.type = ZEND_ACC_PRIVATE | ZEND_ACC_FINAL_CLASS; }
+;
+
+namespace_declaration_statement:   	 
+		T_NAMESPACE '{' { zend_do_begin_namespace(&$1, NULL TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$1 TSRMLS_CC); }
+	|	T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$1, &$2 TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$1 TSRMLS_CC); }
+;
+
+namespace_statement_list: 	 
+		namespace_statement_list namespace_statement 	 
+	|	/* empty */ 	 
+; 	 
+
+namespace_statement:
+		class_declaration_statement		{ zend_do_early_binding(TSRMLS_C); }
 ;
 
 extends_from:
@@ -439,6 +463,7 @@
 optional_class_type:
 		/* empty */		{ $$.op_type = IS_UNUSED; }
 	|	T_STRING		{ $$ = $1; }
+	|	T_NAMESPACE_NAME	{ $$ = $1; }
 	|	T_ARRAY		{ $$.op_type = IS_CONST; $$.u.constant.type=IS_NULL;}
 ;
 
@@ -639,10 +664,12 @@
 
 fully_qualified_class_name:
 		T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+	|	T_NAMESPACE_NAME	{ zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
 ;
 
 class_name_reference:
 		T_STRING				{ zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+	|	T_NAMESPACE_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); }
 ;
 
@@ -654,6 +681,10 @@
 	|	base_variable { $$ = $1; }
 ;
 
+namespace_name:   	 
+		T_NAMESPACE_NAME	{ $$ = $1; }
+	|	T_STRING			{ $$ = $1; }
+;
 
 dynamic_class_name_variable_properties:
 		dynamic_class_name_variable_properties dynamic_class_name_variable_property
@@ -687,6 +718,7 @@
 	|	T_CLASS_C					{ $$ = $1; }
 	|	T_METHOD_C					{ $$ = $1; }
 	|	T_FUNC_C					{ $$ = $1; }
+	|	T_NAMESPACE_C				{ $$ = $1; }
 ;
 
 
@@ -910,6 +942,8 @@
 	|	T_EVAL '(' expr ')' 	{ zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
 	|	T_REQUIRE expr			{ zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
 	|	T_REQUIRE_ONCE expr		{ zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
+	|	T_IMPORT T_NAMESPACE T_NAMESPACE_NAME { zend_do_namespace_import(&$3 TSRMLS_CC); }
+	|	T_IMPORT T_NAMESPACE T_STRING { zend_do_namespace_import(&$3 TSRMLS_CC); }
 ;
 
 isset_variables:
Index: ZendEngine2/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.3
diff -u -r1.131.2.3 zend_language_scanner.l
--- ZendEngine2/zend_language_scanner.l	15 Nov 2005 13:29:28 -0000	1.131.2.3
+++ ZendEngine2/zend_language_scanner.l	22 Nov 2005 03:50:46 -0000
@@ -793,6 +793,7 @@
 ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>[EMAIL PROTECTED]
 ANY_CHAR (.|[\n])
 NEWLINE ("\r"|"\n"|"\r\n")
+NAMESPACE_NAME ({LABEL}":")*{LABEL}
 
 %option noyylineno
 %option noyywrap
@@ -926,6 +927,14 @@
 	return T_CLASS;
 }
 
+<ST_IN_SCRIPTING>"namespace" {
+	return T_NAMESPACE;
+}
+
+<ST_IN_SCRIPTING>"import" {
+	return T_IMPORT;
+}
+
 <ST_IN_SCRIPTING>"interface" {
 	return T_INTERFACE;
 }
@@ -1304,6 +1313,25 @@
 	return T_FUNC_C;
 }
 
+<ST_IN_SCRIPTING>"__NAMESPACE__" {
+	char *namespace_name = NULL;
+	int namespace_name_len = 0;
+
+	if (CG(namespace_prefix)) {
+		namespace_name = CG(namespace_prefix);
+		namespace_name_len = CG(namespace_prefix_len);
+	}
+
+	if (!namespace_name) {
+		namespace_name = ":";
+		namespace_name_len = 1;
+	}
+	zendlval->value.str.len = namespace_name_len - 1;
+	zendlval->value.str.val = estrndup(namespace_name, zendlval->value.str.len);
+	zendlval->type = IS_STRING;
+	return T_NAMESPACE_C;
+}
+
 <ST_IN_SCRIPTING>"__METHOD__" {
 	char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
 	char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
@@ -1436,6 +1464,13 @@
 	return T_STRING;
 }
 
+<ST_IN_SCRIPTING>{NAMESPACE_NAME} {
+	zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
+	zendlval->value.str.len = yyleng;
+	zendlval->type = IS_STRING;
+	return T_NAMESPACE_NAME;
+}
+
 <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{LABEL} {
 	zend_copy_value(zendlval, yytext, yyleng);
 	zendlval->type = IS_STRING;

Attachment: tests.tar.gz
Description: GNU Zip compressed data

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to