From: Michael Wallner Date: Thu, 22 Oct 2015 18:15:52 +0000 (+0200) Subject: flush X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=9f381458672347c0f303dc3b309dc299f998f4f6;hp=f6b2422d4a9cb0424412a4077241cfd5bcb9ebeb flush --- diff --git a/php_psi.h b/php_psi.h index 3e582d0..0889801 100644 --- a/php_psi.h +++ b/php_psi.h @@ -23,6 +23,7 @@ extern zend_module_entry psi_module_entry; #include "parser.h" void psi_error(int type, const char *msg, ...); +size_t psi_t_size(token_t t); int psi_internal_type(impl_type *type); zend_internal_arg_info *psi_internal_arginfo(impl *impl); size_t psi_num_min_args(impl *impl); diff --git a/src/libffi.c b/src/libffi.c index eb5b2b5..4963fc5 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -216,7 +216,8 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) decl_arg *darg = data->impl->decl->args->args[i]; arg_ptr[i] = psi_do_let(darg); - arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i]; + arg_prm[i] = (darg->let->val && darg->let->val->is_reference) + ? &arg_ptr[i] : arg_ptr[i]; darg->let->ptr = arg_ptr[i]; } diff --git a/src/module.c b/src/module.c index 57fe9d6..4d6e5c9 100644 --- a/src/module.c +++ b/src/module.c @@ -142,6 +142,85 @@ void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value) } } +size_t psi_t_size(token_t t) +{ + size_t size; + + switch (t) { + case PSI_T_CHAR: + size = sizeof(char); + break; + case PSI_T_SINT8: + case PSI_T_UINT8: + size = 1; + break; + case PSI_T_SHORT: + size = sizeof(short); + break; + case PSI_T_SINT16: + case PSI_T_UINT16: + size = 2; + break; + case PSI_T_INT: + size = sizeof(int); + break; + case PSI_T_SINT32: + case PSI_T_UINT32: + size = 4; + break; + case PSI_T_LONG: + size = sizeof(long); + break; + case PSI_T_SINT64: + case PSI_T_UINT64: + size = 8; + break; + case PSI_T_FLOAT: + size = sizeof(float); + break; + case PSI_T_DOUBLE: + size = sizeof(double); + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + return size; +} + +static impl_val *iterate(impl_val *val, token_t t, unsigned i, impl_val *tmp) +{ + size_t size = psi_t_size(t); + + memset(tmp, 0, sizeof(*tmp)); + memcpy(tmp, val->ptr + size * i, size); + return tmp; +} + +void psi_to_array(impl_val *ret_val, decl_arg *func, zval *return_value) +{ + zval ele; + unsigned i; + impl_val tmp; + token_t t = real_decl_type(func->type)->type; + + array_init(return_value); + ret_val = deref_impl_val(0, ret_val, func); + for (i = 0; i < func->var->array_size; ++i) { + impl_val *ptr = iterate(ret_val, t, i, &tmp); + + switch (t) { + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + ZVAL_DOUBLE(&ele, ptr->dval); + break; + default: + ZVAL_LONG(&ele, ptr->lval); + break; + } + + add_next_index_zval(return_value, &ele); + } +} + ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) { impl_arg *iarg; @@ -184,6 +263,9 @@ ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) } else if (iarg->def) { iarg->val.str = zend_string_init(str.val, str.len, 0); } + } else if (PSI_T_ARRAY == iarg->type->type) { + /* handled as _zv in let or set */ + Z_PARAM_PROLOGUE(0); } else { error_code = ZPP_ERROR_FAILURE; break; @@ -203,8 +285,16 @@ impl_val *psi_do_let(decl_arg *darg) impl_arg *iarg = darg->let->arg; if (!iarg) { - /* let foo = NULL */ - memset(arg_val, 0, sizeof(*arg_val)); + /* + * let foo = NULL; + * let foo; + */ + if (darg->var->array_size) { + arg_val->ptr = ecalloc(darg->var->array_size, sizeof(*arg_val)); + darg->let->mem = arg_val->ptr; + } else { + memset(arg_val, 0, sizeof(*arg_val)); + } return arg_val; } switch (darg->let->val->func->type) { @@ -244,6 +334,10 @@ impl_val *psi_do_let(decl_arg *darg) zend_string_release(zs); } break; + case PSI_T_CALLOC: + arg_val->ptr = calloc(1, darg->let->val->func->size); + darg->let->mem = arg_val->ptr; + break; EMPTY_SWITCH_DEFAULT_CASE(); } @@ -261,6 +355,9 @@ void psi_do_set(zval *return_value, set_func *func, decl_vars *vars) case PSI_T_TO_STRING: psi_to_string(val, vars->vars[0]->arg, return_value); break; + case PSI_T_TO_ARRAY: + psi_to_array(val, vars->vars[0]->arg, return_value); + break; EMPTY_SWITCH_DEFAULT_CASE(); } } diff --git a/src/parser.h b/src/parser.h index 4e5e064..fe3ff8e 100644 --- a/src/parser.h +++ b/src/parser.h @@ -405,12 +405,14 @@ static inline void free_impl_func(impl_func *f) { typedef struct let_func { token_t type; char *name; + size_t size; } let_func; -static inline let_func *init_let_func(token_t type, char *name) { +static inline let_func *init_let_func(token_t type, char *name, size_t size) { let_func *func = malloc(sizeof(*func)); func->type = type; - func->name = (char *) strdup((const char *) name); + func->name = strdup(name); + func->size = size; return func; } diff --git a/src/parser.re b/src/parser.re index f1fb9b5..9cd39fa 100644 --- a/src/parser.re +++ b/src/parser.re @@ -212,6 +212,8 @@ token_t PSI_ParserScan(PSI_Parser *P) INTVAL = 'intval'; FLOATVAL = 'floatval'; BOOLVAL = 'boolval'; + CALLOC = 'calloc'; + TO_ARRAY = 'to_array'; TO_STRING = 'to_string'; TO_INT = 'to_int'; TO_FLOAT = 'to_float'; @@ -269,6 +271,8 @@ token_t PSI_ParserScan(PSI_Parser *P) INTVAL {RETURN(PSI_T_INTVAL);} FLOATVAL {RETURN(PSI_T_FLOATVAL);} BOOLVAL {RETURN(PSI_T_BOOLVAL);} + CALLOC {RETURN(PSI_T_CALLOC);} + TO_ARRAY {RETURN(PSI_T_TO_ARRAY);} TO_STRING {RETURN(PSI_T_TO_STRING);} TO_INT {RETURN(PSI_T_TO_INT);} TO_FLOAT {RETURN(PSI_T_TO_FLOAT);} diff --git a/src/parser_proc.h b/src/parser_proc.h index b6d8c28..492a681 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -41,18 +41,20 @@ #define PSI_T_FALSE 41 #define PSI_T_DOLLAR 42 #define PSI_T_LET 43 -#define PSI_T_STRLEN 44 -#define PSI_T_STRVAL 45 -#define PSI_T_INTVAL 46 -#define PSI_T_FLOATVAL 47 -#define PSI_T_BOOLVAL 48 -#define PSI_T_SET 49 -#define PSI_T_TO_STRING 50 -#define PSI_T_TO_INT 51 -#define PSI_T_TO_FLOAT 52 -#define PSI_T_TO_BOOL 53 -#define PSI_T_RETURN 54 -#define PSI_T_FREE 55 -#define PSI_T_MIXED 56 -#define PSI_T_ARRAY 57 -#define PSI_T_POINTER 58 +#define PSI_T_CALLOC 44 +#define PSI_T_STRLEN 45 +#define PSI_T_STRVAL 46 +#define PSI_T_INTVAL 47 +#define PSI_T_FLOATVAL 48 +#define PSI_T_BOOLVAL 49 +#define PSI_T_SET 50 +#define PSI_T_TO_ARRAY 51 +#define PSI_T_TO_STRING 52 +#define PSI_T_TO_INT 53 +#define PSI_T_TO_FLOAT 54 +#define PSI_T_TO_BOOL 55 +#define PSI_T_RETURN 56 +#define PSI_T_FREE 57 +#define PSI_T_MIXED 58 +#define PSI_T_ARRAY 59 +#define PSI_T_POINTER 60 diff --git a/src/parser_proc.y b/src/parser_proc.y index 3bdcc22..fb7f53b 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -291,11 +291,24 @@ impl_stmt(stmt) ::= free_stmt(free). { } %type let_stmt {let_stmt*} +let_stmt(let) ::= LET decl_var(var) EOS. { + let = init_let_stmt(var, NULL); +} let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. { let = init_let_stmt(var, val); } %type let_value {let_value*} +let_value(val) ::= CALLOC(F) LPAREN NUMBER(N) COMMA decl_type(t) RPAREN. { + val = init_let_value( + init_let_func(F->type, F->text, + atol(N->text) * psi_t_size(real_decl_type(t)->type) + ), NULL, 0 + ); + free_decl_type(t); + free(F); + free(N); +} let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. { val = init_let_value(func, var, 0); } @@ -311,23 +324,23 @@ let_value(val) ::= NULL. { %type let_func {let_func*} let_func(func) ::= STRLEN(T). { - func = init_let_func(T->type, T->text); + func = init_let_func(T->type, T->text, 0); free(T); } let_func(func) ::= STRVAL(T). { - func = init_let_func(T->type, T->text); + func = init_let_func(T->type, T->text, 0); free(T); } let_func(func) ::= INTVAL(T). { - func = init_let_func(T->type, T->text); + func = init_let_func(T->type, T->text, 0); free(T); } let_func(func) ::= FLOATVAL(T). { - func = init_let_func(T->type, T->text); + func = init_let_func(T->type, T->text, 0); free(T); } let_func(func) ::= BOOLVAL(T). { - func = init_let_func(T->type, T->text); + func = init_let_func(T->type, T->text, 0); free(T); } @@ -342,6 +355,10 @@ set_value(val) ::= set_func(func) LPAREN decl_vars(vars) RPAREN. { } %type set_func {set_func*} +set_func(func) ::= TO_ARRAY(T). { + func = init_set_func(T->type, T->text); + free(T); +} set_func(func) ::= TO_STRING(T). { func = init_set_func(T->type, T->text); free(T); diff --git a/src/validator.c b/src/validator.c index 7222a57..6bfd4e4 100644 --- a/src/validator.c +++ b/src/validator.c @@ -282,7 +282,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * let_stmt *let = stmts->let.list[i]; int check = 0; - if (let->val->var) { + if (let->val && let->val->var) { for (j = 0; j < impl->func->args->count; ++j) { impl_arg *iarg = impl->func->args->args[j]; diff --git a/tests/pipe/pipe.psi b/tests/pipe/pipe.psi new file mode 100644 index 0000000..5bc3cd6 --- /dev/null +++ b/tests/pipe/pipe.psi @@ -0,0 +1,8 @@ + +extern int pipe(int fds[2]); + +function \pipe(array &$fds = null) : int { + return to_int(pipe); + let fds = calloc(2, int); + set $fds = to_array(fds); +} diff --git a/tests/pipe/pipe001.phpt b/tests/pipe/pipe001.phpt new file mode 100644 index 0000000..a6461c4 --- /dev/null +++ b/tests/pipe/pipe001.phpt @@ -0,0 +1,27 @@ +--TEST-- +pipe +--SKIPIF-- + +--INI-- +psi.directory={PWD} +--FILE-- +===TEST=== + +===DONE=== +--EXPECT-- +===TEST=== +int(0) +string(13) "Hello World! +" +===DONE=== \ No newline at end of file