root/Zend/zend_ast.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_ast_create_constant
  2. zend_ast_create_unary
  3. zend_ast_create_binary
  4. zend_ast_create_ternary
  5. zend_ast_create_dynamic
  6. zend_ast_dynamic_add
  7. zend_ast_dynamic_shrink
  8. zend_ast_is_ct_constant
  9. zend_ast_evaluate
  10. zend_ast_copy
  11. zend_ast_destroy

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 2.00 of the Zend license,     |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.zend.com/license/2_00.txt.                                |
  11    | If you did not receive a copy of the Zend license and are unable to  |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@zend.com so we can mail you a copy immediately.              |
  14    +----------------------------------------------------------------------+
  15    | Authors: Bob Weinand <bwoebi@php.net>                                |
  16    |          Dmitry Stogov <dmitry@zend.com>                             |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #include "zend_ast.h"
  23 #include "zend_API.h"
  24 #include "zend_operators.h"
  25 
  26 ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
  27 {
  28         zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval));
  29         ast->kind = ZEND_CONST;
  30         ast->children = 0;
  31         ast->u.val = (zval*)(ast + 1);
  32         INIT_PZVAL_COPY(ast->u.val, zv);
  33         return ast;
  34 }
  35 
  36 ZEND_API zend_ast* zend_ast_create_unary(uint kind, zend_ast *op0)
  37 {
  38         zend_ast *ast = emalloc(sizeof(zend_ast));
  39         ast->kind = kind;
  40         ast->children = 1;
  41         (&ast->u.child)[0] = op0;
  42         return ast;
  43 }
  44 
  45 ZEND_API zend_ast* zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1)
  46 {
  47         zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
  48         ast->kind = kind;
  49         ast->children = 2;
  50         (&ast->u.child)[0] = op0;
  51         (&ast->u.child)[1] = op1;
  52         return ast;
  53 }
  54 
  55 ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
  56 {
  57         zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
  58         ast->kind = kind;
  59         ast->children = 3;
  60         (&ast->u.child)[0] = op0;
  61         (&ast->u.child)[1] = op1;
  62         (&ast->u.child)[2] = op2;
  63         return ast;
  64 }
  65 
  66 ZEND_API zend_ast* zend_ast_create_dynamic(uint kind)
  67 {
  68         zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */
  69         ast->kind = kind;
  70         ast->children = 0;
  71         return ast;
  72 }
  73 
  74 ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op)
  75 {
  76         if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) {
  77                 *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1));
  78         }
  79         (&(*ast)->u.child)[(*ast)->children++] = op;
  80 }
  81 
  82 ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast)
  83 {
  84         *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1));
  85 }
  86 
  87 ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
  88 {
  89         int i;
  90 
  91         if (ast->kind == ZEND_CONST) {
  92                 return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
  93         } else {
  94                 for (i = 0; i < ast->children; i++) {
  95                         if ((&ast->u.child)[i]) {
  96                                 if (!zend_ast_is_ct_constant((&ast->u.child)[i])) {
  97                                         return 0;
  98                                 }
  99                         }
 100                 }
 101                 return 1;
 102         }
 103 }
 104 
 105 ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC)
 106 {
 107         zval op1, op2;
 108 
 109         switch (ast->kind) {
 110                 case ZEND_ADD:
 111                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 112                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 113                         add_function(result, &op1, &op2 TSRMLS_CC);
 114                         zval_dtor(&op1);
 115                         zval_dtor(&op2);
 116                         break;
 117                 case ZEND_SUB:
 118                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 119                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 120                         sub_function(result, &op1, &op2 TSRMLS_CC);
 121                         zval_dtor(&op1);
 122                         zval_dtor(&op2);
 123                         break;
 124                 case ZEND_MUL:
 125                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 126                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 127                         mul_function(result, &op1, &op2 TSRMLS_CC);
 128                         zval_dtor(&op1);
 129                         zval_dtor(&op2);
 130                         break;
 131                 case ZEND_POW:
 132                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 133                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 134                         pow_function(result, &op1, &op2 TSRMLS_CC);
 135                         zval_dtor(&op1);
 136                         zval_dtor(&op2);
 137                         break;
 138                 case ZEND_DIV:
 139                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 140                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 141                         div_function(result, &op1, &op2 TSRMLS_CC);
 142                         zval_dtor(&op1);
 143                         zval_dtor(&op2);
 144                         break;
 145                 case ZEND_MOD:
 146                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 147                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 148                         mod_function(result, &op1, &op2 TSRMLS_CC);
 149                         zval_dtor(&op1);
 150                         zval_dtor(&op2);
 151                         break;
 152                 case ZEND_SL:
 153                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 154                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 155                         shift_left_function(result, &op1, &op2 TSRMLS_CC);
 156                         zval_dtor(&op1);
 157                         zval_dtor(&op2);
 158                         break;
 159                 case ZEND_SR:
 160                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 161                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 162                         shift_right_function(result, &op1, &op2 TSRMLS_CC);
 163                         zval_dtor(&op1);
 164                         zval_dtor(&op2);
 165                         break;
 166                 case ZEND_CONCAT:
 167                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 168                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 169                         concat_function(result, &op1, &op2 TSRMLS_CC);
 170                         zval_dtor(&op1);
 171                         zval_dtor(&op2);
 172                         break;
 173                 case ZEND_BW_OR:
 174                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 175                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 176                         bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
 177                         zval_dtor(&op1);
 178                         zval_dtor(&op2);
 179                         break;
 180                 case ZEND_BW_AND:
 181                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 182                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 183                         bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
 184                         zval_dtor(&op1);
 185                         zval_dtor(&op2);
 186                         break;
 187                 case ZEND_BW_XOR:
 188                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 189                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 190                         bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
 191                         zval_dtor(&op1);
 192                         zval_dtor(&op2);
 193                         break;
 194                 case ZEND_BW_NOT:
 195                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 196                         bitwise_not_function(result, &op1 TSRMLS_CC);
 197                         zval_dtor(&op1);
 198                         break;
 199                 case ZEND_BOOL_NOT:
 200                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 201                         boolean_not_function(result, &op1 TSRMLS_CC);
 202                         zval_dtor(&op1);
 203                         break;
 204                 case ZEND_BOOL_XOR:
 205                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 206                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 207                         boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
 208                         zval_dtor(&op1);
 209                         zval_dtor(&op2);
 210                         break;
 211                 case ZEND_IS_IDENTICAL:
 212                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 213                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 214                         is_identical_function(result, &op1, &op2 TSRMLS_CC);
 215                         zval_dtor(&op1);
 216                         zval_dtor(&op2);
 217                         break;
 218                 case ZEND_IS_NOT_IDENTICAL:
 219                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 220                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 221                         is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
 222                         zval_dtor(&op1);
 223                         zval_dtor(&op2);
 224                         break;
 225                 case ZEND_IS_EQUAL:
 226                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 227                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 228                         is_equal_function(result, &op1, &op2 TSRMLS_CC);
 229                         zval_dtor(&op1);
 230                         zval_dtor(&op2);
 231                         break;
 232                 case ZEND_IS_NOT_EQUAL:
 233                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 234                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 235                         is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
 236                         zval_dtor(&op1);
 237                         zval_dtor(&op2);
 238                         break;
 239                 case ZEND_IS_SMALLER:
 240                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 241                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 242                         is_smaller_function(result, &op1, &op2 TSRMLS_CC);
 243                         zval_dtor(&op1);
 244                         zval_dtor(&op2);
 245                         break;
 246                 case ZEND_IS_SMALLER_OR_EQUAL:
 247                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 248                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 249                         is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
 250                         zval_dtor(&op1);
 251                         zval_dtor(&op2);
 252                         break;
 253                 case ZEND_CONST:
 254                         /* class constants may be updated in-place */
 255                         if (scope) {
 256                                 if (IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val))) {
 257                                         zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC);
 258                                 }
 259                                 *result = *ast->u.val;
 260                                 zval_copy_ctor(result);
 261                         } else {
 262                                 *result = *ast->u.val;
 263                                 zval_copy_ctor(result);
 264                                 if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
 265                                         zval_update_constant_ex(&result, 1, scope TSRMLS_CC);
 266                                 }
 267                         }
 268                         break;
 269                 case ZEND_BOOL_AND:
 270                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 271                         if (zend_is_true(&op1)) {
 272                                 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 273                                 ZVAL_BOOL(result, zend_is_true(&op2));
 274                                 zval_dtor(&op2);
 275                         } else {
 276                                 ZVAL_BOOL(result, 0);
 277                         }
 278                         zval_dtor(&op1);
 279                         break;
 280                 case ZEND_BOOL_OR:
 281                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 282                         if (zend_is_true(&op1)) {
 283                                 ZVAL_BOOL(result, 1);
 284                         } else {
 285                                 zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 286                                 ZVAL_BOOL(result, zend_is_true(&op2));
 287                                 zval_dtor(&op2);
 288                         }
 289                         zval_dtor(&op1);
 290                         break;
 291                 case ZEND_SELECT:
 292                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 293                         if (zend_is_true(&op1)) {
 294                                 if (!(&ast->u.child)[1]) {
 295                                         *result = op1;
 296                                 } else {
 297                                         zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC);
 298                                         zval_dtor(&op1);
 299                                 }
 300                         } else {
 301                                 zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC);
 302                                 zval_dtor(&op1);
 303                         }
 304                         break;
 305                 case ZEND_UNARY_PLUS:
 306                         ZVAL_LONG(&op1, 0);
 307                         zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
 308                         add_function(result, &op1, &op2 TSRMLS_CC);
 309                         zval_dtor(&op2);
 310                         break;
 311                 case ZEND_UNARY_MINUS:
 312                         ZVAL_LONG(&op1, 0);
 313                         zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
 314                         sub_function(result, &op1, &op2 TSRMLS_CC);
 315                         zval_dtor(&op2);
 316                         break;
 317                 case ZEND_INIT_ARRAY:
 318                         INIT_PZVAL(result);
 319                         array_init(result);
 320                         {
 321                                 int i;
 322                                 zend_bool has_key;
 323                                 for (i = 0; i < ast->children; i+=2) {
 324                                         zval *expr;
 325                                         MAKE_STD_ZVAL(expr);
 326                                         if ((has_key = !!(&ast->u.child)[i])) {
 327                                                 zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC);
 328                                         }
 329                                         zend_ast_evaluate(expr, (&ast->u.child)[i+1], scope TSRMLS_CC);
 330                                         zend_do_add_static_array_element(result, has_key?&op1:NULL, expr);
 331                                 }
 332                         }
 333                         break;
 334                 case ZEND_FETCH_DIM_R:
 335                         zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
 336                         zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
 337                         {
 338                                 zval *tmp;
 339                                 zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
 340                                 ZVAL_ZVAL(result, tmp, 1, 1);
 341                         }
 342                         zval_dtor(&op1);
 343                         zval_dtor(&op2);
 344                         break;
 345                 default:
 346                         zend_error(E_ERROR, "Unsupported constant expression");
 347         }
 348 }
 349 
 350 ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
 351 {
 352         if (ast == NULL) {
 353                 return NULL;
 354         } else if (ast->kind == ZEND_CONST) {
 355                 zend_ast *copy = zend_ast_create_constant(ast->u.val);
 356                 zval_copy_ctor(copy->u.val);
 357                 return copy;
 358         } else if (ast->children) {
 359                 zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
 360                 int i;
 361                 new->kind = ast->kind;
 362                 new->children = ast->children;
 363                 for (i = 0; i < ast->children; i++) {
 364                         (&new->u.child)[i] = zend_ast_copy((&ast->u.child)[i]);
 365                 }
 366                 return new;
 367         }
 368         return zend_ast_create_dynamic(ast->kind);
 369 }
 370 
 371 ZEND_API void zend_ast_destroy(zend_ast *ast)
 372 {
 373         int i;
 374 
 375         if (ast->kind == ZEND_CONST) {
 376                 zval_dtor(ast->u.val);
 377         } else {
 378                 for (i = 0; i < ast->children; i++) {
 379                         if ((&ast->u.child)[i]) {
 380                                 zend_ast_destroy((&ast->u.child)[i]);
 381                         }
 382                 }
 383         }
 384         efree(ast);
 385 }

/* [<][>][^][v][top][bottom][index][help] */