⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 php_syntree.cpp

📁 电驴的MAC源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				lval_node = array_push_back(&lval_node->value);			}		case PHP_OP_VAR_BY_EXP: // ${"xxx"}			// should take variable from current scope			break;		case PHP_OP_OBJECT_DEREF: // $x->y			// take variable from scope of current object			php_report_error(PHP_ERROR, "Assign to class members not supported");			break;		case PHP_OP_CLASS_DEREF: // A::y			// take variable (static) from scope of current class			php_report_error(PHP_ERROR, "Assign to static class members not supported");			break;		default:			//			// Error: expression can not be taken as lvalue			//			php_report_error(PHP_ERROR, "This expression can't be used as lvalue");	}	return lval_node;}PHP_VALUE_TYPE cast_type_resolve(PHP_VALUE_NODE *op1, PHP_VALUE_NODE *op2){	if ( (op1->type == PHP_VAL_FLOAT) || (op2->type == PHP_VAL_FLOAT) ) {		cast_value_fnum(op1);		cast_value_fnum(op2);		return PHP_VAL_FLOAT;	} else {		cast_value_dnum(op1);		cast_value_dnum(op2);		return PHP_VAL_INT;	}}/* * Same as simple_math, but result is always bool */void php_eval_compare(PHP_EXP_OP op, PHP_VALUE_NODE *op1, PHP_VALUE_NODE *op2, PHP_VALUE_NODE *result){	result->type = PHP_VAL_BOOL;	if ( (op1->type == PHP_VAL_STRING) || (op2->type == PHP_VAL_STRING) ) {		cast_value_str(op1);		cast_value_str(op2);		int cmp_val = strcmp(op1->str_val, op2->str_val);		switch(op) {			case PHP_OP_EQ:				result->int_val = (cmp_val == 0);				break;			case PHP_OP_NEQ:				result->int_val = (cmp_val != 0);				break;			case PHP_OP_GRT:				result->int_val = (cmp_val > 0);				break;			case PHP_OP_LWR:				result->int_val = (cmp_val < 0);				break;			case PHP_OP_GRT_EQ:				result->int_val = (cmp_val >= 0);				break;			case PHP_OP_LWR_EQ:				result->int_val = (cmp_val <= 0);				break;			default:				php_report_error(PHP_INTERNAL_ERROR, "This op is not compare op");		}		} else {		PHP_VALUE_TYPE restype = cast_type_resolve(op1, op2);		switch(op) {			case PHP_OP_EQ:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val == op2->float_val;				} else {					result->int_val = op1->int_val == op2->int_val;				}				break;			case PHP_OP_NEQ:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val != op2->float_val;				} else {					result->int_val = op1->int_val != op2->int_val;				}				break;			case PHP_OP_GRT:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val > op2->float_val;				} else {					result->int_val = op1->int_val > op2->int_val;				}				break;			case PHP_OP_GRT_EQ:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val >= op2->float_val;				} else {					result->int_val = op1->int_val >= op2->int_val;				}				break;			case PHP_OP_LWR:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val < op2->float_val;				} else {					result->int_val = op1->int_val < op2->int_val;				}				break;			case PHP_OP_LWR_EQ:				if ( restype == PHP_VAL_FLOAT ) {					result->int_val = op1->float_val <= op2->float_val;				} else {					result->int_val = op1->int_val <= op2->int_val;				}				break;			default:				php_report_error(PHP_INTERNAL_ERROR, "This op is not compare op");		}	}}void php_eval_simple_math(PHP_EXP_OP op, PHP_VALUE_NODE *op1, PHP_VALUE_NODE *op2, PHP_VALUE_NODE *result){	result->type = cast_type_resolve(op1, op2);	switch(op) {		case PHP_OP_ADD:			if ( result->type == PHP_VAL_FLOAT ) {				result->float_val = op1->float_val + op2->float_val;			} else {				result->int_val = op1->int_val + op2->int_val;			}			break;		case PHP_OP_SUB:			if ( result->type == PHP_VAL_FLOAT ) {				result->float_val = op1->float_val - op2->float_val;			} else {				result->int_val = op1->int_val - op2->int_val;			}			break;		case PHP_OP_MUL:			if ( result->type == PHP_VAL_FLOAT ) {				result->float_val = op1->float_val * op2->float_val;			} else {				result->int_val = op1->int_val * op2->int_val;			}			break;		case PHP_OP_DIV:			if ( result->type == PHP_VAL_FLOAT ) {				result->float_val = op1->float_val / op2->float_val;			} else {				result->int_val = op1->int_val / op2->int_val;			}			break;		default:			php_report_error(PHP_INTERNAL_ERROR, "This op is not simple math");	}}void php_eval_int_math(PHP_EXP_OP op, PHP_VALUE_NODE *op1, PHP_VALUE_NODE *op2, PHP_VALUE_NODE *result){	cast_value_dnum(op1);	cast_value_dnum(op2);	result->type = PHP_VAL_INT;	switch(op) {    	case PHP_OP_SHL:    		result->int_val = op1->int_val << op2->int_val;    		break;    	case PHP_OP_SHR:    		result->int_val = op1->int_val >> op2->int_val;    		break;    	case PHP_OP_OR:    		result->int_val = op1->int_val | op2->int_val;    		break;		case PHP_OP_LOG_OR:    		result->int_val = op1->int_val || op2->int_val;    		break;    	case PHP_OP_AND:    		result->int_val = op1->int_val & op2->int_val;    		break;		case PHP_OP_LOG_AND:    		result->int_val = op1->int_val && op2->int_val;    		break;		case PHP_OP_LOG_XOR:			op1->int_val = op1->int_val ? 1 : 0;			op2->int_val = op2->int_val ? 1 : 0;    	case PHP_OP_XOR:    		result->int_val = op1->int_val ^ op2->int_val;    		break;		default:			php_report_error(PHP_INTERNAL_ERROR, "This op is not int math");	}}//// left = VAR(func_name), right=ARRAY(args)void php_run_func_call(PHP_EXP_NODE *node, PHP_VALUE_NODE *result){	PHP_EXP_NODE *l_node = node->tree_node.left;	PHP_EXP_NODE *r_node = node->tree_node.right;	if ( (l_node->op != PHP_OP_VAL) || (l_node->val_node.type != PHP_VAL_STRING) ||		(r_node->op != PHP_OP_VAR) || (r_node->var_node->value.type != PHP_VAL_ARRAY) ) {		//		// Internal error: function name must be string value node, and		// params must be an array		//		php_report_error(PHP_INTERNAL_ERROR, "Function call node have wrong data");		return ;	}	PHP_SCOPE_ITEM *si = get_scope_item(g_global_scope, l_node->val_node.str_val);	if ( !si ) {		//		// Error: undeclared symbol		//		php_report_error(PHP_ERROR, "Function [ %s ] is not defined", l_node->val_node.str_val);		return;	}	if ( si->type != PHP_SCOPE_FUNC) {		//		// Error: defined, but wrong type !		//		php_report_error(PHP_ERROR, "Item [ %s ] is not a function", l_node->val_node.str_val);		return;	}	PHP_SYN_NODE *func = si->func;	if ( func->type != PHP_ST_FUNC_DECL ) {		//		// Internal error: node not a function		//		php_report_error(PHP_INTERNAL_ERROR, "Wrong type in function decl node");		return;	}		//	// Switch stack and call function	//		PHP_SYN_FUNC_DECL_NODE *func_decl = func->func_decl;	std::map<std::string, PHP_VAR_NODE *> saved_vars;	func_scope_init(func_decl->params, func_decl->param_count,		(PHP_SCOPE_TABLE_TYPE *)func_decl->scope,		&r_node->var_node->value, saved_vars);	switch_push_scope_table((PHP_SCOPE_TABLE_TYPE *)func_decl->scope);	if ( func_decl->is_native ) {		func_decl->native_ptr(result);	} else {		php_execute(func_decl->code, result);	}	//	// restore stack, free arg list	//	switch_pop_scope_table(0);	func_scope_copy_back(func_decl->params, func_decl->param_count,		(PHP_SCOPE_TABLE_TYPE *)func_decl->scope, &r_node->var_node->value, saved_vars);		//scope_reset_nonstatics(func_decl->scope);	}/* * Theoretically speaking this function must run on generated code. On the * practical side - I need it to debug syntax tree generation. Later, it can * be changes to generate code for some kind of bytecode for stack machine */int php_execute(PHP_SYN_NODE *node, PHP_VALUE_NODE *result){	if ( !node ) {		return 0;	}	int curr_exec_result;	while ( node ) {		curr_exec_result = 0;		PHP_VALUE_NODE cond_result;		cond_result.type = PHP_VAL_NONE;		switch (node->type) {			case PHP_ST_EXPR:				php_expr_eval(node->node_expr, 0);				break;			case PHP_ST_IF:				php_expr_eval(node->node_if.cond, &cond_result);				cast_value_bool(&cond_result);				if ( cond_result.int_val ) {					if ( node->node_if.code_if ) {						curr_exec_result = php_execute(node->node_if.code_if, result);					}				} else {					if ( node->node_if.code_else ) {						curr_exec_result = php_execute(node->node_if.code_else, result);					}				}				break;			case PHP_ST_RET:				if (  node->node_expr ) {					php_expr_eval(node->node_expr, result);				}				if ( node->next_node ) {					//					// Warning: code after "return" statement					//					php_report_error(PHP_WARNING, "code after 'return'");				}				// "return" is ultimate "break"				curr_exec_result = -0xffff;				break;			case PHP_ST_ECHO: {					PHP_EXP_NODE *curr = node->node_expr;					while (curr) {						php_expr_eval(curr->exp_node, &cond_result);						cast_value_str(&cond_result);						CPhPLibContext::Print(cond_result.str_val);						value_value_free(&cond_result);						curr = curr->next;					}				}				break;			case PHP_ST_CONTINUE:			case PHP_ST_BREAK:				if (  node->node_expr ) {					php_expr_eval(node->node_expr, &cond_result);				} else {					cond_result.type = PHP_VAL_INT;					cond_result.int_val = 1;				}				cast_value_dnum(&cond_result);				if ( node->type == PHP_ST_BREAK ) {					curr_exec_result = -cond_result.int_val;				} else {					curr_exec_result = cond_result.int_val;				}				break;							case PHP_ST_WHILE:			case PHP_ST_DO_WHILE:				if ( node->type == PHP_ST_WHILE ) {					php_expr_eval(node->node_while.cond, &cond_result);					cast_value_bool(&cond_result);				} else {					cond_result.int_val = 1;				}				while ( cond_result.int_val ) {					curr_exec_result = php_execute(node->node_while.code, 0);					if ( curr_exec_result < 0 ) {						break;					}					php_expr_eval(node->node_while.cond, &cond_result);					cast_value_bool(&cond_result);				}				break;			case PHP_ST_FOR:				php_expr_eval(node->node_for.do_start, &cond_result);				php_expr_eval(node->node_for.cond, &cond_result);				cast_value_bool(&cond_result);				while ( cond_result.int_val ) {					curr_exec_result = php_execute(node->node_for.code, 0);					if ( curr_exec_result < 0 ) {						break;					}					php_expr_eval(node->node_for.do_next, &cond_result);					php_expr_eval(node->node_for.cond, &cond_result);					cast_value_bool(&cond_result);				}				break;			case PHP_ST_FOREACH: {					PHP_VAR_NODE *elems = php_expr_eval_lvalue(node->node_foreach.elems);					if ( !elems || (elems->value.type != PHP_VAL_ARRAY) ) {						php_report_error(PHP_ERROR, "Argument of 'foreach' must be array");						break;					}					PHP_ARRAY_TYPE *array = (PHP_ARRAY_TYPE *)elems->value.ptr_val;					PHP_SCOPE_ITEM *i_key = node->node_foreach.i_key;					// keys in array are string values.					if ( i_key ) {						i_key->var->value.type = PHP_VAL_STRING;					}					PHP_SCOPE_ITEM *i_val = node->node_foreach.i_val;					array->current = array->sorted_keys.begin();					while ( array->current != array->sorted_keys.end() ) {						if ( i_key ) {							PHP_VALUE_NODE tmp_val;							tmp_val.type = PHP_VAL_STRING;							tmp_val.str_val = (char *)array->current->c_str();							value_value_assign(&i_key->var->value, &tmp_val);						}						PHP_VALUE_NODE *curr_value = &array->array[*array->current]->value;						value_value_assign(&i_val->var->value, curr_value);						curr_exec_result = php_execute(node->node_foreach.code, 0);						if ( i_key ) {							value_value_free(&i_key->var->value);						}						if ( node->node_foreach.byref ) {							value_value_assign(curr_value, &i_val->var->value);						}						value_value_free(&i_val->var->value);						if ( curr_exec_result < 0 ) {							break;						}						array->current++;					}				}				break;			case PHP_ST_SWITCH: {					PHP_SYN_NODE *cur_exec = 0;					php_expr_eval(node->node_switch.cond, &cond_result);					PHP_EXP_NODE *curr = node->node_switch.case_list;					while (curr) {						PHP_VALUE_NODE cur_value, cmp_result;						cur_value.type = cmp_result.type = PHP_VAL_NONE;						php_expr_eval(curr->exp_node->tree_node.left, &cur_value);						php_eval_compare(PHP_OP_EQ, &cur_value, &cond_result, &cmp_result);						if ( cmp_result.int_val ) {							cur_exec = (PHP_SYN_NODE *)curr->exp_node->tree_node.syn_right;							break;						}						curr = curr->next;					}					if ( cur_exec ) {						php_execute(cur_exec, result);					}				}				break;			default: ;		}		if ( curr_exec_result ) {			return curr_exec_result;		}		node = node->next_node;	}	// everything ok, keep going	return 0;}//// call it when something gone wrong//void php_report_error(PHP_MSG_TYPE err_type, const char *msg, ...){	//	// hope my error message will never be that big.	//	// security is ok, since _user_ errors are not reporting thru	// this function, but handled by scipt itself.	// However, badly written script MAY force user-supplied data to	// leak here and create stack overrun exploit. Be warned.	//	char msgbuf[1024];	const char *type_msg = 0;	switch(err_type) {		case PHP_MESAGE:			type_msg = "PHP:";			break;		case PHP_WARNING:			type_msg = "PHP Warning:";			break;		case PHP_ERROR:			type_msg = "PHP Error:";			break;		case PHP_INTERNAL_ERROR:			type_msg = "PHP Internal Error:";			break;	}		va_list args;	va_start(args, msg);	vsnprintf(msgbuf, sizeof(msgbuf), msg, args);	va_end(args);	printf("%s %s\n", type_msg, msgbuf);	assert(err_type != PHP_INTERNAL_ERROR);}int yyerror(char *s){	printf("ERROR in grammar %s after [%s] near line %d\n", s, yytext, yylineno);	return 0;}#ifdef PHP_STANDALONE_ENint main(int argc, char *argv[]){	const char *filename = ( argc == 2 ) ? argv[1] : "test.php";	CWriteStrBuffer buffer;		yydebug = 0;	CPhpFilter php_filter((CWebServerBase*)0, (CSession *)0,filename, &buffer);		int size = buffer.Length();	char *buf = new char [size+1];	buffer.CopyAll(buf);	printf("%s", buf);	delete [] buf;		return 0;}#endif// File_checked_for_headers

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -