25 Commits

Author SHA1 Message Date
Peter Kokot
ac217a41eb Remove unused Git attributes ident
The `$Id$` keywords were used in CVS and Subversion where they can be
substituted with filename, last revision number change, last changed
date, and last user who changed it.

In Git this functionality is different and can be done with Git
attribute ident. These need to be defined manually for each file in the
`.gitattributes` file and are afterwards replaced with 40-character
hexadecimal blob object name which is based only on the particular file
contents.

This patch simplifies handling of `$Id$` keywords by removing them since
they are not used anymore.
2018-10-04 07:41:13 +02:00
Peter Kokot
f2ccb4a634 Fix some minor whitespace issues
- trim trailing whitespace
- phpt closing tag
- final EOL(s) trimmed and synced
2018-10-04 07:39:54 +02:00
Nat Ryall
32242463b2 Update package.xml
Fix for failed compile due to erroneous tag
2018-10-04 07:37:27 +02:00
Sara Golemon
39815275d8 Sigh, typos... 2017-03-09 15:02:37 -08:00
Sara Golemon
d270470099 Add support for is_greater(_or_equal) back
Support still requires a patch to the runtime,
but it's a really small patch now.
2017-03-09 14:59:26 -08:00
SvenRtbg
063bf71387 Fix typo 2017-03-09 10:50:04 -08:00
Sara Golemon
13d22dba51 Fix README table 2017-03-08 19:26:36 -08:00
Sara Golemon
ea41d2bed1 PHP7 rewrite 2017-03-08 19:23:58 -08:00
Sara Golemon
8d08917aad Add overloading for direct assignment.
class Foo {
  public $val;

  public function __assign($val) {
    $this->val = $val;
  }
}

$f = new Foo;
$f = 123;
var_dump($f->val); // int(123)
2013-07-17 04:19:43 -07:00
Sara Golemon
63f17c8743 Apply patch from Bug#56904 because it can't hurt.
Also add test case for the observed behavior.
2013-07-17 03:09:22 -07:00
Sara Golemon
214fb2cd8d PHP-5.5 compat 2013-03-03 11:34:03 -08:00
Sara Golemon
7f9dbc34ea PHP-5.4 compat 2013-03-03 11:33:56 -08:00
Sara Golemon
f763d3b6d4 PHP-5.3 compat 2013-03-03 08:24:12 -08:00
Sara Golemon
dc4963d28f Add .gitignore 2013-03-03 08:23:41 -08:00
Pierre Joye
382784abce - update to package.xml v2 2009-11-05 16:54:35 +00:00
Gwynne Raskind
a1417fd74e fix a huge number of wrong MIME types. UGH. 2009-07-13 12:15:13 +00:00
Steph Fox
73e1d2d007 - Bring the majority of PECL extensions into line with macro/x.x.x versioning.
- Please use the -dev tag during the development cycle so that snapshots can easily be distinguished from releases.
2008-03-31 10:01:43 +00:00
Sebastian Bergmann
45efaa097e Copy .cvsignore file from pecl/runkit. 2006-11-17 12:46:30 +00:00
Sara Golemon
12993438af Update (c) info 2006-06-07 17:35:36 +00:00
Sara Golemon
cf21cb13c6 Remove bool/bool_not ops; They should not have been added 2006-05-15 20:26:31 +00:00
Sara Golemon
7ad81b5389 Bugfix #6847: Compile failure under PHP 5.0.x 2006-02-21 03:45:04 +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
15 changed files with 579 additions and 710 deletions

31
.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
/.deps
/.libs/
/Makefile
/Makefile.fragments
/Makefile.global
/Makefile.objects
/acinclude.m4
/aclocal.m4
/autom4te.cache/
/build/
/config.cache
/config.guess
/config.h
/config.h.in
/config.log
/config.nice
/config.status
/config.sub
/configure
/configure.ac
/configure.in
/install-sh
/libtool
/ltmain.sh
/missing
/mkinstalldirs
/modules/
/php_test_results_*.txt
/run-tests.php
/*.lo
/*.la

View File

@@ -1,3 +1,2 @@
operator
Sara Golemon

68
README.md Normal file
View File

@@ -0,0 +1,68 @@
# Operator overloading extension for PHP7
## Usage
Implement magic methods in a class to provide operator overloading automatically, for example:
```php
class C {
private $value = 0;
public function __add($delta) {
$this->value += $delta;
return $this;
}
public function __toString() {
return strval($this->value);
}
}
$c = new C;
var_dump($c + 5); // object(C)#1 { ["C:value:private"]=>5 }
```
The following overload methods are supported:
| Operator | Method |
|:---:| --- |
| $o + $arg | `__add($arg)` |
| $o - $arg | `__sub($arg)` |
| $o * $arg | `__mul($arg)` |
| $o / $arg | `__div($arg)` |
| $o % $arg | `__mod($arg)` |
| $o ** $arg | `__pow($arg)` |
| $o << $arg | `__sl($arg)` |
| $o >> $arg | `__sr($arg)` |
| $o . $arg | `__concat($arg)` |
| $o &#x7c; $arg | `__bw_or($arg)` |
| $o & $arg | `__bw_and($arg)` |
| $o ^ $arg | `__bw_xor($arg)` |
| ~$o | `__bw_not()` |
| $o === $arg | `__is_identical($arg)` |
| $o !== $arg | `__is_not_identical($arg)` |
| $o == $arg | `__is_equal($arg)` |
| $o != $arg | `__is_not_equal($arg)` |
| $o < $arg | `__is_smaller($arg)` |
| $o <= $arg | `__is_smaller_or_equal($arg)` |
| $o > $arg | `__is_greater($arg)` &#42; |
| $o >= $arg | `__is_greater_or_equal($arg)` &#42; |
| $o <=> $arg | `__cmp($arg)` |
| ++$o | `__pre_inc()` |
| $o++ | `__post_inc()` |
| --$o | `__pre_dec()` |
| $o-- | `__post_dec()` |
| $o = $arg | `__assign($arg)` |
| $o += $arg | `__assign_add($arg)` |
| $o -= $arg | `__assign_sub($arg)` |
| $o *= $arg | `__assign_mul($arg)` |
| $o /= $arg | `__assign_div($arg)` |
| $o %= $arg | `__assign_mod($arg)` |
| $o **= $arg | `__assign_pow($arg)` |
| $o <<= $arg | `__assign_sl($arg)` |
| $o >>= $arg | `__assign_sr($arg)` |
| $o .= $arg | `__assign_concat($arg)` |
| $o &#x7c;= $arg | `__assign_bw_or($arg)` |
| $o &= $arg | `__assign_bw_and($arg)` |
| $o ^= $arg | `__assign_bw_xor($arg)` |
&#42; - `__is_greater()` and `__is_greater_or_equal()` require a rebuild of the main PHP runtime using the [included patch](php7-is_greater.diff). Withtout this patch, `$a > $b` is automatically remapped to `$b < $a` by the engine.

View File

@@ -1,4 +1,3 @@
dnl $Id$
dnl config.m4 for extension operators
PHP_ARG_ENABLE(operator, whether to enable operator overload support,

View File

@@ -1,4 +1,3 @@
// $Id$
// vim:ft=javascript
ARG_ENABLE("operator", "enable operator overload support", "no");
@@ -7,4 +6,3 @@ if (PHP_OPERATOR != "no") {
AC_DEFINE("ZEND_VM_KIND", 1, "CFLAGS_OPERATOR");
EXTENSION("operator", "operator.c");
}

View File

@@ -1,528 +1,236 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sara Golemon <pollita@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
# include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_operator.h"
#ifndef ZEND_VM_KIND_CALL
/* ZEND_VM_KIND gets defined to this, but this doesn't get defined... go figure... */
#define ZEND_VM_KIND_CALL 1
#endif
#define USE_OPLINE const zend_op *opline = EX(opline);
#define GET_OP1_ZVAL_PTR_UNDEF(fetch) \
get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, execute_data)
#define GET_OP2_ZVAL_PTR_UNDEF(fetch) \
get_zval_ptr_undef(opline->op2_type, opline->op2, &free_op2, execute_data)
#if (PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0) && ZEND_VM_KIND != ZEND_VM_KIND_CALL
# error "Operator overload support requires CALL style Zend VM"
#endif
#define FREE_OP1 if (free_op1) { zval_ptr_dtor_nogc(free_op1); }
#define FREE_OP2 if (free_op2) { zval_ptr_dtor_nogc(free_op2); }
/* ***********
* Helpers *
*********** */
#define PHP_OPERATOR_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
static inline int php_operator_method(zval *result, zval *op1, const char *method, int method_len, zval *op2 TSRMLS_DC)
{
zval *caller;
int ret;
ALLOC_INIT_ZVAL(caller);
array_init(caller);
ZVAL_ADDREF(op1);
add_index_zval(caller, 0, op1);
add_index_stringl(caller, 1, (char*)method, method_len, 1);
ret = call_user_function(EG(function_table), NULL, caller, result, op2 ? 1 : 0, op2 ? &op2 : NULL TSRMLS_CC);
zval_ptr_dtor(&caller);
return ret;
static
zval *get_zval_ptr_undef(zend_uchar op_type, znode_op op, zend_free_op *free_op,
zend_execute_data *execute_data) {
switch (op_type) {
case IS_TMP_VAR:
case IS_VAR: return (*free_op = EX_VAR(op.var));
case IS_CONST: return EX_CONSTANT(op);
case IS_CV: return EX_VAR(op.var);
default: return NULL;
}
}
static inline zval *php_operator_zval_ptr(znode *node, zend_free_op *should_free, zend_execute_data *execute_data TSRMLS_DC)
{
should_free->var = NULL;
/* ----------------------------------------------------------------------- */
switch (node->op_type) {
case IS_CONST:
return &(node->u.constant);
case IS_VAR:
return PHP_OPERATOR_EX_T(node->u.var).var.ptr;
case IS_TMP_VAR:
return (should_free->var = &PHP_OPERATOR_EX_T(node->u.var).tmp_var);
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0
case IS_CV:
{
zval ***ret = &execute_data->CVs[node->u.var];
#define UNARY_OPS(X) \
X(BW_NOT, __bw_not)
if (!*ret) {
zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ret)==FAILURE) {
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
return &EG(uninitialized_zval);
}
}
return **ret;
}
#endif
case IS_UNUSED:
default:
return NULL;
}
#define BINARY_OPS(X) \
X(ADD, __add) \
X(SUB, __sub) \
X(MUL, __mul) \
X(DIV, __div) \
X(MOD, __mod) \
X(POW, __pow) \
X(SL, __sl) \
X(SR, __sr) \
X(CONCAT, __concat) \
X(BW_OR, __bw_or) \
X(BW_AND, __bw_and) \
X(BW_XOR, __bw_xor) \
X(IS_IDENTICAL, __is_identical) \
X(IS_NOT_IDENTICAL, __is_not_identical) \
X(IS_EQUAL, __is_equal) \
X(IS_NOT_EQUAL, __is_not_equal) \
X(IS_SMALLER, __is_smaller) \
X(IS_SMALLER_OR_EQUAL, __is_smaller_or_equal) \
X(SPACESHIP, __cmp)
#define UNARY_ASSIGN_OPS(X) \
X(PRE_INC, __pre_inc) \
X(POST_INC, __post_inc) \
X(PRE_DEC, __pre_dec) \
X(POST_DEC, __post_dec)
#define BINARY_ASSIGN_OPS(X) \
X(ASSIGN, __assign) \
X(ASSIGN_ADD, __assign_add) \
X(ASSIGN_SUB, __assign_sub) \
X(ASSIGN_MUL, __assign_mul) \
X(ASSIGN_DIV, __assign_div) \
X(ASSIGN_MOD, __assign_mod) \
X(ASSIGN_POW, __assign_pow) \
X(ASSIGN_SL, __assign_sl) \
X(ASSIGN_SR, __assign_sr) \
X(ASSIGN_CONCAT, __assign_concat) \
X(ASSIGN_BW_OR, __assign_bw_or) \
X(ASSIGN_BW_AND, __assign_bw_and) \
X(ASSIGN_BW_XOR, __assign_bw_xor)
#define ALL_OPS(X) \
UNARY_OPS(X) \
BINARY_OPS(X) \
UNARY_ASSIGN_OPS(X) \
BINARY_ASSIGN_OPS(X)
/* greater/greater-equal are encoded as smaller/smaller-equal
* so they require special handling
*/
#define GREATER_OPS(X) \
X(IS_SMALLER, __is_greater) \
X(IS_SMALLER_OR_EQUAL, __is_greater_or_equal)
#define X(op, meth) static zend_string *s_##meth;
ALL_OPS(X)
GREATER_OPS(X)
#undef X
/* {{{ operator_method_name */
static inline zend_string* operator_method_name(zend_uchar opcode) {
switch (opcode) {
#define X(op, meth) case ZEND_##op: return s_##meth;
ALL_OPS(X)
#undef X
default:
ZEND_ASSERT(0);
return NULL;
}
}
/* }}} */
static inline zval **php_operator_zval_ptr_ptr(znode *node, zend_execute_data *execute_data TSRMLS_DC)
{
switch (node->op_type) {
case IS_VAR:
return PHP_OPERATOR_EX_T(node->u.var).var.ptr_ptr;
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0
case IS_CV:
{
zval ***ret = &execute_data->CVs[node->u.var];
/* {{{ operator_get_method */
static zend_bool operator_get_method(zend_string *method, zval *obj,
zend_fcall_info *fci,
zend_fcall_info_cache *fcc) {
memset(fci, 0, sizeof(zend_fcall_info));
fci->size = sizeof(zend_fcall_info);
fci->object = Z_OBJ_P(obj);
ZVAL_STR(&(fci->function_name), method);
if (!*ret) {
zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ret)==FAILURE) {
zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
return &EG(uninitialized_zval_ptr);
}
}
return *ret;
}
#endif
case IS_CONST:
case IS_TMP_VAR:
case IS_UNUSED:
default:
return NULL;
}
if (!zend_is_callable_ex(&(fci->function_name), fci->object,
IS_CALLABLE_CHECK_SILENT | IS_CALLABLE_STRICT,
NULL, fcc, NULL)) {
return 0;
}
/* Disallow dispatch via __call */
if (fcc->function_handler == Z_OBJCE_P(obj)->__call) { return 0; }
if (fcc->function_handler->type == ZEND_USER_FUNCTION) {
zend_op_array *oparray = (zend_op_array*)(fcc->function_handler);
if (oparray->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
return 0;
}
}
return 1;
}
/* }}} */
static inline zval *php_operator_get_result_ptr(zend_op *opline, zend_execute_data *execute_data)
{
zval *tmp;
if (opline->result.op_type == IS_TMP_VAR) {
return &PHP_OPERATOR_EX_T(opline->result.u.var).tmp_var;
}
ALLOC_INIT_ZVAL(tmp);
return tmp;
/* {{{ operator_is_greater_op */
static inline zend_bool operator_is_greater_op(const zend_op *opline, zend_string **pmethod) {
if (opline->extended_value == 1) {
switch (opline->opcode) {
#define X(op, meth) \
case ZEND_##op: *pmethod = s_##meth; return 1;
GREATER_OPS(X)
#undef X
}
}
return 0;
}
/* }}} */
static inline void php_operator_set_result_ptr(zval *result, zend_op *opline, zend_execute_data *execute_data)
{
switch (opline->result.op_type) {
case IS_TMP_VAR:
/* Nothing to do */
return;
case IS_VAR:
PHP_OPERATOR_EX_T(opline->result.u.var).var.ptr = result;
PHP_OPERATOR_EX_T(opline->result.u.var).var.ptr_ptr = &PHP_OPERATOR_EX_T(opline->result.u.var).var.ptr;
return;
default:
zval_ptr_dtor(&result);
}
/* {{{ op_handler */
static int op_handler(zend_execute_data *execute_data) {
USE_OPLINE
zend_free_op free_op1 = NULL, free_op2 = NULL;
zval *op1, *op2 = NULL;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_string *method = operator_method_name(opline->opcode);
if (opline->op1_type == IS_UNUSED) {
/* Assign op */
op1 = EX_VAR(opline->result.var);
} else {
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
}
ZVAL_DEREF(op1);
switch (opline->opcode) {
#define X(op, meth) \
case ZEND_##op:
BINARY_OPS(X)
BINARY_ASSIGN_OPS(X)
#undef X
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
}
if (operator_is_greater_op(opline, &method)) {
zval *tmp = op1;
zend_free_op free_tmp = free_op1;
op1 = op2; op2 = tmp;
free_op1 = free_op2; free_op2 = free_tmp;
}
if ((Z_TYPE_P(op1) != IS_OBJECT) ||
!operator_get_method(method, op1, &fci, &fcc)) {
/* Not an overloaded call */
return ZEND_USER_OPCODE_DISPATCH;
}
fci.retval = EX_VAR(opline->result.var);
fci.params = op2;
fci.param_count = op2 ? 1 : 0;
if (FAILURE == zend_call_function(&fci, &fcc)) {
php_error(E_WARNING, "Failed calling %s::%s()", Z_OBJCE_P(op1)->name, Z_STRVAL(fci.function_name));
ZVAL_NULL(fci.retval);
}
FREE_OP2
FREE_OP1
EX(opline) = opline + 1;
return ZEND_USER_OPCODE_CONTINUE;
}
/* }}} */
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0
static inline int _php_operator_decode(zend_op *opline)
{
int ret = opline->opcode * 25;
switch (opline->op1.op_type) {
case IS_CONST: break;
case IS_TMP_VAR: ret += 5; break;
case IS_VAR: ret += 10; break;
case IS_UNUSED: ret += 15; break;
case IS_CV: ret += 20; break;
}
switch (opline->op2.op_type) {
case IS_CONST: break;
case IS_TMP_VAR: ret += 1; break;
case IS_VAR: ret += 2; break;
case IS_UNUSED: ret += 3; break;
case IS_CV: ret += 4; break;
}
return ret;
/* {{{ MINIT */
static PHP_MINIT_FUNCTION(operator) {
#define X(op, meth) \
s_##meth = zend_string_init(#meth, strlen(#meth), 1);
GREATER_OPS(X)
#undef X
#define X(op, meth) \
s_##meth = zend_string_init(#meth, strlen(#meth), 1); \
zend_set_user_opcode_handler(ZEND_##op, op_handler);
ALL_OPS(X)
#undef X
return SUCCESS;
}
#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_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_DECODE(opline) (opline->code)
#define PHP_OPERATOR_GET_OPLINE
#endif
/* }}} */
static opcode_handler_t *php_operator_original_opcode_handlers;
static opcode_handler_t php_operator_opcode_handlers[PHP_OPERATOR_OPHANDLER_COUNT];
/* *******************
* Op Replacements *
******************* */
#define PHP_OPERATOR_BINARY_OP(opname,methodname) static int php_operator_op_##opname (ZEND_OPCODE_HANDLER_ARGS) { return _php_operator_binary_op(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, methodname, sizeof(methodname) - 1); }
static inline int _php_operator_binary_op(ZEND_OPCODE_HANDLER_ARGS, const char *methodname, int methodname_len)
{
PHP_OPERATOR_GET_OPLINE
zend_free_op free_op1, free_op2;
zval *result;
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 ||
!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);
}
result = php_operator_get_result_ptr(opline, execute_data);
if (php_operator_method(result, op1, methodname, methodname_len, op2 TSRMLS_CC) == FAILURE) {
/* Fallback on original handler */
if (opline->result.op_type != IS_TMP_VAR) zval_ptr_dtor(&result);
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
php_operator_set_result_ptr(result, opline, execute_data);
if (free_op1.var) zval_dtor(free_op1.var);
if (free_op2.var) zval_dtor(free_op2.var);
execute_data->opline++;
return 0;
}
#define PHP_OPERATOR_UNARY_OP(opname,methodname) static int php_operator_op_##opname (ZEND_OPCODE_HANDLER_ARGS) { return _php_operator_unary_op(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, methodname, sizeof(methodname) - 1); }
static inline int _php_operator_unary_op(ZEND_OPCODE_HANDLER_ARGS, const char *methodname, int methodname_len)
{
PHP_OPERATOR_GET_OPLINE
zend_free_op free_op1;
zval *result;
zval *op1 = php_operator_zval_ptr(&(opline->op1), &free_op1, execute_data TSRMLS_CC);
if (opline->op1.op_type == IS_CONST ||
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);
}
result = php_operator_get_result_ptr(opline, execute_data);
if (php_operator_method(result, op1, methodname, methodname_len, NULL TSRMLS_CC) == FAILURE) {
/* Fallback on original handler */
if (opline->result.op_type != IS_TMP_VAR) zval_ptr_dtor(&result);
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
php_operator_set_result_ptr(result, opline, execute_data);
if (free_op1.var) zval_dtor(free_op1.var);
execute_data->opline++;
return 0;
}
#define PHP_OPERATOR_BINARY_ASSIGN_OP(opname,methodname) static int php_operator_op_##opname (ZEND_OPCODE_HANDLER_ARGS) { return _php_operator_binary_assign_op(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, methodname, sizeof(methodname) - 1); }
static int _php_operator_binary_assign_op(ZEND_OPCODE_HANDLER_ARGS, const char *methodname, int methodname_len)
{
PHP_OPERATOR_GET_OPLINE
zend_free_op free_value, free_prop, free_obj;
zval *var = NULL, *value, *result;
zend_bool increment_opline = 0;
free_prop.var = free_obj.var = NULL;
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
case ZEND_ASSIGN_DIM:
{
zend_op *opdata = opline + 1;
zval *object = php_operator_zval_ptr(&(opline->op1), &free_obj, execute_data TSRMLS_CC);
zval *prop = php_operator_zval_ptr(&(opline->op2), &free_prop, execute_data TSRMLS_CC);
if (!object || Z_TYPE_P(object) != IS_OBJECT) {
/* Let orignal handler throw error */
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
increment_opline = 1;
value = php_operator_zval_ptr(&(opdata->op1), &free_value, execute_data TSRMLS_CC);
if (!value) {
/* Shouldn't happen */
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
/* Plan A */
if (opline->extended_value == ZEND_ASSIGN_OBJ &&
Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
zval **varpp = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, prop TSRMLS_CC);
if (varpp) {
var = *varpp;
break;
}
}
/* Plan B */
if (opline->extended_value == ZEND_ASSIGN_OBJ &&
Z_OBJ_HT_P(object)->read_property) {
var = Z_OBJ_HT_P(object)->read_property(object, prop, BP_VAR_RW TSRMLS_CC);
} else if (opline->extended_value == ZEND_ASSIGN_DIM &&
Z_OBJ_HT_P(object)->read_dimension) {
var = Z_OBJ_HT_P(object)->read_dimension(object, prop, BP_VAR_RW TSRMLS_CC);
}
break;
}
default:
var = php_operator_zval_ptr(&(opline->op1), &free_obj, execute_data TSRMLS_CC);
value = php_operator_zval_ptr(&(opline->op2), &free_value, execute_data TSRMLS_CC);
}
if (!var || Z_TYPE_P(var) != IS_OBJECT ||
!zend_hash_exists(&Z_OBJCE_P(var)->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);
}
result = php_operator_get_result_ptr(opline, execute_data);
if (php_operator_method(result, var, methodname, methodname_len, value TSRMLS_CC) == FAILURE) {
/* Fallback on original handler */
if (opline->result.op_type != IS_TMP_VAR) zval_ptr_dtor(&result);
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (free_prop.var) zval_dtor(free_prop.var);
if (free_value.var) zval_dtor(free_value.var);
php_operator_set_result_ptr(result, opline, execute_data);
execute_data->opline += increment_opline ? 2 : 1;
return 0;
}
#define PHP_OPERATOR_UNARY_ASSIGN_OP(opname,methodname) static int php_operator_op_##opname (ZEND_OPCODE_HANDLER_ARGS) { return _php_operator_unary_assign_op(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, methodname, sizeof(methodname) - 1); }
static inline int _php_operator_unary_assign_op(ZEND_OPCODE_HANDLER_ARGS, const char *methodname, int methodname_len)
{
PHP_OPERATOR_GET_OPLINE
zval *result;
zval **op1 = php_operator_zval_ptr_ptr(&(opline->op1), execute_data TSRMLS_CC);
if (!op1 || Z_TYPE_PP(op1) != IS_OBJECT ||
!zend_hash_exists(&Z_OBJCE_PP(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);
}
result = php_operator_get_result_ptr(opline, execute_data);
if (php_operator_method(result, *op1, methodname, methodname_len, NULL TSRMLS_CC) == FAILURE) {
/* Fallback on original handler */
if (opline->result.op_type != IS_TMP_VAR) zval_ptr_dtor(&result);
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
php_operator_set_result_ptr(result, opline, execute_data);
execute_data->opline++;
return 0;
}
#define PHP_OPERATOR_UNARY_ASSIGN_OBJ_OP(opname,methodname) static int php_operator_op_##opname (ZEND_OPCODE_HANDLER_ARGS) { return _php_operator_unary_assign_obj_op(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, methodname, sizeof(methodname) - 1); }
static inline int _php_operator_unary_assign_obj_op(ZEND_OPCODE_HANDLER_ARGS, const char *methodname, int methodname_len)
{
PHP_OPERATOR_GET_OPLINE
zend_free_op free_obj, free_prop;
zval *result;
zval *obj = php_operator_zval_ptr(&(opline->op1), &free_obj, execute_data TSRMLS_CC);
zval *prop = php_operator_zval_ptr(&(opline->op2), &free_prop, execute_data TSRMLS_CC);
zval *var = NULL;
if (!obj || Z_TYPE_P(obj) != IS_OBJECT || !prop) {
/* Rely on primary handler */
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (Z_OBJ_HT_P(obj)->get_property_ptr_ptr) {
zval **varpp = Z_OBJ_HT_P(obj)->get_property_ptr_ptr(obj, prop TSRMLS_CC);
if (varpp) {
var = *varpp;
}
}
if (!var && Z_OBJ_HT_P(obj)->read_property) {
var = Z_OBJ_HT_P(obj)->read_property(obj, prop, BP_VAR_RW TSRMLS_CC);
}
if (!var || Z_TYPE_P(var) != IS_OBJECT ||
!zend_hash_exists(&Z_OBJCE_P(var)->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);
}
result = php_operator_get_result_ptr(opline, execute_data);
if (php_operator_method(result, var, methodname, methodname_len, NULL TSRMLS_CC) == FAILURE) {
/* Fallback on original handler */
if (opline->result.op_type != IS_TMP_VAR) zval_ptr_dtor(&result);
return php_operator_original_opcode_handlers[PHP_OPERATOR_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (free_obj.var) { zval_dtor(free_obj.var); }
if (free_prop.var) { zval_dtor(free_prop.var); }
php_operator_set_result_ptr(result, opline, execute_data);
execute_data->opline++;
return 0;
}
PHP_OPERATOR_BINARY_OP(ZEND_ADD, "__add")
PHP_OPERATOR_BINARY_OP(ZEND_SUB, "__sub")
PHP_OPERATOR_BINARY_OP(ZEND_MUL, "__mul")
PHP_OPERATOR_BINARY_OP(ZEND_DIV, "__div")
PHP_OPERATOR_BINARY_OP(ZEND_MOD, "__mod")
PHP_OPERATOR_BINARY_OP(ZEND_SL, "__sl")
PHP_OPERATOR_BINARY_OP(ZEND_SR, "__sr")
PHP_OPERATOR_BINARY_OP(ZEND_CONCAT, "__concat")
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_UNARY_OP(ZEND_BW_NOT, "__bw_not")
PHP_OPERATOR_UNARY_OP(ZEND_BOOL, "__bool")
PHP_OPERATOR_UNARY_OP(ZEND_BOOL_NOT, "__bool_not")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_ADD, "__assign_add")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_SUB, "__assign_sub")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_MUL, "__assign_mul")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_DIV, "__assign_div")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_MOD, "__assign_mod")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_SL, "__assign_sl")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_SR, "__assign_sr")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_CONCAT, "__assign_concat")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_BW_OR, "__assign_bw_or")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_BW_AND, "__assign_bw_and")
PHP_OPERATOR_BINARY_ASSIGN_OP(ZEND_ASSIGN_BW_XOR, "__assign_bw_xor")
PHP_OPERATOR_UNARY_ASSIGN_OP(ZEND_PRE_INC, "__pre_inc")
PHP_OPERATOR_UNARY_ASSIGN_OP(ZEND_PRE_DEC, "__pre_dec")
PHP_OPERATOR_UNARY_ASSIGN_OP(ZEND_POST_INC, "__post_inc")
PHP_OPERATOR_UNARY_ASSIGN_OP(ZEND_POST_DEC, "__post_dec")
PHP_OPERATOR_UNARY_ASSIGN_OBJ_OP(ZEND_PRE_INC_OBJ, "__pre_inc")
PHP_OPERATOR_UNARY_ASSIGN_OBJ_OP(ZEND_PRE_DEC_OBJ, "__pre_dec")
PHP_OPERATOR_UNARY_ASSIGN_OBJ_OP(ZEND_POST_INC_OBJ, "__post_inc")
PHP_OPERATOR_UNARY_ASSIGN_OBJ_OP(ZEND_POST_DEC_OBJ, "__post_dec")
/* ***********************
* Module Housekeeping *
*********************** */
PHP_MINIT_FUNCTION(operator)
{
memcpy(php_operator_opcode_handlers, zend_opcode_handlers, sizeof(php_operator_opcode_handlers));
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0
php_operator_original_opcode_handlers = zend_opcode_handlers;
zend_opcode_handlers = php_operator_opcode_handlers;
#else
php_operator_original_opcode_handlers = php_operator_opcode_handlers;
#endif
/* Binaries */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ADD);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_SUB);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_MUL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_DIV);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_MOD);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_SL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_SR);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_CONCAT);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_OR);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_AND);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_XOR);
/* Unaries */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BW_NOT);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BOOL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_BOOL_NOT);
/* Binary Assign */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_ADD);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_SUB);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_MUL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_DIV);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_MOD);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_SL);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_SR);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_CONCAT);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_BW_OR);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_BW_AND);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_ASSIGN_BW_XOR);
/* Unary Assign */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_PRE_INC);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_PRE_DEC);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_POST_INC);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_POST_DEC);
/* Unary Assign Obj */
PHP_OPERATOR_REPLACE_OPCODE(ZEND_PRE_INC_OBJ);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_PRE_DEC_OBJ);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_POST_INC_OBJ);
PHP_OPERATOR_REPLACE_OPCODE(ZEND_POST_DEC_OBJ);
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(operator)
{
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION > 0
zend_opcode_handlers = php_operator_original_opcode_handlers;
#else
memcpy(zend_opcode_handlers, php_operator_original_opcode_handlers, sizeof(php_operator_opcode_handlers));
#endif
return SUCCESS;
}
PHP_MINFO_FUNCTION(operator)
{
php_info_print_table_start();
php_info_print_table_header(2, "operator overloading support", "+ - * / % << >> . | & ^ ~ ! ++ -- "
"+= -= *= /= %= <<= >>= .= |= &= ^= ~=");
php_info_print_table_end();
}
zend_module_entry operator_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_OPERATOR_EXTNAME,
NULL,
PHP_MINIT(operator),
PHP_MSHUTDOWN(operator),
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
PHP_MINFO(operator),
#if ZEND_MODULE_API_NO >= 20010901
PHP_OPERATOR_EXTVER,
#endif
STANDARD_MODULE_PROPERTIES
/* {{{ operator_module_entry
*/
static zend_module_entry operator_module_entry = {
STANDARD_MODULE_HEADER,
"operator",
NULL, /* functions */
PHP_MINIT(operator),
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
"7.2.0",
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_OPERATOR
ZEND_GET_MODULE(operator)
#endif

View File

@@ -1,55 +1,119 @@
<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>
<license>PHP</license>
<maintainers>
<maintainer>
<user>pollita</user>
<name>Sara Golemon</name>
<email>pollita@php.net</email>
<role>lead</role>
</maintainer>
</maintainers>
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>operator</name>
<channel>pecl.php.net</channel>
<summary>Operator overloading for Objects</summary>
<description>Operator overloading for: +, -, *, /, %, **, &lt;&lt;, &gt;&gt;, ., |, &amp;, ^, ~, !, ++, --,
+=, -=, *=, /=, %=, **=, &lt;&lt;=, &gt;&gt;=, .=, |=, &amp;=, ^=, ~=,
==, !=, ===, !==, &lt;, &lt;=, and &lt;=&gt; operators.
<release>
<version>0.2</version>
<state>beta</state>
<date>2006-01-25</date>
<notes>* Added support for pre/post inc/dec operators
</description>
<lead>
<name>Sara Golemon</name>
<user>pollita</user>
<email>pollita@php.net</email>
<active>yes</active>
</lead>
<date>2017-03-08</date>
<time>20:54:00</time>
<version>
<release>1.0</release>
<api>1.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
<notes>
* Rewrote for PHP7, dropped PHP5 support
* Removed pre/post inc/dec support for objects in object properties (this will come back eventually)
* Added pow, assign-pow, and spaceship operators
</notes>
<contents>
<dir name="/">
<dir name="tests">
<file name="binary.phpt" role="test" />
<file name="binary_assign.phpt" role="test" />
<file name="bug56904.phpt" role="test" />
<file name="compare.phpt" role="test" />
<file name="incdec.phpt" role="test" />
<file name="unary.phpt" role="test" />
</dir> <!-- //tests -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
<file name="CREDITS" role="doc" />
<file name="EXPERIMENTAL" role="doc" />
<file name="operator.c" role="src" />
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>4.0.0</min>
</php>
<pearinstaller>
<min>1.4.0b1</min>
</pearinstaller>
</required>
</dependencies>
<providesextension>operator</providesextension>
<extsrcrelease />
<changelog>
<release>
<date>2009-11-05</date>
<time>17:54:16</time>
<version>
<release>0.3</release>
<api>0.3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
<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>
<release>
<version>
<release>0.2</release>
<api>0.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-01-25</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
* Added support for pre/post inc/dec operators
* Added support for assignment operators
* Refactored opline->result handling
* Refactored opcode handlers</notes>
</release>
<changelog>
<release>
<version>0.1</version>
<state>beta</state>
<date>2006-01-12</date>
<notes>Initial Release</notes>
</release>
</changelog>
<filelist>
<file role="doc" name="CREDITS"/>
<file role="doc" name="EXPERIMENTAL"/>
<file role="src" name="config.m4"/>
<file role="src" name="config.w32"/>
<file role="src" name="operator.c"/>
<file role="src" name="php_operator.h"/>
<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"/>
</dir>
</filelist>
* Refactored opline-&gt;result handling
* Refactored opcode handlers
</notes>
</release>
<release>
<version>
<release>0.1</release>
<api>0.1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-01-12</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
Initial Release
</notes>
</release>
</changelog>
</package>
<!--
vim: et ts=1 sw=1
-->

13
php7-is_greater.diff Normal file
View File

@@ -0,0 +1,13 @@
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 88d7192..b797939 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6716,7 +6716,7 @@ void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
zend_emit_op_tmp(result,
ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
- &right_node, &left_node);
+ &right_node, &left_node)->extended_value = 1;
}
/* }}} */

View File

@@ -1,45 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sara Golemon <pollita@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef PHP_OPERATOR_H
#define PHP_OPERATOR_H
#define PHP_OPERATOR_EXTNAME "operator"
#define PHP_OPERATOR_EXTVER "0.2"
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 0
typedef struct {
zval *var;
} zend_free_op;
#endif
extern zend_module_entry operator_module_entry;
#define phpext_operator_ptr &operator_module_entry
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

View File

@@ -7,6 +7,10 @@ Basic binary assign ops
class foo {
private $value;
function __assign($val) {
return $this->value = $val;
}
function __assign_add($val) {
return $this->value += $val;
}
@@ -56,6 +60,11 @@ class foo {
}
}
$a = new foo(1);
var_dump($a = 2);
var_dump($a += 2);
var_dump(is_object($a));
$c = new foo(4);
var_dump($c += 3);
@@ -77,6 +86,9 @@ var_dump($f |= 0xAA);
var_dump($f &= 0xAA);
var_dump($f ^= 0xAA);
--EXPECT--
int(2)
int(4)
bool(true)
int(7)
int(4)
int(12)

View File

@@ -1,43 +0,0 @@
--TEST--
binary assign obj/dim ops
--SKIPIF--
<?php if(!extension_loaded("operator")) print "skip"; ?>
--FILE--
<?php
class foo {
private $value;
function __assign_add($val) {
return $this->value += $val;
}
function __construct($init) {
$this->value = $init;
}
}
class bar implements arrayaccess {
public $baz;
function offsetget($ofs) {
return $this->{$ofs};
}
function offsetset($ofs,$val) { echo "argh"; }
function offsetunset($ofs) { echo "oof"; }
function offsetexists($ofs) { echo "ick"; return true; }
}
$a = new foo(4);
$b = new bar;
$b->baz = $a;
var_dump($b->baz += 10);
var_dump($b->baz += 5);
var_dump($b['baz'] += 10);
var_dump($b['baz'] += 5);
--EXPECT--
int(14)
int(19)
int(29)
int(34)

33
tests/bug56904.phpt Normal file
View File

@@ -0,0 +1,33 @@
--TEST--
Bug#56904 Mixing direct calls and implicit overloads
--FILE--
<?php
class a {
public $v = 'initial';
public function __assign_sl($val) {
$this->v = $val;
}
}
$bob = new a;
var_dump($bob);
$bob->__assign_sl('abc');
var_dump($bob);
$bob <<= 'def';
var_dump($bob);
?>
--EXPECTF--
object(a)#%d (1) {
["v"]=>
string(7) "initial"
}
object(a)#%d (1) {
["v"]=>
string(3) "abc"
}
object(a)#%d (1) {
["v"]=>
string(3) "def"
}

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)

28
tests/compare2.phpt Normal file
View File

@@ -0,0 +1,28 @@
--TEST--
Extended comparison ops
--SKIPIF--
<?php if(!extension_loaded("operator")) 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)

View File

@@ -1,65 +0,0 @@
--TEST--
Inc/Dec obj ops
--SKIPIF--
<?php if(!extension_loaded("operator")) print "skip"; ?>
--FILE--
<?php
class foo {
private $value;
function __post_inc() {
return $this->value++;
}
function __post_dec() {
return $this->value--;
}
function __pre_inc() {
$this->value++;
return $this->value;
}
function __pre_dec() {
$this->value--;
return $this->value;
}
function __construct($init) {
$this->value = $init;
}
}
class bar {
public $baz;
}
$c = new foo(7);
$d = new bar;
$d->baz = $c;
for($i = 0; $i < 3; $i++) {
var_dump($d->baz++);
}
for($i = 0; $i < 3; $i++) {
var_dump($d->baz--);
}
for($i = 0; $i < 3; $i++) {
var_dump(++$d->baz);
}
for($i = 0; $i < 3; $i++) {
var_dump(--$d->baz);
}
--EXPECT--
int(7)
int(8)
int(9)
int(10)
int(9)
int(8)
int(8)
int(9)
int(10)
int(9)
int(8)
int(7)