mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
@- Adding 'is' operator that can be used to check the type of a variable,
@ or its class. (Andrei)
This commit is contained in:
parent
84ae5adf29
commit
82c72f2799
@ -2724,6 +2724,28 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void zend_do_is_type(znode *result, znode *expr, znode *class, int type TSRMLS_DC)
|
||||||
|
{
|
||||||
|
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||||
|
|
||||||
|
opline->opcode = ZEND_IS_TYPE;
|
||||||
|
opline->result.op_type = IS_TMP_VAR;
|
||||||
|
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||||
|
opline->op1 = *expr;
|
||||||
|
|
||||||
|
if (class) {
|
||||||
|
opline->op2 = *class;
|
||||||
|
opline->extended_value = 1;
|
||||||
|
} else {
|
||||||
|
opline->op2.u.constant.value.lval = type;
|
||||||
|
SET_UNUSED(opline->op2);
|
||||||
|
opline->extended_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = opline->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC)
|
void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zend_op *opline;
|
zend_op *opline;
|
||||||
|
@ -358,6 +358,8 @@ void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC);
|
|||||||
void zend_do_unset(znode *variable TSRMLS_DC);
|
void zend_do_unset(znode *variable TSRMLS_DC);
|
||||||
void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC);
|
void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC);
|
||||||
|
|
||||||
|
void zend_do_is_type(znode *result, znode *expr, znode *class, int type TSRMLS_DC);
|
||||||
|
|
||||||
void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC);
|
void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC);
|
||||||
void zend_do_foreach_cont(znode *value, znode *key, znode *as_token TSRMLS_DC);
|
void zend_do_foreach_cont(znode *value, znode *key, znode *as_token TSRMLS_DC);
|
||||||
void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC);
|
void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC);
|
||||||
@ -595,6 +597,9 @@ int zendlex(znode *zendlval TSRMLS_DC);
|
|||||||
|
|
||||||
#define ZEND_ASSIGN_OBJ 136
|
#define ZEND_ASSIGN_OBJ 136
|
||||||
#define ZEND_MAKE_VAR 137
|
#define ZEND_MAKE_VAR 137
|
||||||
|
|
||||||
|
#define ZEND_IS_TYPE 138
|
||||||
|
|
||||||
/* end of block */
|
/* end of block */
|
||||||
|
|
||||||
|
|
||||||
|
@ -3115,6 +3115,19 @@ send_by_ref:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
NEXT_OPCODE();
|
NEXT_OPCODE();
|
||||||
|
case ZEND_IS_TYPE: {
|
||||||
|
zval *expr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
|
||||||
|
if (EX(opline)->extended_value) {
|
||||||
|
is_type_function(&EX(Ts)[EX(opline)->result.u.var].tmp_var, expr,
|
||||||
|
EX(Ts)[EX(opline)->op2.u.var].EA.class_entry, 0 TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
is_type_function(&EX(Ts)[EX(opline)->result.u.var].tmp_var, expr,
|
||||||
|
NULL, EX(opline)->op2.u.constant.value.lval TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
|
||||||
|
}
|
||||||
|
NEXT_OPCODE();
|
||||||
case ZEND_EXT_NOP:
|
case ZEND_EXT_NOP:
|
||||||
case ZEND_NOP:
|
case ZEND_NOP:
|
||||||
NEXT_OPCODE();
|
NEXT_OPCODE();
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
%right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
|
%right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
|
||||||
%right '['
|
%right '['
|
||||||
%nonassoc T_NEW
|
%nonassoc T_NEW T_IS_TYPE
|
||||||
%token T_EXIT
|
%token T_EXIT
|
||||||
%token T_IF
|
%token T_IF
|
||||||
%left T_ELSEIF
|
%left T_ELSEIF
|
||||||
@ -94,6 +94,7 @@
|
|||||||
%token T_ENDFOREACH
|
%token T_ENDFOREACH
|
||||||
%token T_DECLARE
|
%token T_DECLARE
|
||||||
%token T_ENDDECLARE
|
%token T_ENDDECLARE
|
||||||
|
%token T_IS_TYPE
|
||||||
%token T_AS
|
%token T_AS
|
||||||
%token T_SWITCH
|
%token T_SWITCH
|
||||||
%token T_ENDSWITCH
|
%token T_ENDSWITCH
|
||||||
@ -528,6 +529,14 @@ expr_without_variable:
|
|||||||
| expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$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 '>' 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 T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE is_type_expr { zend_do_is_type(&$$, &$1, &$3, 0 TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_INT_CAST { zend_do_is_type(&$$, &$1, NULL, IS_LONG TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_DOUBLE_CAST { zend_do_is_type(&$$, &$1, NULL, IS_DOUBLE TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_STRING_CAST { zend_do_is_type(&$$, &$1, NULL, IS_STRING TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_ARRAY_CAST { zend_do_is_type(&$$, &$1, NULL, IS_ARRAY TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_OBJECT_CAST { zend_do_is_type(&$$, &$1, NULL, IS_OBJECT TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_BOOL_CAST { zend_do_is_type(&$$, &$1, NULL, IS_BOOL TSRMLS_CC); }
|
||||||
|
| expr T_IS_TYPE T_UNSET_CAST { zend_do_is_type(&$$, &$1, NULL, IS_NULL TSRMLS_CC); }
|
||||||
| '(' expr ')' { $$ = $2; }
|
| '(' expr ')' { $$ = $2; }
|
||||||
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
|
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
|
||||||
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
|
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
|
||||||
@ -585,6 +594,10 @@ static_or_variable_string:
|
|||||||
| r_variable_without_static_member { $$ = $1; }
|
| r_variable_without_static_member { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
is_type_expr:
|
||||||
|
parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
|
||||||
|
| T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
|
||||||
|
;
|
||||||
|
|
||||||
exit_expr:
|
exit_expr:
|
||||||
/* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
|
/* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
|
||||||
|
@ -555,6 +555,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
|||||||
return T_ENDDECLARE;
|
return T_ENDDECLARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<ST_IN_SCRIPTING>"is" {
|
||||||
|
return T_IS_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
<ST_IN_SCRIPTING>"as" {
|
<ST_IN_SCRIPTING>"as" {
|
||||||
return T_AS;
|
return T_AS;
|
||||||
}
|
}
|
||||||
|
@ -1365,6 +1365,60 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSR
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ZEND_API int is_type_function(zval *result, zval *op1, zend_class_entry *class, int type TSRMLS_DC)
|
||||||
|
{
|
||||||
|
if (class) {
|
||||||
|
if (Z_TYPE_P(op1) == IS_OBJECT) {
|
||||||
|
zend_class_entry *ce;
|
||||||
|
for (ce = Z_OBJCE_P(op1); ce != NULL; ce = ce->parent) {
|
||||||
|
if (ce == class) {
|
||||||
|
ZVAL_BOOL(result, 1);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZVAL_BOOL(result, 0);
|
||||||
|
} else {
|
||||||
|
ZVAL_BOOL(result, 0);
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case IS_NULL:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_LONG:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_LONG);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_DOUBLE:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_DOUBLE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_STRING:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_STRING);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_ARRAY:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_ARRAY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_OBJECT:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_OBJECT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_BOOL:
|
||||||
|
ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_BOOL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
zend_error(E_ERROR, "Unknown operand type");
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#define LOWER_CASE 1
|
#define LOWER_CASE 1
|
||||||
#define UPPER_CASE 2
|
#define UPPER_CASE 2
|
||||||
#define NUMERIC 3
|
#define NUMERIC 3
|
||||||
|
@ -58,6 +58,8 @@ ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
|||||||
ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||||
ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||||
|
|
||||||
|
ZEND_API int is_type_function(zval *result, zval *op1, zend_class_entry *ce, int type TSRMLS_DC);
|
||||||
|
|
||||||
static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
|
static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
|
||||||
{
|
{
|
||||||
long local_lval;
|
long local_lval;
|
||||||
|
Loading…
Reference in New Issue
Block a user