Hi,

With the first release of pecl/phar, I have started thinking about the
implementation of __HALT_COMPILER();

Currently, this code results in a fatal error:

file1.php:
<?php
__HALT_COMPILER();
?>

file2.php:
<?php
__HALT_COMPILER();
?>

file3.php:
<?php
include 'file1.php';
include 'file2.php'; // fatal error - can't declare __HALT_COMPILER();
more than once in the same request
?>

The current implementation simply defines __COMPILER_HALT_OFFSET__ as
the first __HALT_COMPILER();, independent of the file.

However, it occurred to me that it might be easy to fix this by
introducing a hash of halt offsets by file.  After talking to Sara on
IRC, she proved she is truly an internals goddess by suggesting instead
to use a mangled constant name (__COMPILER_HALT_OFFSET__ + filename) and
use the existing global constants hash instead.  So, with that helpful
tip, I whipped up a patch to provide file-specific
__COMPILER_HALT_OFFSET__.  This does change behavior in that
__COMPILER_HALT_OFFSET__ can only be used within the same file that it
is defined.  However, this is extremely unlikely to break any existing
scripts since it was designed for self-contained installers, and to my
knowledge, Phar/PHP_Archive and some auxiliary thing called PHK are the
only things using it.  The benefits to users of phar-like things would
be immense, with no performance degradation for anything except for the
worst case constant lookup where a user requests the value of an
undefined constant (UPPERCASE constant doesn't exist, lowercase constant
doesn't exist).

Anyways, the patch is very short, so I've attached it.  This patch is
against PHP_5_2 (since I consider it a bug fix) and I will happily whip
up a patch against HEAD if it is acceptable.  My assumption here, of
course, is that this would go in 5.2.2 at the earliest since Ilia was
waiting for a CVS lock to release in order to put up 5.2.1 while I was
coding the patch.

Thanks,
Greg
? better_halt.patch.txt
? zlib.patch
? ext/zlib/zlib_filter.c.2
? pear/scripts
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.29
diff -u -r1.647.2.27.2.29 zend_compile.c
--- Zend/zend_compile.c 1 Feb 2007 15:23:46 -0000       1.647.2.27.2.29
+++ Zend/zend_compile.c 7 Feb 2007 05:41:45 -0000
@@ -3094,7 +3094,18 @@
        zend_llist_add_element(fetch_list_ptr, &opline);
 }
 
-
+void zend_do_halt_compiler_register(TSRMLS_D)
+{
+       char *name, *cfilename;
+       char haltoff[] = "__COMPILER_HALT_OFFSET__";
+       int len, clen;
+       cfilename = zend_get_compiled_filename(TSRMLS_C);
+       clen = strlen(cfilename);
+       zend_mangle_property_name(&name, &len, haltoff,
+               sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+       zend_register_long_constant(name, len+1, 
zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
+       pefree(name, 0);
+}
 
 void zend_do_declare_implicit_property(TSRMLS_D)
 {
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.9
diff -u -r1.316.2.8.2.9 zend_compile.h
--- Zend/zend_compile.h 10 Jan 2007 15:58:07 -0000      1.316.2.8.2.9
+++ Zend/zend_compile.h 7 Feb 2007 05:41:46 -0000
@@ -447,6 +447,7 @@
 
 void zend_do_fetch_property(znode *result, znode *object, znode *property 
TSRMLS_DC);
 
+void zend_do_halt_compiler_register(TSRMLS_D);
 
 void zend_do_push_object(znode *object TSRMLS_DC);
 void zend_do_pop_object(znode *object TSRMLS_DC);
Index: Zend/zend_constants.c
===================================================================
RCS file: /repository/ZendEngine2/zend_constants.c,v
retrieving revision 1.71.2.5.2.4
diff -u -r1.71.2.5.2.4 zend_constants.c
--- Zend/zend_constants.c       1 Jan 2007 09:35:46 -0000       1.71.2.5.2.4
+++ Zend/zend_constants.c       7 Feb 2007 05:41:46 -0000
@@ -277,7 +277,7 @@
                
                return retval;
        }
-       
+
        if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) 
== FAILURE) {
                lookup_name = estrndup(name, name_len);
                zend_str_tolower(lookup_name, name_len);
@@ -287,7 +287,26 @@
                                retval=0;
                        }
                } else {
-                       retval=0;
+                       char haltoff[] = "__COMPILER_HALT_OFFSET__";
+                       if (!EG(in_execution)) {
+                               retval = 0;
+                       } else if (name_len == 
sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name, name_len) == 0) 
{
+                               char *cfilename, *haltname;
+                               int len, clen;
+                               cfilename = 
zend_get_executed_filename(TSRMLS_C);
+                               clen = strlen(cfilename);
+                               /* check for __COMPILER_HALT_OFFSET__ */
+                               zend_mangle_property_name(&haltname, &len, 
haltoff,
+                                       sizeof("__COMPILER_HALT_OFFSET__") - 1, 
cfilename, clen, 0);
+                               if (zend_hash_find(EG(zend_constants), 
haltname, len+1, (void **) &c) == SUCCESS) {
+                                       retval = 1;
+                               } else {
+                                       retval=0;
+                               }
+                               pefree(haltname, 0);
+                       } else {
+                               retval = 0;
+                       }
                }
                efree(lookup_name);
        }
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.3
diff -u -r1.160.2.4.2.3 zend_language_parser.y
--- Zend/zend_language_parser.y 10 Jan 2007 15:58:07 -0000      1.160.2.4.2.3
+++ Zend/zend_language_parser.y 7 Feb 2007 05:41:47 -0000
@@ -162,7 +162,7 @@
                statement
        |       function_declaration_statement  { 
zend_do_early_binding(TSRMLS_C); }
        |       class_declaration_statement             { 
zend_do_early_binding(TSRMLS_C); }
-       |       T_HALT_COMPILER '(' ')' ';'   { zval c; if 
(zend_get_constant("__COMPILER_HALT_OFFSET__", 
sizeof("__COMPILER_HALT_OFFSET__") - 1, &c TSRMLS_CC)) { zval_dtor(&c); 
zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used once per 
request"); } else { REGISTER_MAIN_LONG_CONSTANT("__COMPILER_HALT_OFFSET__", 
zend_get_scanned_file_offset(TSRMLS_C), CONST_CS); } YYACCEPT; }
+       |       T_HALT_COMPILER '(' ')' ';'   { 
zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
 ;
 
 

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

Reply via email to