5 Commits

Author SHA1 Message Date
SVN Migration
2cd8a295d0 This commit was manufactured by cvs2svn to create tag 'RELEASE_0_3'. 2006-02-08 21:22:17 +00:00
Sara Golemon
9d3e29ef40 Prep for 0.3 release 2006-02-08 21:22:16 +00:00
Sara Golemon
3c6fe465db Add patch for 5.0 branch and fix 5.1 patch to be relative to root 2006-02-08 21:08:31 +00:00
Sara Golemon
00288f24ee Bugfix #36288 Saucy little string offsets... 2006-02-05 00:23:35 +00:00
Sara Golemon
cad8f9d1da Add comparator support: ===, !==, ==, !=, <, <=, >, >=
*Note: > and >= require patch to parser to function
2006-02-04 01:33:38 +00:00
7 changed files with 306 additions and 8 deletions

View File

@@ -0,0 +1,66 @@
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.567.2.33
diff -u -r1.567.2.33 zend_compile.c
--- Zend/zend_compile.c 24 Nov 2005 11:33:27 -0000 1.567.2.33
+++ Zend/zend_compile.c 8 Feb 2006 21:05:21 -0000
@@ -235,6 +235,20 @@
}
+void zend_do_binary_compare_op(zend_uchar op, znode *result, znode *op1, znode *op2, zend_uint extval TSRMLS_DC)
+{
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = op;
+ opline->result.op_type = IS_TMP_VAR;
+ opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op1 = *op1;
+ opline->op2 = *op2;
+ opline->extended_value = extval;
+ *result = opline->result;
+}
+
+
void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.284.2.7
diff -u -r1.284.2.7 zend_compile.h
--- Zend/zend_compile.h 20 Sep 2005 11:38:37 -0000 1.284.2.7
+++ Zend/zend_compile.h 8 Feb 2006 21:05:21 -0000
@@ -321,6 +321,8 @@
/* parser-driven code generators */
+#define ZEND_HAVE_DO_BINARY_COMPARE_OP 1
+void zend_do_binary_compare_op(zend_uchar op, znode *result, znode *op1, znode *op2, zend_uint extval TSRMLS_DC);
void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC);
void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.144.2.4
diff -u -r1.144.2.4 zend_language_parser.y
--- Zend/zend_language_parser.y 21 Sep 2005 09:58:10 -0000 1.144.2.4
+++ Zend/zend_language_parser.y 8 Feb 2006 21:05:21 -0000
@@ -585,10 +585,10 @@
| expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
| expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
| expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
+ | expr '<' expr { zend_do_binary_compare_op(ZEND_IS_SMALLER, &$$, &$1, &$3, 0 TSRMLS_CC); }
+ | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_compare_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3, 0 TSRMLS_CC); }
+ | expr '>' expr { zend_do_binary_compare_op(ZEND_IS_SMALLER, &$$, &$3, &$1, 1 TSRMLS_CC); }
+ | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_compare_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1, 1 TSRMLS_CC); }
| expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
| '(' expr ')' { $$ = $2; }
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }

View File

@@ -0,0 +1,66 @@
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.21
diff -u -r1.647.2.21 zend_compile.c
--- Zend/zend_compile.c 4 Jan 2006 23:53:04 -0000 1.647.2.21
+++ Zend/zend_compile.c 8 Feb 2006 21:06:49 -0000
@@ -267,6 +267,20 @@
}
+void zend_do_binary_compare_op(zend_uchar op, znode *result, znode *op1, znode *op2, zend_uint extval TSRMLS_DC)
+{
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = op;
+ opline->result.op_type = IS_TMP_VAR;
+ opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op1 = *op1;
+ opline->op2 = *op2;
+ opline->extended_value = extval;
+ *result = opline->result;
+}
+
+
void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.6
diff -u -r1.316.2.6 zend_compile.h
--- Zend/zend_compile.h 4 Jan 2006 23:53:04 -0000 1.316.2.6
+++ Zend/zend_compile.h 8 Feb 2006 21:06:49 -0000
@@ -336,6 +336,8 @@
/* parser-driven code generators */
+#define ZEND_HAVE_DO_BINARY_COMPARE_OP 1
+void zend_do_binary_compare_op(zend_uchar op, znode *result, znode *op1, znode *op2, zend_uint extval TSRMLS_DC);
void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC);
void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.3
diff -u -r1.160.2.3 zend_language_parser.y
--- Zend/zend_language_parser.y 4 Jan 2006 23:53:04 -0000 1.160.2.3
+++ Zend/zend_language_parser.y 8 Feb 2006 21:06:49 -0000
@@ -597,10 +597,10 @@
| expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
| expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
| expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
+ | expr '<' expr { zend_do_binary_compare_op(ZEND_IS_SMALLER, &$$, &$1, &$3, 0 TSRMLS_CC); }
+ | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_compare_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3, 0 TSRMLS_CC); }
+ | expr '>' expr { zend_do_binary_compare_op(ZEND_IS_SMALLER, &$$, &$3, &$1, 1 TSRMLS_CC); }
+ | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_compare_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1, 1 TSRMLS_CC); }
| expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
| '(' expr ')' { $$ = $2; }
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }

View File

@@ -167,11 +167,13 @@ static inline int _php_operator_decode(zend_op *opline)
}
#define PHP_OPERATOR_OPHANDLER_COUNT ((25 * 151) + 1)
#define PHP_OPERATOR_REPLACE_OPCODE(opname) { int i; for(i = 5; i < 25; i++) if (php_operator_opcode_handlers[(opname*25) + i]) php_operator_opcode_handlers[(opname*25) + i] = php_operator_op_##opname; }
#define PHP_OPERATOR_REPLACE_ALL_OPCODE(opname) { int i; for(i = 0; i < 25; i++) if (php_operator_opcode_handlers[(opname*25) + i]) php_operator_opcode_handlers[(opname*25) + i] = php_operator_op_##opname; }
#define PHP_OPERATOR_DECODE(opline) _php_operator_decode(opline)
#define PHP_OPERATOR_GET_OPLINE zend_op *opline = (execute_data->opline);
#else
#define PHP_OPERATOR_OPHANDLER_COUNT 512
#define PHP_OPERATOR_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = php_operator_op_##opname
#define PHP_OPERATOR_REPLACE_ALL_OPCODE(opname) zend_opcode_handlers[opname] = php_operator_op_##opname
#define PHP_OPERATOR_DECODE(opline) (opline->code)
#define PHP_OPERATOR_GET_OPLINE
#endif
@@ -192,8 +194,23 @@ static inline int _php_operator_binary_op(ZEND_OPCODE_HANDLER_ARGS, const char *
zval *op1 = php_operator_zval_ptr(&(opline->op1), &free_op1, execute_data TSRMLS_CC);
zval *op2 = php_operator_zval_ptr(&(opline->op2), &free_op2, execute_data TSRMLS_CC);
if (opline->op1.op_type == IS_CONST ||
op1->type != IS_OBJECT ||
#ifdef ZEND_HAVE_DO_BINARY_COMPARE_OP
if (opline->extended_value &&
opline->opcode == ZEND_IS_SMALLER) {
zval *swap = op1; op1 = op2; op2 = swap;
methodname = "__is_greater";
methodname_len = sizeof("__is_greater") - 1;
} else if (opline->extended_value &&
opline->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
zval *swap = op1; op1 = op2; op2 = swap;
methodname = "__is_greater_or_equal";
methodname_len = sizeof("__is_greater_or_equal") - 1;
}
#endif
if (!op1 || op1->type != IS_OBJECT ||
!zend_hash_exists(&Z_OBJCE_P(op1)->function_table, (char*)methodname, methodname_len + 1)) {
/* Rely on primary handler */
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -221,7 +238,7 @@ static inline int _php_operator_unary_op(ZEND_OPCODE_HANDLER_ARGS, const char *m
zval *result;
zval *op1 = php_operator_zval_ptr(&(opline->op1), &free_op1, execute_data TSRMLS_CC);
if (opline->op1.op_type == IS_CONST ||
if (!op1 ||
op1->type != IS_OBJECT ||
!zend_hash_exists(&Z_OBJCE_P(op1)->function_table, (char*)methodname, methodname_len + 1)) {
/* Rely on primary handler */
@@ -398,6 +415,14 @@ PHP_OPERATOR_BINARY_OP(ZEND_BW_OR, "__bw_or")
PHP_OPERATOR_BINARY_OP(ZEND_BW_AND, "__bw_and")
PHP_OPERATOR_BINARY_OP(ZEND_BW_XOR, "__bw_xor")
PHP_OPERATOR_BINARY_OP(ZEND_IS_IDENTICAL, "__is_identical")
PHP_OPERATOR_BINARY_OP(ZEND_IS_NOT_IDENTICAL, "__is_not_identical")
PHP_OPERATOR_BINARY_OP(ZEND_IS_EQUAL, "__is_equal")
PHP_OPERATOR_BINARY_OP(ZEND_IS_NOT_EQUAL, "__is_not_equal")
PHP_OPERATOR_BINARY_OP(ZEND_IS_SMALLER, "__is_smaller") /* includes __is_greater when patch applied */
PHP_OPERATOR_BINARY_OP(ZEND_IS_SMALLER_OR_EQUAL, "__is_smaller_or_equal") /* includes __is_greater_or_equal ... */
PHP_OPERATOR_UNARY_OP(ZEND_BW_NOT, "__bw_not")
PHP_OPERATOR_UNARY_OP(ZEND_BOOL, "__bool")
PHP_OPERATOR_UNARY_OP(ZEND_BOOL_NOT, "__bool_not")
@@ -452,6 +477,23 @@ PHP_MINIT_FUNCTION(operator)
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_AND);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_XOR);
/* Comparators (Binaries in disguise) */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_IDENTICAL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_NOT_IDENTICAL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_EQUAL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_NOT_EQUAL);
#ifdef ZEND_HAVE_DO_BINARY_COMPARE_OP
/* __is_greater and __is_greater_or_equal support requires patching parser: compare-greater-VERSION.diff */
REGISTER_LONG_CONSTANT("OPERATOR_COMPARE_PATCH", 1, CONST_CS | CONST_PERSISTENT);
PHP_OPERATOR_REPLACE_ALL_OPCODE(ZEND_IS_SMALLER);
PHP_OPERATOR_REPLACE_ALL_OPCODE(ZEND_IS_SMALLER_OR_EQUAL);
#else
REGISTER_LONG_CONSTANT("OPERATOR_COMPARE_PATCH", 0, CONST_CS | CONST_PERSISTENT);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_SMALLER);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_IS_SMALLER_OR_EQUAL);
#endif
/* Unaries */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_NOT);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BOOL);
@@ -501,7 +543,11 @@ PHP_MINFO_FUNCTION(operator)
{
php_info_print_table_start();
php_info_print_table_header(2, "operator overloading support", "+ - * / % << >> . | & ^ ~ ! ++ -- "
"+= -= *= /= %= <<= >>= .= |= &= ^= ~=");
"+= -= *= /= %= <<= >>= .= |= &= ^= ~= === !== == != < <= "
#ifdef ZEND_HAVE_DO_BINARY_COMPARE_OP
"> >= "
#endif
);
php_info_print_table_end();
}

View File

@@ -1,8 +1,10 @@
<package version="1.0">
<name>operator</name>
<summary>Operator overloading for Objects</summary>
<description>
Operator overloading for +, -, *, /, %, &lt;&lt;, &gt;&gt;, ., |, &amp;, ^, ~, !, ++, -- += -= *= /= %= &lt;&lt;= &gt;&gt;= .= |= &amp;= ^= and ~= operators.
<description>Operator overloading for: +, -, *, /, %, &lt;&lt;, &gt;&gt;, ., |, &amp;, ^, ~, !, ++, --,
+=, -=, *=, /=, %=, &lt;&lt;=, &gt;&gt;=, .=, |=, &amp;=, ^=, ~=,
==, !=, ===, !==, &lt;, and &lt;= operators.
Conditional support for &gt; and &gt;= available with application of a patch.
</description>
<license>PHP</license>
<maintainers>
@@ -14,6 +16,18 @@
</maintainer>
</maintainers>
<release>
<version>0.3</version>
<state>beta</state>
<date>2006-02-03</date>
<notes>* Added support for comparator ops
Note: ZE treats &gt; style comparisons as backwards &lt; comparisons, so what looks like a left-associative greater than becomes a right-associative less-than.
Because of this, overloading the &gt; and &gt;= operators for left-association requires application of a parser patch.
</notes>
</release>
<changelog>
<release>
<version>0.2</version>
<state>beta</state>
@@ -24,7 +38,6 @@
* Refactored opcode handlers</notes>
</release>
<changelog>
<release>
<version>0.1</version>
<state>beta</state>
@@ -40,12 +53,16 @@
<file role="src" name="config.w32"/>
<file role="src" name="operator.c"/>
<file role="src" name="php_operator.h"/>
<file role="src" name="compare-greater-5.0.5.diff"/>
<file role="src" name="compare-greater-5.1.2.diff"/>
<dir role="test" name="tests">
<file role="test" name="unary.phpt"/>
<file role="test" name="binary.phpt"/>
<file role="test" name="incdec.phpt"/>
<file role="test" name="binary_assign.phpt"/>
<file role="test" name="binary_assign_objdim.phpt"/>
<file role="test" name="compare.phpt"/>
<file role="test" name="compare2.phpt"/>
</dir>
</filelist>

View File

@@ -20,7 +20,7 @@
#define PHP_OPERATOR_H
#define PHP_OPERATOR_EXTNAME "operator"
#define PHP_OPERATOR_EXTVER "0.2"
#define PHP_OPERATOR_EXTVER "0.3"
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 0
typedef struct {

69
tests/compare.phpt Normal file
View File

@@ -0,0 +1,69 @@
--TEST--
Basic comparison ops
--SKIPIF--
<?php if(!extension_loaded("operator")) print "skip"; ?>
--FILE--
<?php
class foo {
private $value;
function __is_identical($val) {
return $this->value === $val;
}
function __is_not_identical($val) {
return $this->value !== $val;
}
function __is_equal($val) {
return $this->value == $val;
}
function __is_not_equal($val) {
return $this->value != $val;
}
function __is_smaller($val) {
return $this->value < $val;
}
function __is_smaller_or_equal($val) {
return $this->value <= $val;
}
function __construct($init) {
$this->value = $init;
}
}
$c = new foo(5);
var_dump($c === 5);
var_dump($c === '5');
var_dump($c !== 5);
var_dump($c !== '5');
var_dump($c == 5);
var_dump($c == '5');
var_dump($c == 6);
var_dump($c != 5);
var_dump($c != '5');
var_dump($c != 6);
var_dump($c < 5);
var_dump($c < 6);
var_dump($c <= 5);
var_dump($c <= 4);
--EXPECT--
bool(true)
bool(false)
bool(false)
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)

34
tests/compare2.phpt Normal file
View File

@@ -0,0 +1,34 @@
--TEST--
Extended comparison ops
--SKIPIF--
<?php if(!extension_loaded("operator")) print "skip";
if(!OPERATOR_COMPARE_PATCH) print "skip"; ?>
--FILE--
<?php
class foo {
private $value;
function __is_greater($val) {
return $this->value > $val;
}
function __is_greater_or_equal($val) {
return $this->value >= $val;
}
function __construct($init) {
$this->value = $init;
}
}
$c = new foo(5);
var_dump($c > 5);
var_dump($c > 4);
var_dump($c >= 5);
var_dump($c >= 6);
--EXPECT--
bool(false)
bool(true)
bool(true)
bool(false)