2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2005-2011 Froenchenko Leonid ( lfroen@gmail.com / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <string> // Do_not_auto_remove (g++-4.0.1)
29 #ifdef PHP_STANDALONE_EN
34 #include "WebServer.h"
38 #include "php_syntree.h"
39 #include "php_core_lib.h"
42 PHP_SYN_NODE
*g_syn_tree_top
= 0;
45 PHP_SCOPE_TABLE g_global_scope
= 0;
46 PHP_SCOPE_TABLE g_current_scope
= 0;
47 PHP_SCOPE_STACK g_scope_stack
= 0;
51 // Known named constant values
52 std::map
<std::string
, int> g_known_const
;
54 PHP_EXP_NODE
*make_zero_exp_node()
56 PHP_EXP_NODE
*node
= new PHP_EXP_NODE
;
57 memset(node
, 0, sizeof(PHP_EXP_NODE
));
61 PHP_EXP_NODE
*make_const_exp_dnum(int number
)
63 PHP_EXP_NODE
*node
= make_zero_exp_node();
64 node
->op
= PHP_OP_VAL
;
65 node
->val_node
.type
= PHP_VAL_INT
;
66 node
->val_node
.int_val
= number
;
71 PHP_EXP_NODE
*make_const_exp_fnum(float number
)
73 PHP_EXP_NODE
*node
= make_zero_exp_node();
74 node
->op
= PHP_OP_VAL
;
75 node
->val_node
.type
= PHP_VAL_FLOAT
;
76 node
->val_node
.float_val
= number
;
81 PHP_EXP_NODE
*make_const_exp_str(char *s
, int unescape
)
83 PHP_EXP_NODE
*node
= make_zero_exp_node();
84 node
->op
= PHP_OP_VAL
;
85 node
->val_node
.type
= PHP_VAL_STRING
;
88 node
->val_node
.str_val
= (char *)malloc(strlen(s
)+1);
89 // copy and unescape string
90 char *p
= node
->val_node
.str_val
;
94 case 'n' : *p
++ = '\n'; s
++; break;
95 case 't' : *p
++ = '\t'; s
++; break;
96 default : *p
++ = *s
++; break;
104 node
->val_node
.str_val
= strdup(s
);
110 PHP_EXP_NODE
*make_const_exp_int_obj(void *obj
)
112 PHP_EXP_NODE
*node
= make_zero_exp_node();
113 node
->op
= PHP_OP_VAL
;
114 node
->val_node
.type
= PHP_VAL_INT_DATA
;
115 node
->val_node
.ptr_val
= obj
;
120 PHP_EXP_NODE
*make_exp_1(PHP_EXP_OP op
, PHP_EXP_NODE
*operand
)
122 PHP_EXP_NODE
*node
= make_zero_exp_node();
124 node
->tree_node
.left
= operand
;
128 PHP_EXP_NODE
*make_exp_2(PHP_EXP_OP op
, PHP_EXP_NODE
*left
, PHP_EXP_NODE
*right
)
130 PHP_EXP_NODE
*node
= make_zero_exp_node();
132 node
->tree_node
.left
= left
;
133 node
->tree_node
.right
= right
;
137 PHP_EXP_NODE
*make_exp_2_self(PHP_EXP_OP op
, PHP_EXP_NODE
*self
, PHP_EXP_NODE
*right
)
139 PHP_EXP_NODE
*clone_self
= make_zero_exp_node();
141 return make_exp_2(op
, clone_self
, right
);
144 PHP_EXP_NODE
*make_known_const(char *name
)
147 if ( g_known_const
.count(name
) ) {
148 const_id
= g_known_const
[name
];
150 return make_const_exp_dnum(const_id
);
154 // Create function parameter (in declaration)
156 PHP_EXP_NODE
*make_func_param(PHP_EXP_NODE
*list
, PHP_EXP_NODE
*var_exp_node
, char *class_name
, int byref
)
158 PHP_FUNC_PARAM_DEF
*param
= new PHP_FUNC_PARAM_DEF
;
159 memset(param
, 0, sizeof(PHP_FUNC_PARAM_DEF
));
161 param
->si_var
= var_exp_node
->var_si_node
;
162 param
->si_var
->type
= PHP_SCOPE_PARAM
;
163 //printf("mark %p->%p as param\n", param->si_var, param->si_var->var);
165 param
->var
= param
->si_var
->var
;
168 param
->class_name
= class_name
? strdup(class_name
) : 0;
169 param
->byref
= byref
;
171 PHP_EXP_NODE
*curr_node
= make_const_exp_int_obj(param
);
174 PHP_EXP_NODE
*p
= list
;
186 * Syntax tree generation
188 PHP_SYN_NODE
*make_expr_syn_node(PHP_STATMENT_TYPE type
, PHP_EXP_NODE
*expr
)
190 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
191 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
193 syn_node
->type
= type
;
194 syn_node
->node_expr
= expr
;
199 PHP_SYN_NODE
*make_ifelse_syn_node(PHP_EXP_NODE
*expr
,
200 PHP_SYN_NODE
*then_node
, PHP_SYN_NODE
*elseif_list
, PHP_SYN_NODE
*else_node
)
202 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
203 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
205 syn_node
->type
= PHP_ST_IF
;
206 syn_node
->node_if
.cond
= expr
;
207 syn_node
->node_if
.code_if
= then_node
;
210 syn_node
->node_if
.code_else
= elseif_list
;
212 PHP_SYN_NODE
*curr_if
= elseif_list
;
213 while ( curr_if
->node_if
.code_else
) {
214 curr_if
= curr_if
->node_if
.code_else
;
216 curr_if
->node_if
.code_else
= else_node
;
218 syn_node
->node_if
.code_else
= else_node
;
223 PHP_SYN_NODE
*make_while_loop_syn_node(PHP_EXP_NODE
*cond
, PHP_SYN_NODE
*code
, int do_while
)
225 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
226 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
228 syn_node
->type
= do_while
? PHP_ST_WHILE
: PHP_ST_DO_WHILE
;
229 syn_node
->node_while
.cond
= cond
;
230 syn_node
->node_while
.code
= code
;
235 PHP_SYN_NODE
*make_for_syn_node(PHP_EXP_NODE
*start
, PHP_EXP_NODE
*cond
,
236 PHP_EXP_NODE
*next
, PHP_SYN_NODE
*code
)
238 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
239 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
241 syn_node
->type
= PHP_ST_FOR
;
242 syn_node
->node_for
.do_start
= start
;
243 syn_node
->node_for
.cond
= cond
;
244 syn_node
->node_for
.do_next
= next
;
245 syn_node
->node_for
.code
= code
;
250 PHP_SYN_NODE
*make_foreach_loop_syn_node(PHP_EXP_NODE
*elems
,
251 PHP_EXP_NODE
*i_key
, PHP_EXP_NODE
*i_val
, PHP_SYN_NODE
*code
, int byref
)
253 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
254 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
256 syn_node
->type
= PHP_ST_FOREACH
;
257 syn_node
->node_foreach
.elems
= elems
;
258 syn_node
->node_foreach
.code
= code
;
259 syn_node
->node_foreach
.i_key
= i_key
? i_key
->var_si_node
: 0;
260 syn_node
->node_foreach
.i_val
= i_val
->var_si_node
;
261 syn_node
->node_foreach
.byref
= byref
;
271 PHP_SYN_NODE
*make_func_decl_syn_node(const char *name
, PHP_EXP_NODE
*param_list
)
273 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
274 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
276 syn_node
->type
= PHP_ST_FUNC_DECL
;
278 syn_node
->func_decl
= new PHP_SYN_FUNC_DECL_NODE
;
279 memset(syn_node
->func_decl
, 0, sizeof(PHP_SYN_FUNC_DECL_NODE
));
280 syn_node
->func_decl
->name
= strdup(name
);
283 PHP_EXP_NODE
*curr_param
= param_list
;
284 // count parameters first
285 while ( curr_param
) {
286 syn_node
->func_decl
->param_count
++;
287 curr_param
= curr_param
->next
;
289 syn_node
->func_decl
->params
= new PHP_FUNC_PARAM_DEF
[syn_node
->func_decl
->param_count
];
290 curr_param
= param_list
;
291 for(int i
= 0; param_list
; param_list
= param_list
->next
, i
++) {
292 syn_node
->func_decl
->params
[i
] = *(PHP_FUNC_PARAM_DEF
*)param_list
->val_node
.ptr_val
;
293 // param has been copied to array, so it's no longer needed
294 delete (PHP_FUNC_PARAM_DEF
*)param_list
->val_node
.ptr_val
;
296 // dispose linked list as well
297 while ( curr_param
) {
298 PHP_EXP_NODE
*p
= curr_param
->next
;
307 PHP_SYN_NODE
*make_class_decl_syn_node()
309 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
310 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
312 syn_node
->type
= PHP_ST_CLASS_DECL
;
314 syn_node
->class_decl
= new PHP_SYN_CLASS_DECL_NODE
;
315 memset(syn_node
->class_decl
, 0, sizeof(PHP_SYN_CLASS_DECL_NODE
));
320 PHP_SYN_NODE
*make_switch_syn_node(PHP_EXP_NODE
*cond
, PHP_EXP_NODE
*case_list
)
322 PHP_SYN_NODE
*syn_node
= new PHP_SYN_NODE
;
323 memset(syn_node
, 0, sizeof(PHP_SYN_NODE
));
325 syn_node
->type
= PHP_ST_SWITCH
;
328 // Bind all statement lists into single one for
329 // simplier execution
331 PHP_SYN_NODE
*stat_list_tail
= 0;
332 for(PHP_EXP_NODE
*cur_case
= case_list
; cur_case
; cur_case
= cur_case
->next
) {
333 PHP_SYN_NODE
*cur_stat_list
= cur_case
->exp_node
->tree_node
.syn_right
;
334 if ( stat_list_tail
) {
335 while ( stat_list_tail
->next_node
) stat_list_tail
= stat_list_tail
->next_node
;
336 stat_list_tail
->next_node
= cur_stat_list
;
338 stat_list_tail
= cur_stat_list
;
342 syn_node
->node_switch
.cond
= cond
;
343 syn_node
->node_switch
.case_list
= case_list
;
348 PHP_VAR_NODE
*make_var_node()
350 PHP_VAR_NODE
*node
= new PHP_VAR_NODE
;
351 memset(node
, 0, sizeof(PHP_VAR_NODE
));
352 node
->value
.type
= PHP_VAL_NONE
;
357 PHP_VAR_NODE
*make_array_var()
359 PHP_VAR_NODE
*node
= make_var_node();
360 cast_value_array(&node
->value
);
366 * Called from lexer when ${IDENT} is recognized
368 PHP_EXP_NODE
*get_var_node(const char *name
)
370 PHP_EXP_NODE
*node
= make_zero_exp_node();
371 node
->op
= PHP_OP_VAR
;
373 PHP_SCOPE_ITEM
*si
= get_scope_item(g_current_scope
, name
);
375 if ( (si
->type
== PHP_SCOPE_VAR
) || (si
->type
== PHP_SCOPE_PARAM
) ) {
376 node
->var_si_node
= si
;
379 // Error: symbol already defined as different entity
381 php_report_error(PHP_ERROR
,
382 "symbol [%s] already defined as different entity (%d)", name
, si
->type
);
385 add_var_2_scope(g_current_scope
, make_var_node(), name
);
386 node
->var_si_node
= get_scope_item(g_current_scope
, name
);
392 void free_var_node(PHP_VAR_NODE
*v
)
398 * Init function scope table before transferring control there.
399 * 1. Evaluate all by-value params
400 * 2. Lvalue-evaluate all by-ref params and adjust pointers
402 void func_scope_init(PHP_FUNC_PARAM_DEF
*params
, int param_count
,
403 PHP_SCOPE_TABLE_TYPE
* /*scope_map*/, PHP_VALUE_NODE
*arg_array
,
404 std::map
<std::string
, PHP_VAR_NODE
*> &saved_vars
)
407 // Step 1: save origival vars
408 PHP_SCOPE_TABLE_TYPE
*curr_scope_map
= (PHP_SCOPE_TABLE_TYPE
*)g_current_scope
;
409 for(PHP_SCOPE_TABLE_TYPE::iterator i
= curr_scope_map
->begin(); i
!= curr_scope_map
->end();++i
) {
410 if ( (i
->second
->type
== PHP_SCOPE_VAR
) || (i
->second
->type
== PHP_SCOPE_PARAM
) ) {
411 if ( !(i
->second
->var
->flags
& PHP_VARFLAG_STATIC
) ) {
412 //printf("Saving %s = %p->%p\n", i->first.c_str(), i->second, i->second->var);
413 saved_vars
[i
->first
] = i
->second
->var
;
418 // Step 2: calculate new values of call parameters
419 PHP_VAR_NODE
*call_params
[PHP_MAX_FUNC_PARAM
];
420 for(int i
= 0; i
< param_count
; i
++) {
421 PHP_VAR_NODE
*curr_arg_val
= array_get_by_int_key(arg_array
, i
);
422 if ( curr_arg_val
->value
.type
!= PHP_VAL_NONE
) {
423 if ( (curr_arg_val
->flags
& PHP_VARFLAG_BYREF
) || params
[i
].byref
) {
424 call_params
[i
] = php_expr_eval_lvalue((PHP_EXP_NODE
*)curr_arg_val
->value
.ptr_val
);
425 if ( !call_params
[i
] ) {
426 php_report_error(PHP_ERROR
, "Byref parameter is not lvalue");
430 call_params
[i
] = make_var_node();
431 call_params
[i
]->ref_count
= 1;
432 //printf("alloc var for callparam %d -> %p\n", i, call_params[i]);
433 php_expr_eval((PHP_EXP_NODE
*)curr_arg_val
->value
.ptr_val
, &call_params
[i
]->value
);
437 php_report_error(PHP_WARNING
, "Default parameters are not implemented yet");
438 call_params
[i
] = make_var_node();
439 call_params
[i
]->ref_count
= 1;
443 // Step 3: assign new values to call parameters
444 for(int i
= 0; i
< param_count
; i
++) {
445 //printf("assign new param si=%p var=%p -> %p\n", params[i].si_var, params[i].si_var->var, call_params[i]);
446 params
[i
].si_var
->var
= call_params
[i
];
450 // Step 4: allocate new stack local vars
451 for(PHP_SCOPE_TABLE_TYPE::iterator i
= curr_scope_map
->begin(); i
!= curr_scope_map
->end();++i
) {
452 if ( !((i
->second
->type
== PHP_SCOPE_PARAM
) || (i
->second
->type
== PHP_SCOPE_VAR
)) ) {
455 //printf("in scope: %p %s [ %s ] with flags %02x\n", i->second, i->second->type == PHP_SCOPE_PARAM ? "param" : "var",
456 // i->first.c_str(), i->second->var->flags);
457 if ( !(i
->second
->var
->flags
& PHP_VARFLAG_STATIC
) && (i
->second
->type
!= PHP_SCOPE_PARAM
) ) {
458 //printf("alloc new for %s [ %p->%p ]\n", i->first.c_str(), i->second, i->second->var);
459 i
->second
->var
= make_var_node();
460 i
->second
->var
->ref_count
= 1;
466 * Since by-ref params changes pointers in scope table, we need to restore them
467 * to original objects, so:
468 * 1. Memory will not leak
469 * 2. Next call may be using same params by-value, so it need independent varnode
471 void func_scope_copy_back(PHP_FUNC_PARAM_DEF
*params
, int param_count
,
472 PHP_SCOPE_TABLE_TYPE
* /*scope_map*/, PHP_VALUE_NODE
*arg_array
,
473 std::map
<std::string
, PHP_VAR_NODE
*> &saved_vars
)
476 if ( param_count < array_get_size(arg_array) ) {
477 param_count = array_get_size(arg_array);
480 PHP_VAR_NODE
*call_params
[PHP_MAX_FUNC_PARAM
];
481 int call_param_2free_count
= 0;
482 for(int i
= 0; i
< param_count
; i
++) {
483 PHP_VAR_NODE
*curr_arg_val
= array_get_by_int_key(arg_array
, i
);
484 if ( !((curr_arg_val
->flags
& PHP_VARFLAG_BYREF
) || params
[i
].byref
) ) {
485 //printf("Delete param %d %p->%p\n", i, params[i].si_var, params[i].si_var->var);
486 call_params
[call_param_2free_count
++] = params
[i
].si_var
->var
;
488 params
[i
].si_var
->var
= params
[i
].var
;
491 PHP_SCOPE_TABLE_TYPE
*curr_scope_map
= (PHP_SCOPE_TABLE_TYPE
*)g_current_scope
;
492 for(PHP_SCOPE_TABLE_TYPE::iterator i
= curr_scope_map
->begin(); i
!= curr_scope_map
->end();++i
) {
493 if ( (i
->second
->type
== PHP_SCOPE_VAR
) || (i
->second
->type
== PHP_SCOPE_PARAM
) ) {
494 if ( !(i
->second
->var
->flags
& PHP_VARFLAG_STATIC
) ) {
495 //printf("Restoring %s = %p->%p\n", i->first.c_str(), i->second, i->second->var);
496 //assert(saved_vars[i->first]);
497 if (i
->second
->type
== PHP_SCOPE_VAR
) {
498 value_value_free(&i
->second
->var
->value
);
499 delete i
->second
->var
;
501 i
->second
->var
= saved_vars
[i
->first
];
505 for(int i
= 0; i
< call_param_2free_count
; i
++) {
506 value_value_free(&call_params
[i
]->value
);
507 delete call_params
[i
];
511 PHP_SCOPE_TABLE
make_scope_table()
513 PHP_SCOPE_TABLE_TYPE
*scope_map
= new PHP_SCOPE_TABLE_TYPE
;
518 void switch_push_scope_table(PHP_SCOPE_TABLE new_table
)
520 PHP_SCOPE_STACK_TYPE
*scope_stack
= (PHP_SCOPE_STACK_TYPE
*)g_scope_stack
;
521 scope_stack
->push_back((PHP_SCOPE_TABLE_TYPE
*)g_current_scope
);
522 g_current_scope
= new_table
;
525 void switch_pop_scope_table(int old_free
)
527 PHP_SCOPE_STACK_TYPE
*scope_stack
= (PHP_SCOPE_STACK_TYPE
*)g_scope_stack
;
529 delete_scope_table(g_current_scope
);
531 if ( scope_stack
->size() == 0 ) {
532 php_report_error(PHP_INTERNAL_ERROR
, "Stack underrun - no valid scope");
534 g_current_scope
= scope_stack
->back();
535 scope_stack
->pop_back();
538 void delete_scope_table(PHP_SCOPE_TABLE scope
)
540 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
542 for(PHP_SCOPE_TABLE_TYPE::iterator i
= scope_map
->begin(); i
!= scope_map
->end();++i
) {
543 switch ( i
->second
->type
) {
544 case PHP_SCOPE_PARAM
:
546 case PHP_SCOPE_VAR
: {
547 //printf("removing %s\n", i->first.c_str());
548 PHP_VAR_NODE
*var
= i
->second
->var
;
552 case PHP_SCOPE_FUNC
: {
553 PHP_SYN_NODE
*func
= i
->second
->func
;
554 php_syn_tree_free(func
);
557 case PHP_SCOPE_CLASS
: {
558 PHP_SYN_NODE
*class_decl
= i
->second
->class_decl
;
559 php_syn_tree_free(class_decl
);
563 php_report_error(PHP_INTERNAL_ERROR
, "Scope table can not have such items");
571 void add_func_2_scope(PHP_SCOPE_TABLE scope
, PHP_SYN_NODE
*func
)
573 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
574 PHP_SCOPE_ITEM
*it
= new PHP_SCOPE_ITEM
;
575 it
->type
= PHP_SCOPE_FUNC
;
577 std::string
key(func
->func_decl
->name
);
578 if ( scope_map
->count(key
) ) {
579 // error - function already defined
580 php_report_error(PHP_ERROR
, "Can not add function to scope table - already present");
582 (*scope_map
)[key
] = it
;
586 void add_class_2_scope(PHP_SCOPE_TABLE scope
, PHP_SYN_NODE
*class_node
)
588 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
589 PHP_SCOPE_ITEM
*it
= new PHP_SCOPE_ITEM
;
590 it
->type
= PHP_SCOPE_CLASS
;
591 it
->class_decl
= class_node
;
592 std::string
key(class_node
->class_decl
->name
);
593 if ( scope_map
->count(key
) ) {
594 // error - function already defined
595 php_report_error(PHP_ERROR
, "Can not add function to scope table - already present");
597 (*scope_map
)[key
] = it
;
601 PHP_SCOPE_ITEM
*make_named_scope_item(PHP_SCOPE_TABLE scope
, const char *name
)
603 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
604 PHP_SCOPE_ITEM
*it
= new PHP_SCOPE_ITEM
;
605 memset(it
, 0, sizeof(PHP_SCOPE_ITEM
));
607 std::string
key(name
);
608 (*scope_map
)[key
] = it
;
612 PHP_SCOPE_ITEM
*add_var_2_scope(PHP_SCOPE_TABLE scope
, PHP_VAR_NODE
*var
, const char *name
)
614 PHP_SCOPE_ITEM
*it
= make_named_scope_item(scope
, name
);
615 it
->type
= PHP_SCOPE_VAR
;
621 PHP_SCOPE_ITEM_TYPE
get_scope_item_type(PHP_SCOPE_TABLE scope
, const char *name
)
623 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
624 std::string
key(name
);
625 if ( scope_map
->count(key
) ) {
626 PHP_SCOPE_ITEM
*it
= (*scope_map
)[key
];
629 return PHP_SCOPE_NONE
;
632 PHP_SCOPE_ITEM
*get_scope_item(PHP_SCOPE_TABLE scope
, const char *name
)
635 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
636 std::string
key(name
);
637 if ( scope_map
->count(key
) ) {
638 PHP_SCOPE_ITEM
*it
= (*scope_map
)[key
];
644 const char *get_scope_var_name(PHP_SCOPE_TABLE scope
, PHP_VAR_NODE
*var
)
646 PHP_SCOPE_TABLE_TYPE
*scope_map
= (PHP_SCOPE_TABLE_TYPE
*)scope
;
648 for(PHP_SCOPE_TABLE_TYPE::iterator i
= scope_map
->begin(); i
!= scope_map
->end();++i
) {
649 if ( i
->second
->type
== PHP_SCOPE_VAR
) {
650 PHP_VAR_NODE
*curr_var
= i
->second
->var
;
651 if ( curr_var
== var
) {
652 return i
->first
.c_str();
660 /* array operations */
661 const std::string
&array_get_ith_key(PHP_VALUE_NODE
*array
, int i
)
663 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
664 PHP_ARRAY_ITER_TYPE it
= arr_ptr
->array
.begin();
670 PHP_VAR_NODE
*array_get_by_str_key(PHP_VALUE_NODE
*array
, std::string key
)
672 if ( array
->type
!= PHP_VAL_ARRAY
) {
675 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
676 if ( arr_ptr
->array
.count(key
) ) {
677 return (arr_ptr
->array
)[key
];
679 PHP_VAR_NODE
*add_node
= make_var_node();
680 add_node
->value
.type
= PHP_VAL_NONE
;
681 add_node
->ref_count
++;
682 (arr_ptr
->array
)[key
] = add_node
;
683 arr_ptr
->sorted_keys
.push_back(key
);
688 PHP_VAR_NODE
*array_get_by_int_key(PHP_VALUE_NODE
*array
, int key
)
690 if ( array
->type
!= PHP_VAL_ARRAY
) {
694 snprintf(s_key
, sizeof(s_key
), "%d", key
);
695 return array_get_by_str_key(array
, s_key
);
698 PHP_VAR_NODE
*array_get_by_key(PHP_VALUE_NODE
*array
, PHP_VALUE_NODE
*key
)
700 if ( array
->type
!= PHP_VAL_ARRAY
) {
703 PHP_VALUE_NODE s_key
= *key
;
704 cast_value_str(&s_key
);
705 return array_get_by_str_key(array
, s_key
.str_val
);
708 void array_set_by_key(PHP_VALUE_NODE
*array
, PHP_VALUE_NODE
*key
, PHP_VAR_NODE
*node
)
710 if ( array
->type
!= PHP_VAL_ARRAY
) {
713 PHP_VALUE_NODE s_key
= *key
;
714 cast_value_str(&s_key
);
715 array_remove_at_str_key(array
, s_key
.str_val
);
716 array_add_to_str_key(array
, s_key
.str_val
, node
);
717 value_value_free(&s_key
);
720 void array_add_to_str_key(PHP_VALUE_NODE
*array
, std::string key
, PHP_VAR_NODE
*node
)
722 if ( array
->type
!= PHP_VAL_ARRAY
) {
725 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
726 if ( !arr_ptr
->array
.count(key
) ) {
728 (arr_ptr
->array
)[key
] = node
;
729 arr_ptr
->sorted_keys
.push_back(key
);
733 void array_remove_at_str_key(PHP_VALUE_NODE
*array
, std::string key
)
735 if ( array
->type
!= PHP_VAL_ARRAY
) {
738 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
739 if ( arr_ptr
->array
.count(key
) ) {
740 PHP_VAR_NODE
*node
= (arr_ptr
->array
)[key
];
742 arr_ptr
->array
.erase(key
);
743 for(PHP_ARRAY_KEY_ITER_TYPE i
= arr_ptr
->sorted_keys
.begin(); i
!= arr_ptr
->sorted_keys
.end(); ++i
) {
745 arr_ptr
->sorted_keys
.erase(i
);
752 void array_add_to_int_key(PHP_VALUE_NODE
*array
, int key
, PHP_VAR_NODE
*node
)
755 snprintf(s_key
, sizeof(s_key
), "%d", key
);
756 array_add_to_str_key(array
, s_key
, node
);
760 int array_is_key_here(PHP_VALUE_NODE
*array
, PHP_VALUE_NODE
*key
)
762 if ( array
->type
!= PHP_VAL_ARRAY
) {
765 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
766 PHP_VALUE_NODE s_key
= *key
;
767 cast_value_str(&s_key
);
768 std::string
arr_key(s_key
.str_val
);
770 return arr_ptr
->array
.count(arr_key
);
773 int array_get_size(PHP_VALUE_NODE
*array
)
775 if ( array
->type
!= PHP_VAL_ARRAY
) {
778 PHP_ARRAY_TYPE
*arr_ptr
= (PHP_ARRAY_TYPE
*)array
->ptr_val
;
780 return arr_ptr
->array
.size();
783 PHP_VAR_NODE
*array_push_back(PHP_VALUE_NODE
*array
)
785 for(int i
= 0; i
< 0xffff;i
++) {
786 PHP_VAR_NODE
*arr_var_node
= array_get_by_int_key(array
, i
);
787 if ( arr_var_node
->value
.type
== PHP_VAL_NONE
) {
791 // array size reached 64K ?!
795 /* value manipulation - assignment and disposal */
797 void value_value_assign(PHP_VALUE_NODE
*dst
, PHP_VALUE_NODE
*src
)
799 // first, free old value
800 value_value_free(dst
);
801 dst
->type
= src
->type
;
803 // scalars are copied. Objects are copied too, since
804 // interpreter doesn't allocate them.
810 // assign biggest in union
811 dst
->obj_val
= src
->obj_val
;
813 // string is duplicated
814 case PHP_VAL_STRING
: {
815 dst
->str_val
= strdup(src
->str_val
);
818 // array must duplicate all it's values
819 case PHP_VAL_ARRAY
: {
820 dst
->ptr_val
= new PHP_ARRAY_TYPE
;
821 PHP_ARRAY_TYPE
*src_array
= (PHP_ARRAY_TYPE
*)src
->ptr_val
;
822 for(PHP_ARRAY_KEY_ITER_TYPE i
= src_array
->sorted_keys
.begin(); i
!= src_array
->sorted_keys
.end(); ++i
) {
823 PHP_VAR_NODE
*added
= array_get_by_str_key(dst
, *i
);
824 value_value_assign(&added
->value
, &src_array
->array
[*i
]->value
);
829 case PHP_VAL_VAR_NODE
:
830 case PHP_VAL_INT_DATA
: break;
834 void var_node_free(PHP_VAR_NODE
*var
)
836 assert(var
&& var
->ref_count
);
838 if ( var
->ref_count
== 0 ) {
839 value_value_free(&var
->value
);
844 void value_value_free(PHP_VALUE_NODE
*val
)
852 case PHP_VAL_STRING
: {
857 case PHP_VAL_ARRAY
: {
858 for(PHP_ARRAY_ITER_TYPE i
= ((PHP_ARRAY_TYPE
*)val
->ptr_val
)->array
.begin();
859 i
!= ((PHP_ARRAY_TYPE
*)val
->ptr_val
)->array
.end(); ++i
) {
860 PHP_VAR_NODE
*var_i
= i
->second
;
861 var_node_free(var_i
);
863 delete ((PHP_ARRAY_TYPE
*)val
->ptr_val
);
866 case PHP_VAL_OBJECT
: break;
868 case PHP_VAL_VAR_NODE
:
869 case PHP_VAL_INT_DATA
: break;
871 val
->type
= PHP_VAL_NONE
;
874 /* casting functions */
875 void cast_value_dnum(PHP_VALUE_NODE
*val
)
878 case PHP_VAL_NONE
: val
->int_val
= 0; break;
880 case PHP_VAL_INT
: break;
881 case PHP_VAL_FLOAT
: val
->int_val
= (int)val
->float_val
; break;
882 case PHP_VAL_STRING
: {
883 char *str
= val
->str_val
;
884 val
->int_val
= atoll(val
->str_val
);
889 case PHP_VAL_OBJECT
: val
->int_val
= 0; break;
890 case PHP_VAL_VAR_NODE
:
891 case PHP_VAL_INT_DATA
: assert(0); break;
893 val
->type
= PHP_VAL_INT
;
896 void cast_value_bool(PHP_VALUE_NODE
*val
)
898 cast_value_dnum(val
);
899 val
->type
= PHP_VAL_BOOL
;
902 void cast_value_fnum(PHP_VALUE_NODE
*val
)
905 case PHP_VAL_NONE
: val
->float_val
= 0; break;
907 case PHP_VAL_INT
: val
->float_val
= val
->int_val
; break;
908 case PHP_VAL_FLOAT
: break;
909 case PHP_VAL_STRING
: {
910 char *str
= val
->str_val
;
911 val
->float_val
= atof(val
->str_val
);
916 case PHP_VAL_OBJECT
: val
->float_val
= 0; break;
917 case PHP_VAL_VAR_NODE
:
918 case PHP_VAL_INT_DATA
: assert(0); break;
920 val
->type
= PHP_VAL_FLOAT
;
923 void cast_value_str(PHP_VALUE_NODE
*val
)
927 case PHP_VAL_NONE
: buff
[0] = 0; break;
929 case PHP_VAL_INT
: snprintf(buff
, sizeof(buff
), "%" PRIu64
, val
->int_val
); break;
930 case PHP_VAL_FLOAT
: snprintf(buff
, sizeof(buff
), "%.02f", val
->float_val
); break;
931 case PHP_VAL_STRING
: return;
932 case PHP_VAL_ARRAY
: {
933 delete ((PHP_ARRAY_TYPE
*)val
->ptr_val
);
934 strcpy(buff
, "Array"); break;
936 case PHP_VAL_OBJECT
: strcpy(buff
, "Object"); break;
937 case PHP_VAL_VAR_NODE
:
938 case PHP_VAL_INT_DATA
: assert(0); break;
940 val
->str_val
= strdup(buff
);
941 val
->type
= PHP_VAL_STRING
;
944 void cast_value_array(PHP_VALUE_NODE
*val
)
950 case PHP_VAL_FLOAT
: break;
951 case PHP_VAL_STRING
: free(val
->str_val
);
952 case PHP_VAL_ARRAY
: return;
953 case PHP_VAL_OBJECT
: ;/* must call to free_obj() */
954 case PHP_VAL_VAR_NODE
:
955 case PHP_VAL_INT_DATA
: assert(0); break;
957 val
->ptr_val
= new PHP_ARRAY_TYPE
;
958 val
->type
= PHP_VAL_ARRAY
;
964 PHP_EXP_NODE
*make_func_call_exp(char *func_name
, PHP_EXP_NODE
*args
)
966 PHP_EXP_NODE
*call_node
= make_zero_exp_node();
968 call_node
->op
= PHP_OP_FUNC_CALL
;
969 // copy function name
970 call_node
->tree_node
.left
= make_zero_exp_node();
971 call_node
->tree_node
.left
->op
= PHP_OP_VAL
;
972 call_node
->tree_node
.left
->val_node
.type
= PHP_VAL_STRING
;
973 call_node
->tree_node
.left
->val_node
.str_val
= strdup(func_name
);
975 call_node
->tree_node
.right
= args
;
980 PHP_EXP_NODE
*make_func_call_param_list()
982 PHP_VAR_NODE
*params
= make_array_var();
984 PHP_EXP_NODE
*exp_node
= make_zero_exp_node();
986 exp_node
->op
= PHP_OP_VAR
;
987 exp_node
->var_node
= params
;
992 void func_call_add_expr(PHP_VAR_NODE
*paramlist
, PHP_EXP_NODE
*arg
, int byref
)
994 PHP_VAR_NODE
*node
= array_push_back(¶mlist
->value
);
995 node
->value
.type
= PHP_VAL_INT_DATA
;
996 node
->value
.ptr_val
= arg
;
998 node
->flags
|= PHP_VARFLAG_BYREF
;
1002 void php_add_native_func(PHP_BLTIN_FUNC_DEF
*def
)
1004 if ( get_scope_item_type(g_global_scope
, def
->name
) != PHP_SCOPE_NONE
) {
1006 // Error: something already defined by this name
1008 php_report_error(PHP_ERROR
, "Can't add scope item: symbol already defined");
1011 PHP_SCOPE_TABLE func_scope
= make_scope_table();
1013 PHP_SYN_NODE
*decl_node
= make_func_decl_syn_node(def
->name
, 0);
1014 decl_node
->func_decl
->param_count
= def
->param_count
;
1015 decl_node
->func_decl
->params
= new PHP_FUNC_PARAM_DEF
[def
->param_count
];
1018 // Built-in functions don't have class specifier, and can handle
1019 // default arguments internally
1021 memset(decl_node
->func_decl
->params
, 0, sizeof(PHP_FUNC_PARAM_DEF
) * def
->param_count
);
1022 for(int i
= 0; i
< def
->param_count
;i
++) {
1023 PHP_VAR_NODE
*func_param
= make_var_node();
1024 char param_name
[32];
1025 snprintf(param_name
, sizeof(param_name
), "__param_%d", i
);
1027 decl_node
->func_decl
->params
[i
].def_value
.type
= PHP_VAL_NONE
;
1028 decl_node
->func_decl
->params
[i
].var
= func_param
;
1029 decl_node
->func_decl
->params
[i
].si_var
= add_var_2_scope(func_scope
, func_param
, param_name
);
1030 decl_node
->func_decl
->params
[i
].si_var
->type
= PHP_SCOPE_PARAM
;
1032 decl_node
->func_decl
->scope
= func_scope
;
1033 decl_node
->func_decl
->is_native
= 1;
1034 decl_node
->func_decl
->native_ptr
= def
->func
;
1036 add_func_2_scope(g_global_scope
, decl_node
);
1039 void php_add_native_class(const char *name
, PHP_NATIVE_PROP_GET_FUNC_PTR prop_get_native_ptr
)
1041 if ( get_scope_item_type(g_global_scope
, name
) != PHP_SCOPE_NONE
) {
1043 // Error: something already defined by this name
1045 php_report_error(PHP_ERROR
, "Can't add scope item: symbol already defined");
1048 PHP_SYN_NODE
*decl_node
= make_class_decl_syn_node();
1049 decl_node
->class_decl
->name
= strdup(name
);
1050 decl_node
->class_decl
->is_native
= 1;
1051 decl_node
->class_decl
->native_prop_get_ptr
= prop_get_native_ptr
;
1052 add_class_2_scope(g_global_scope
, decl_node
);
1055 void php_engine_init()
1057 g_global_scope
= make_scope_table();
1059 g_current_scope
= g_global_scope
;
1061 g_scope_stack
= new PHP_SCOPE_STACK_TYPE
;
1063 // here built-in functions/objects/vars are loaded
1064 php_init_core_lib();
1065 php_init_amule_lib();
1068 void php_exp_tree_free(PHP_EXP_NODE
*tree
)
1073 switch ( tree
->op
) {
1075 /* will be deleted during scope table destruction */
1078 value_value_free(&tree
->val_node
);
1080 case PHP_OP_FUNC_CALL
: {
1081 php_exp_tree_free(tree
->tree_node
.left
);
1082 PHP_VAR_NODE
*args
= tree
->tree_node
.right
->var_node
;
1083 PHP_VALUE_NODE
*args_array
= &args
->value
;
1084 for(PHP_ARRAY_ITER_TYPE i
= ((PHP_ARRAY_TYPE
*)args_array
->ptr_val
)->array
.begin();
1085 i
!= ((PHP_ARRAY_TYPE
*)args_array
->ptr_val
)->array
.end(); ++i
) {
1086 PHP_VAR_NODE
*var_i
= i
->second
;
1087 php_exp_tree_free((PHP_EXP_NODE
*)var_i
->value
.ptr_val
);
1089 value_value_free(&args
->value
);
1090 delete tree
->tree_node
.right
->var_node
;
1091 delete tree
->tree_node
.right
;
1094 case PHP_OP_ARRAY
: {
1095 PHP_EXP_NODE
*curr
= tree
->tree_node
.left
;
1097 PHP_EXP_NODE
*next
= curr
->next
;
1098 php_exp_tree_free(curr
->exp_node
);
1105 php_exp_tree_free(tree
->exp_node
);
1107 // all other things using left/right
1108 php_exp_tree_free(tree
->tree_node
.left
);
1109 php_exp_tree_free(tree
->tree_node
.right
);
1115 void php_syn_tree_free(PHP_SYN_NODE
*tree
)
1118 switch ( tree
->type
) {
1121 php_exp_tree_free(tree
->node_expr
);
1124 PHP_EXP_NODE
*curr
= tree
->node_expr
;
1126 PHP_EXP_NODE
*next
= curr
->next
;
1127 php_exp_tree_free(curr
->exp_node
);
1134 php_exp_tree_free(tree
->node_if
.cond
);
1135 php_syn_tree_free(tree
->node_if
.code_if
);
1136 php_syn_tree_free(tree
->node_if
.code_else
);
1139 case PHP_ST_DO_WHILE
:
1140 php_exp_tree_free(tree
->node_while
.cond
);
1141 php_syn_tree_free(tree
->node_while
.code
);
1144 php_exp_tree_free(tree
->node_for
.do_start
);
1145 php_exp_tree_free(tree
->node_for
.cond
);
1146 php_exp_tree_free(tree
->node_for
.do_next
);
1147 php_syn_tree_free(tree
->node_for
.code
);
1149 case PHP_ST_FOREACH
:
1150 php_exp_tree_free(tree
->node_foreach
.elems
);
1151 php_syn_tree_free(tree
->node_foreach
.code
);
1153 case PHP_ST_CONTINUE
:
1156 case PHP_ST_FUNC_DECL
:
1157 if ( !tree
->func_decl
->is_native
) {
1158 php_syn_tree_free(tree
->func_decl
->code
);
1160 delete_scope_table(tree
->func_decl
->scope
);
1161 free(tree
->func_decl
->name
);
1162 for(int i
= 0; i
< tree
->func_decl
->param_count
; i
++) {
1163 if (tree
->func_decl
->params
[i
].class_name
) {
1164 free(tree
->func_decl
->params
[i
].class_name
);
1167 delete [] tree
->func_decl
->params
;
1168 delete tree
->func_decl
;
1170 case PHP_ST_SWITCH
: {
1171 php_exp_tree_free(tree
->node_switch
.cond
);
1172 php_syn_tree_free(tree
->node_switch
.case_list
->exp_node
->tree_node
.syn_right
);
1173 PHP_EXP_NODE
*curr
= tree
->node_switch
.case_list
;
1175 PHP_EXP_NODE
*next
= curr
->next
;
1176 if ( curr
->exp_node
) {
1177 php_exp_tree_free(curr
->exp_node
->tree_node
.left
);
1178 delete curr
->exp_node
;
1185 case PHP_ST_CLASS_DECL
:
1186 free(tree
->class_decl
->name
);
1187 delete tree
->class_decl
;
1190 PHP_SYN_NODE
*next_node
= tree
->next_node
;
1196 void php_engine_free()
1198 if ( g_global_scope
) {
1199 delete_scope_table(g_global_scope
);
1201 php_syn_tree_free(g_syn_tree_top
);
1203 g_current_scope
= 0;
1204 delete (PHP_SCOPE_STACK_TYPE
*)g_scope_stack
;
1208 * Create reference. This is recoursive process, since operators []
1209 * can be stacked: $a[1][2][3] = & $b;
1210 * There's 3 valid cases in making reference:
1211 * 1,2. Target is scalar variable or variable by name ${xxx}
1212 * 3. Target is member of array.
1214 void exp_set_ref(PHP_EXP_NODE
*expr
, PHP_VAR_NODE
*var
, PHP_VALUE_NODE
*key
)
1216 switch ( expr
->op
) {
1218 if ( expr
->var_si_node
->var
!= var
) {
1220 cast_value_array(&expr
->var_si_node
->var
->value
);
1221 array_set_by_key(&expr
->var_si_node
->var
->value
, key
, var
);
1223 var_node_free(expr
->var_si_node
->var
);
1224 expr
->var_si_node
->var
= var
;
1230 case PHP_OP_ARRAY_BY_KEY
: {
1231 PHP_VALUE_NODE i_key
;
1232 i_key
.type
= PHP_VAL_NONE
;
1233 php_expr_eval(expr
->tree_node
.right
, &i_key
);
1234 exp_set_ref(expr
->tree_node
.left
, var
, &i_key
);
1238 php_report_error(PHP_ERROR
, "Bad left part of operator =&: (%d)",
1239 expr
->tree_node
.left
->op
);
1244 * This is heart of expression tree: evaluation. It's split into 2 functions
1245 * where 1 evaluates "value" of expression, and other evaluates "lvalue" i.e. assignable
1246 * entity from given subtree.
1249 void php_expr_eval(PHP_EXP_NODE
*expr
, PHP_VALUE_NODE
*result
)
1251 PHP_VALUE_NODE result_val_right
, result_val_left
;
1252 PHP_VAR_NODE
*lval_node
= 0;
1253 PHP_SCOPE_ITEM
*si
= 0;
1254 result_val_right
.type
= PHP_VAL_NONE
;
1255 result_val_left
.type
= PHP_VAL_NONE
;
1259 value_value_assign(result
, &expr
->val_node
);
1264 value_value_assign(result
, &expr
->var_si_node
->var
->value
);
1268 lval_node
= php_expr_eval_lvalue(expr
->tree_node
.left
);
1272 php_expr_eval(expr
->tree_node
.right
, &lval_node
->value
);
1274 value_value_assign(result
, &lval_node
->value
);
1277 case PHP_OP_ARRAY_BY_KEY
:
1278 php_expr_eval(expr
->tree_node
.right
, &result_val_right
);
1279 lval_node
= php_expr_eval_lvalue(expr
->tree_node
.left
);
1280 cast_value_array(&lval_node
->value
);
1281 cast_value_str(&result_val_right
);
1282 lval_node
= array_get_by_key(&lval_node
->value
, &result_val_right
);
1284 value_value_assign(result
, &lval_node
->value
);
1288 lval_node
= php_expr_eval_lvalue(expr
->tree_node
.right
);
1292 exp_set_ref(expr
->tree_node
.left
, lval_node
, 0);
1296 PHP_EXP_NODE
*curr
= expr
->tree_node
.left
;
1297 value_value_free(result
);
1298 cast_value_array(result
);
1300 switch( curr
->exp_node
->op
) {
1301 case PHP_OP_ARRAY_PAIR
:
1302 if ( curr
->exp_node
->tree_node
.right
) {
1303 php_expr_eval(curr
->exp_node
->tree_node
.left
, &result_val_left
);
1304 cast_value_str(&result_val_left
);
1305 lval_node
= array_get_by_key(result
, &result_val_left
);
1306 value_value_free(&result_val_left
);
1307 php_expr_eval(curr
->exp_node
->tree_node
.right
, &lval_node
->value
);
1309 lval_node
= array_push_back(result
);
1310 php_expr_eval(curr
->exp_node
->tree_node
.left
, &lval_node
->value
);
1313 case PHP_OP_ARRAY_REF_PAIR
:
1314 lval_node
= php_expr_eval_lvalue(curr
->exp_node
->tree_node
.right
);
1317 php_report_error(PHP_INTERNAL_ERROR
, "Array list contain wrong node");
1324 case PHP_OP_FUNC_CALL
:
1325 php_run_func_call(expr
, result
);
1328 PHP_EXP_NODE
*curr
= expr
;
1330 if ( curr
->exp_node
) {
1331 php_expr_eval(curr
->exp_node
, result
);
1338 php_expr_eval(expr
->tree_node
.right
, &result_val_right
);
1339 php_expr_eval(expr
->tree_node
.left
, &result_val_left
);
1341 cast_value_str(&result_val_left
);
1342 cast_value_str(&result_val_right
);
1343 value_value_free(result
);
1344 result
->type
= PHP_VAL_STRING
;
1345 // using "malloc" and not "new" since all strings are freed
1346 // later with "free" and not "delete"
1347 result
->str_val
= (char *)malloc(strlen(result_val_left
.str_val
) +
1348 strlen(result_val_right
.str_val
) + 1);
1349 strcpy(result
->str_val
, result_val_left
.str_val
);
1350 strcat(result
->str_val
, result_val_right
.str_val
);
1354 php_expr_eval(expr
->exp_node
, &result_val_right
);
1355 cast_value_bool(&result_val_right
);
1356 if ( result_val_right
.int_val
) {
1357 php_expr_eval(expr
->tree_node
.left
, result
);
1359 php_expr_eval(expr
->tree_node
.right
, result
);
1362 case PHP_OP_CAST_INT
:
1364 php_expr_eval(expr
->tree_node
.left
, result
);
1365 cast_value_dnum(result
);
1368 case PHP_OP_CAST_FLOAT
:
1370 php_expr_eval(expr
->tree_node
.left
, result
);
1371 cast_value_fnum(result
);
1374 case PHP_OP_CAST_BOOL
:
1376 php_expr_eval(expr
->tree_node
.left
, result
);
1377 cast_value_bool(result
);
1380 case PHP_OP_CAST_STR
:
1382 php_expr_eval(expr
->tree_node
.left
, result
);
1383 cast_value_str(result
);
1386 case PHP_OP_LOG_NOT
:
1388 php_expr_eval(expr
->tree_node
.left
, &result_val_right
);
1389 cast_value_bool(&result_val_right
);
1390 result_val_right
.int_val
= !result_val_right
.int_val
;
1391 value_value_assign(result
, &result_val_right
);
1396 php_expr_eval(expr
->tree_node
.left
, &result_val_right
);
1397 cast_value_bool(&result_val_right
);
1398 result_val_right
.int_val
= ~result_val_right
.int_val
;
1399 value_value_assign(result
, &result_val_right
);
1406 php_expr_eval(expr
->tree_node
.right
, &result_val_right
);
1407 php_expr_eval(expr
->tree_node
.left
, &result_val_left
);
1409 php_eval_simple_math(expr
->op
, &result_val_left
, &result_val_right
, result
);
1418 case PHP_OP_LOG_AND
:
1419 case PHP_OP_LOG_XOR
:
1420 php_expr_eval(expr
->tree_node
.right
, &result_val_right
);
1421 php_expr_eval(expr
->tree_node
.left
, &result_val_left
);
1423 php_eval_int_math(expr
->op
, &result_val_left
, &result_val_right
, result
);
1430 php_expr_eval(expr
->tree_node
.right
, &result_val_right
);
1431 php_expr_eval(expr
->tree_node
.left
, &result_val_left
);
1433 php_eval_compare(expr
->op
, &result_val_left
, &result_val_right
, result
);
1437 php_expr_eval(expr
->tree_node
.left
, &result_val_right
);
1438 cast_value_str(&result_val_right
);
1440 // I print to buffer
1441 CPhPLibContext::Print(result_val_right
.str_val
);
1443 case PHP_OP_OBJECT_DEREF
: // $x->y
1444 // take variable from scope of current object
1445 lval_node
= php_expr_eval_lvalue(expr
->tree_node
.left
);
1447 php_report_error(PHP_ERROR
, "Left part of -> must be lvalue");
1450 if ( lval_node
->value
.type
!= PHP_VAL_OBJECT
) {
1451 php_report_error(PHP_ERROR
, "Left part of -> must be an object");
1454 if ( get_scope_item_type(g_global_scope
, lval_node
->value
.obj_val
.class_name
) == PHP_SCOPE_NONE
) {
1455 php_report_error(PHP_ERROR
, "Undeclared object");
1458 si
= get_scope_item(g_global_scope
, lval_node
->value
.obj_val
.class_name
);
1459 if ( si
->type
!= PHP_SCOPE_CLASS
) {
1460 php_report_error(PHP_INTERNAL_ERROR
, "Object classname is not name of class");
1463 // left part is ok, let's check the right
1464 if ( (expr
->tree_node
.right
->op
!= PHP_OP_VAL
) || (expr
->tree_node
.right
->val_node
.type
!= PHP_VAL_STRING
) ) {
1465 php_report_error(PHP_ERROR
, "Right part of -> must be string value");
1468 if ( si
->class_decl
->class_decl
->is_native
) {
1469 si
->class_decl
->class_decl
->native_prop_get_ptr(lval_node
->value
.obj_val
.inst_ptr
,
1470 expr
->tree_node
.right
->val_node
.str_val
, result
);
1472 php_report_error(PHP_ERROR
, "Only native classes supported");
1476 case PHP_OP_CLASS_DEREF
: // A::y
1477 // take variable (static) from scope of current class
1478 php_report_error(PHP_ERROR
, "Value of static class members not supported");
1483 value_value_free(&result_val_left
);
1484 value_value_free(&result_val_right
);
1487 PHP_VAR_NODE
*php_expr_eval_lvalue(PHP_EXP_NODE
*expr
)
1489 PHP_VAR_NODE
*lval_node
= 0;
1491 PHP_VALUE_NODE index
;
1492 index
.type
= PHP_VAL_NONE
;
1496 lval_node
= expr
->var_si_node
->var
;
1498 case PHP_OP_ARRAY_BY_KEY
:
1499 lval_node
= php_expr_eval_lvalue(expr
->tree_node
.left
);
1504 cast_value_array(&lval_node
->value
);
1505 if ( expr
->tree_node
.right
) {
1506 php_expr_eval(expr
->tree_node
.right
, &index
);
1507 if ( index
.type
== PHP_VAL_NONE
) {
1508 // something got wrong: evaluation result is not a value
1511 cast_value_str(&index
);
1512 lval_node
= array_get_by_key(&lval_node
->value
, &index
);
1513 value_value_free(&index
);
1515 // this is "$xxx[] = " construct.
1516 lval_node
= array_push_back(&lval_node
->value
);
1518 case PHP_OP_VAR_BY_EXP
: // ${"xxx"}
1519 // should take variable from current scope
1521 case PHP_OP_OBJECT_DEREF
: // $x->y
1522 // take variable from scope of current object
1523 php_report_error(PHP_ERROR
, "Assign to class members not supported");
1525 case PHP_OP_CLASS_DEREF
: // A::y
1526 // take variable (static) from scope of current class
1527 php_report_error(PHP_ERROR
, "Assign to static class members not supported");
1531 // Error: expression can not be taken as lvalue
1533 php_report_error(PHP_ERROR
, "This expression can't be used as lvalue");
1538 PHP_VALUE_TYPE
cast_type_resolve(PHP_VALUE_NODE
*op1
, PHP_VALUE_NODE
*op2
)
1540 if ( (op1
->type
== PHP_VAL_FLOAT
) || (op2
->type
== PHP_VAL_FLOAT
) ) {
1541 cast_value_fnum(op1
);
1542 cast_value_fnum(op2
);
1543 return PHP_VAL_FLOAT
;
1545 cast_value_dnum(op1
);
1546 cast_value_dnum(op2
);
1552 * Same as simple_math, but result is always bool
1554 void php_eval_compare(PHP_EXP_OP op
, PHP_VALUE_NODE
*op1
, PHP_VALUE_NODE
*op2
, PHP_VALUE_NODE
*result
)
1556 result
->type
= PHP_VAL_BOOL
;
1557 if ( (op1
->type
== PHP_VAL_STRING
) || (op2
->type
== PHP_VAL_STRING
) ) {
1558 cast_value_str(op1
);
1559 cast_value_str(op2
);
1560 int cmp_val
= strcmp(op1
->str_val
, op2
->str_val
);
1563 result
->int_val
= (cmp_val
== 0);
1566 result
->int_val
= (cmp_val
!= 0);
1569 result
->int_val
= (cmp_val
> 0);
1572 result
->int_val
= (cmp_val
< 0);
1575 result
->int_val
= (cmp_val
>= 0);
1578 result
->int_val
= (cmp_val
<= 0);
1581 php_report_error(PHP_INTERNAL_ERROR
, "This op is not compare op");
1584 PHP_VALUE_TYPE restype
= cast_type_resolve(op1
, op2
);
1587 if ( restype
== PHP_VAL_FLOAT
) {
1588 result
->int_val
= op1
->float_val
== op2
->float_val
;
1590 result
->int_val
= op1
->int_val
== op2
->int_val
;
1594 if ( restype
== PHP_VAL_FLOAT
) {
1595 result
->int_val
= op1
->float_val
!= op2
->float_val
;
1597 result
->int_val
= op1
->int_val
!= op2
->int_val
;
1601 if ( restype
== PHP_VAL_FLOAT
) {
1602 result
->int_val
= op1
->float_val
> op2
->float_val
;
1604 result
->int_val
= op1
->int_val
> op2
->int_val
;
1608 if ( restype
== PHP_VAL_FLOAT
) {
1609 result
->int_val
= op1
->float_val
>= op2
->float_val
;
1611 result
->int_val
= op1
->int_val
>= op2
->int_val
;
1615 if ( restype
== PHP_VAL_FLOAT
) {
1616 result
->int_val
= op1
->float_val
< op2
->float_val
;
1618 result
->int_val
= op1
->int_val
< op2
->int_val
;
1622 if ( restype
== PHP_VAL_FLOAT
) {
1623 result
->int_val
= op1
->float_val
<= op2
->float_val
;
1625 result
->int_val
= op1
->int_val
<= op2
->int_val
;
1629 php_report_error(PHP_INTERNAL_ERROR
, "This op is not compare op");
1634 void php_eval_simple_math(PHP_EXP_OP op
, PHP_VALUE_NODE
*op1
, PHP_VALUE_NODE
*op2
, PHP_VALUE_NODE
*result
)
1636 result
->type
= cast_type_resolve(op1
, op2
);
1639 if ( result
->type
== PHP_VAL_FLOAT
) {
1640 result
->float_val
= op1
->float_val
+ op2
->float_val
;
1642 result
->int_val
= op1
->int_val
+ op2
->int_val
;
1646 if ( result
->type
== PHP_VAL_FLOAT
) {
1647 result
->float_val
= op1
->float_val
- op2
->float_val
;
1649 result
->int_val
= op1
->int_val
- op2
->int_val
;
1653 if ( result
->type
== PHP_VAL_FLOAT
) {
1654 result
->float_val
= op1
->float_val
* op2
->float_val
;
1656 result
->int_val
= op1
->int_val
* op2
->int_val
;
1660 if ( result
->type
== PHP_VAL_FLOAT
) {
1661 result
->float_val
= op1
->float_val
/ op2
->float_val
;
1663 result
->int_val
= op1
->int_val
/ op2
->int_val
;
1667 php_report_error(PHP_INTERNAL_ERROR
, "This op is not simple math");
1671 void php_eval_int_math(PHP_EXP_OP op
, PHP_VALUE_NODE
*op1
, PHP_VALUE_NODE
*op2
, PHP_VALUE_NODE
*result
)
1673 cast_value_dnum(op1
);
1674 cast_value_dnum(op2
);
1675 result
->type
= PHP_VAL_INT
;
1678 result
->int_val
= op1
->int_val
<< op2
->int_val
;
1681 result
->int_val
= op1
->int_val
>> op2
->int_val
;
1684 result
->int_val
= op1
->int_val
| op2
->int_val
;
1687 result
->int_val
= op1
->int_val
|| op2
->int_val
;
1690 result
->int_val
= op1
->int_val
& op2
->int_val
;
1692 case PHP_OP_LOG_AND
:
1693 result
->int_val
= op1
->int_val
&& op2
->int_val
;
1695 case PHP_OP_LOG_XOR
:
1696 op1
->int_val
= op1
->int_val
? 1 : 0;
1697 op2
->int_val
= op2
->int_val
? 1 : 0;
1699 result
->int_val
= op1
->int_val
^ op2
->int_val
;
1702 php_report_error(PHP_INTERNAL_ERROR
, "This op is not int math");
1707 // left = VAR(func_name), right=ARRAY(args)
1708 void php_run_func_call(PHP_EXP_NODE
*node
, PHP_VALUE_NODE
*result
)
1710 PHP_EXP_NODE
*l_node
= node
->tree_node
.left
;
1711 PHP_EXP_NODE
*r_node
= node
->tree_node
.right
;
1712 if ( (l_node
->op
!= PHP_OP_VAL
) || (l_node
->val_node
.type
!= PHP_VAL_STRING
) ||
1713 (r_node
->op
!= PHP_OP_VAR
) || (r_node
->var_node
->value
.type
!= PHP_VAL_ARRAY
) ) {
1715 // Internal error: function name must be string value node, and
1716 // params must be an array
1718 php_report_error(PHP_INTERNAL_ERROR
, "Function call node have wrong data");
1721 PHP_SCOPE_ITEM
*si
= get_scope_item(g_global_scope
, l_node
->val_node
.str_val
);
1724 // Error: undeclared symbol
1726 php_report_error(PHP_ERROR
, "Function [ %s ] is not defined", l_node
->val_node
.str_val
);
1729 if ( si
->type
!= PHP_SCOPE_FUNC
) {
1731 // Error: defined, but wrong type !
1733 php_report_error(PHP_ERROR
, "Item [ %s ] is not a function", l_node
->val_node
.str_val
);
1736 PHP_SYN_NODE
*func
= si
->func
;
1737 if ( func
->type
!= PHP_ST_FUNC_DECL
) {
1739 // Internal error: node not a function
1741 php_report_error(PHP_INTERNAL_ERROR
, "Wrong type in function decl node");
1746 // Switch stack and call function
1749 PHP_SYN_FUNC_DECL_NODE
*func_decl
= func
->func_decl
;
1751 std::map
<std::string
, PHP_VAR_NODE
*> saved_vars
;
1752 func_scope_init(func_decl
->params
, func_decl
->param_count
,
1753 (PHP_SCOPE_TABLE_TYPE
*)func_decl
->scope
,
1754 &r_node
->var_node
->value
, saved_vars
);
1756 switch_push_scope_table((PHP_SCOPE_TABLE_TYPE
*)func_decl
->scope
);
1758 if ( func_decl
->is_native
) {
1759 func_decl
->native_ptr(result
);
1761 php_execute(func_decl
->code
, result
);
1765 // restore stack, free arg list
1767 switch_pop_scope_table(0);
1768 func_scope_copy_back(func_decl
->params
, func_decl
->param_count
,
1769 (PHP_SCOPE_TABLE_TYPE
*)func_decl
->scope
, &r_node
->var_node
->value
, saved_vars
);
1771 //scope_reset_nonstatics(func_decl->scope);
1776 * Theoretically speaking this function must run on generated code. On the
1777 * practical side - I need it to debug syntax tree generation. Later, it can
1778 * be changes to generate code for some kind of bytecode for stack machine
1780 int php_execute(PHP_SYN_NODE
*node
, PHP_VALUE_NODE
*result
)
1785 int curr_exec_result
;
1787 curr_exec_result
= 0;
1788 PHP_VALUE_NODE cond_result
;
1789 cond_result
.type
= PHP_VAL_NONE
;
1790 switch (node
->type
) {
1792 php_expr_eval(node
->node_expr
, 0);
1795 php_expr_eval(node
->node_if
.cond
, &cond_result
);
1796 cast_value_bool(&cond_result
);
1797 if ( cond_result
.int_val
) {
1798 if ( node
->node_if
.code_if
) {
1799 curr_exec_result
= php_execute(node
->node_if
.code_if
, result
);
1802 if ( node
->node_if
.code_else
) {
1803 curr_exec_result
= php_execute(node
->node_if
.code_else
, result
);
1808 if ( node
->node_expr
) {
1809 php_expr_eval(node
->node_expr
, result
);
1811 if ( node
->next_node
) {
1813 // Warning: code after "return" statement
1815 php_report_error(PHP_WARNING
, "code after 'return'");
1817 // "return" is ultimate "break"
1818 curr_exec_result
= -0xffff;
1821 PHP_EXP_NODE
*curr
= node
->node_expr
;
1823 php_expr_eval(curr
->exp_node
, &cond_result
);
1824 cast_value_str(&cond_result
);
1825 CPhPLibContext::Print(cond_result
.str_val
);
1826 value_value_free(&cond_result
);
1831 case PHP_ST_CONTINUE
:
1833 if ( node
->node_expr
) {
1834 // 'break' or 'continue' used with an argument
1835 php_expr_eval(node
->node_expr
, &cond_result
);
1837 // without an argument break or continue just 1 loop
1838 cond_result
.type
= PHP_VAL_INT
;
1839 cond_result
.int_val
= 1;
1841 cast_value_dnum(&cond_result
);
1842 if ( node
->type
== PHP_ST_BREAK
) {
1843 curr_exec_result
= -(int)(cond_result
.int_val
);
1845 curr_exec_result
= cond_result
.int_val
;
1850 case PHP_ST_DO_WHILE
:
1851 if ( node
->type
== PHP_ST_WHILE
) {
1852 php_expr_eval(node
->node_while
.cond
, &cond_result
);
1853 cast_value_bool(&cond_result
);
1855 cond_result
.int_val
= 1;
1857 while ( cond_result
.int_val
) {
1858 // evaluate code within while loop
1859 curr_exec_result
= php_execute(node
->node_while
.code
, 0);
1860 // if 'break' was used
1861 if ( curr_exec_result
< 0 ) {
1862 // decrease number of loops to break
1864 // and break current loop
1867 // normal execution of loop or continue
1868 if ( curr_exec_result
== 0 || curr_exec_result
== 1 ) {
1869 curr_exec_result
= 0;
1870 // evaluate 'while' loop conditions
1871 php_expr_eval(node
->node_while
.cond
, &cond_result
);
1872 cast_value_bool(&cond_result
);
1874 // if 'continue' was used with an argument > 1
1875 if ( curr_exec_result
> 1 ) {
1876 // decrease number of loops to skip
1878 // and break current loop
1884 php_expr_eval(node
->node_for
.do_start
, &cond_result
);
1885 php_expr_eval(node
->node_for
.cond
, &cond_result
);
1886 cast_value_bool(&cond_result
);
1887 while ( cond_result
.int_val
) {
1888 curr_exec_result
= php_execute(node
->node_for
.code
, 0);
1889 // handle 'break' and 'continue'
1890 if ( curr_exec_result
< 0 ) {
1894 if ( curr_exec_result
== 0 || curr_exec_result
== 1 ) {
1895 curr_exec_result
= 0;
1896 // evaluate 'for' loop conditions
1897 php_expr_eval(node
->node_for
.do_next
, &cond_result
);
1898 php_expr_eval(node
->node_for
.cond
, &cond_result
);
1899 cast_value_bool(&cond_result
);
1901 if ( curr_exec_result
> 1 ) {
1907 case PHP_ST_FOREACH
: {
1908 PHP_VAR_NODE
*elems
= php_expr_eval_lvalue(node
->node_foreach
.elems
);
1909 if ( !elems
|| (elems
->value
.type
!= PHP_VAL_ARRAY
) ) {
1910 php_report_error(PHP_ERROR
, "Argument of 'foreach' must be array");
1913 PHP_ARRAY_TYPE
*array
= (PHP_ARRAY_TYPE
*)elems
->value
.ptr_val
;
1914 PHP_SCOPE_ITEM
*i_key
= node
->node_foreach
.i_key
;
1915 // keys in array are string values.
1917 i_key
->var
->value
.type
= PHP_VAL_STRING
;
1919 PHP_SCOPE_ITEM
*i_val
= node
->node_foreach
.i_val
;
1920 array
->current
= array
->sorted_keys
.begin();
1921 while ( array
->current
!= array
->sorted_keys
.end() ) {
1923 PHP_VALUE_NODE tmp_val
;
1924 tmp_val
.type
= PHP_VAL_STRING
;
1925 tmp_val
.str_val
= (char *)array
->current
->c_str();
1926 value_value_assign(&i_key
->var
->value
, &tmp_val
);
1928 PHP_VALUE_NODE
*curr_value
= &array
->array
[*array
->current
]->value
;
1929 value_value_assign(&i_val
->var
->value
, curr_value
);
1930 curr_exec_result
= php_execute(node
->node_foreach
.code
, 0);
1933 value_value_free(&i_key
->var
->value
);
1935 if ( node
->node_foreach
.byref
) {
1936 value_value_assign(curr_value
, &i_val
->var
->value
);
1938 value_value_free(&i_val
->var
->value
);
1939 // handle 'break' and 'continue'
1940 if ( curr_exec_result
< 0 ) {
1944 if ( curr_exec_result
== 0 || curr_exec_result
== 1 ) {
1945 curr_exec_result
= 0;
1949 if ( curr_exec_result
> 1 ) {
1956 case PHP_ST_SWITCH
: {
1957 PHP_SYN_NODE
*cur_exec
= 0;
1958 // evaluate switch argument
1959 php_expr_eval(node
->node_switch
.cond
, &cond_result
);
1960 // loop through list of case statements
1961 PHP_EXP_NODE
*curr
= node
->node_switch
.case_list
;
1963 PHP_VALUE_NODE cur_value
, cmp_result
;
1964 cur_value
.type
= cmp_result
.type
= PHP_VAL_NONE
;
1965 // TODO make amuleweb not crash when 'default' is used
1966 php_expr_eval(curr
->exp_node
->tree_node
.left
, &cur_value
);
1968 // switch argument equal to case argument?
1969 php_eval_compare(PHP_OP_EQ
, &cur_value
, &cond_result
, &cmp_result
);
1970 if ( cmp_result
.int_val
) {
1971 // execute code and rest of case statements
1972 cur_exec
= static_cast<PHP_SYN_NODE
*>(curr
->exp_node
->tree_node
.syn_right
);
1978 curr_exec_result
= php_execute(cur_exec
, result
);
1980 if (curr_exec_result
< 0) curr_exec_result
++;
1982 if (curr_exec_result
> 0) curr_exec_result
--;
1988 if ( curr_exec_result
) {
1989 return curr_exec_result
;
1991 node
= node
->next_node
;
1993 // everything ok, keep going
1999 // call it when something gone wrong
2001 void php_report_error(PHP_MSG_TYPE err_type
, const char *msg
, ...)
2004 // hope my error message will never be that big.
2006 // security is ok, since _user_ errors are not reporting thru
2007 // this function, but handled by scipt itself.
2008 // However, badly written script MAY force user-supplied data to
2009 // leak here and create stack overrun exploit. Be warned.
2012 const char *type_msg
= 0;
2018 type_msg
= "PHP Warning:";
2021 type_msg
= "PHP Error:";
2023 case PHP_INTERNAL_ERROR
:
2024 type_msg
= "PHP Internal Error:";
2029 va_start(args
, msg
);
2030 vsnprintf(msgbuf
, sizeof(msgbuf
), msg
, args
);
2033 printf("%s %s\n", type_msg
, msgbuf
);
2034 assert(err_type
!= PHP_INTERNAL_ERROR
);
2038 int phperror(char *s
)
2040 printf("ERROR in grammar %s after [%s] near line %d\n", s
, phptext
, phplineno
);
2044 // File_checked_for_headers