From d59f10e81c33354ee1589fb10847b4611423de2e Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 22 Dec 2015 15:43:29 +0100 Subject: [PATCH] flush --- src/context.c | 171 ++++++++++++++++++++++++-------------- src/module.c | 163 +++++++++++++++--------------------- src/parser.h | 100 +++++++++++++++------- src/parser.re | 1 + src/parser_proc.h | 123 +++++++++++++-------------- src/parser_proc.y | 68 +++++++++------ tests/iconv/iconv.psi | 25 ++++++ tests/iconv/iconv001.phpt | 28 +++++++ tests/iconv/iconv002.phpt | 79 ++++++++++++++++++ 9 files changed, 484 insertions(+), 274 deletions(-) create mode 100644 tests/iconv/iconv.psi create mode 100644 tests/iconv/iconv001.phpt create mode 100644 tests/iconv/iconv002.phpt diff --git a/src/context.c b/src/context.c index 709c6b4..ef9cc40 100644 --- a/src/context.c +++ b/src/context.c @@ -543,8 +543,9 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg } for (i = 0; i < set->vars->count; ++i) { - if (!locate_decl_var_arg(set->vars->vars[i], ref_list, NULL)) { - data->error(PSI_WARNING, "Unknown variable '%s'", set->vars->vars[i]->name); + decl_var *svar = set->vars->vars[i]; + if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) { + data->error(PSI_WARNING, "Unknown variable '%s'", svar->name); return 0; } } @@ -671,15 +672,70 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { size_t i, j; /* we can have multiple let stmts */ + /* check that we have a decl arg for every let stmt */ for (i = 0; i < impl->stmts->let.count; ++i) { let_stmt *let = impl->stmts->let.list[i]; + decl_var *let_var; + int check = 0; - if (!locate_decl_var_arg(let->var, impl->decl->args, impl->decl->func)) { + if (let->val && let->val->kind == PSI_LET_TMP) { + let_var = let->val->data.var; + } else { + let_var = let->var; + } + + if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) { data->error(PSI_WARNING, "Unknown variable '%s' in `let` statement" - " of implementation '%s'", let->var->name, impl->func->name); + " of implementation '%s'", let_var->name, impl->func->name); return 0; } + + switch (let->val->kind) { + case PSI_LET_NULL: + break; + case PSI_LET_TMP: + /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */ + /* e.g. let foo = *bar; */ + let->var->pointer_level = let->val->data.var->pointer_level; + let->var->arg = init_decl_arg( + init_decl_type(real_decl_type(let->val->data.var->arg->type)->type, + real_decl_type(let->val->data.var->arg->type)->name), + init_decl_var(let->var->name, let->var->pointer_level, let->var->array_size)); + break; + case PSI_LET_NUMEXP: + if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.num)) { + return 0; + } + break; + case PSI_LET_CALLOC: + if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.alloc->nmemb)) { + return 0; + } + if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.alloc->size)) { + return 0; + } + break; + case PSI_LET_FUNC: + if (impl->func->args) { + for (j = 0; j < impl->func->args->count; ++j) { + impl_arg *iarg = impl->func->args->args[j]; + + if (!strcmp(let->val->data.func->var->name, iarg->var->name)) { + let->val->data.func->arg = iarg; + check = 1; + break; + } + } + } + if (!check) { + data->error(PSI_WARNING, "Unknown value '$%s' of `let` statement" + " for variable '%s' of implementation '%s'", + let->val->data.func->var->name, let->var->name, impl->func->name); + return 0; + } + break; + } } /* check that we have a let stmt for every decl arg */ @@ -704,42 +760,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { return 0; } } - /* check that the let_value references a known variable or NULL */ - for (i = 0; i < impl->stmts->let.count; ++i) { - let_stmt *let = impl->stmts->let.list[i]; - int check = 0; - if (let->val && let->val->func && let->val->func->alloc) { - if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->func->alloc->nmemb)) { - return 0; - } - if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->func->alloc->size)) { - return 0; - } - } - if (let->val && let->val->var) { - if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { - impl_arg *iarg = impl->func->args->args[j]; - - if (!strcmp(let->val->var->name, iarg->var->name)) { - let->arg = iarg; - check = 1; - break; - } - } - if (!check) { - data->error(PSI_WARNING, "Unknown value '$%s' of `let` statement" - " for variable '%s' of implementation '%s'", - let->val->var->name, let->var->name, impl->func->name); - return 0; - } - } - if (let->val && let->val->num) { - if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->num)) { - return 0; - } - } - } return 1; } static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { @@ -770,16 +791,35 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { decl_var *set_var = set->val->vars->vars[j]; check = 0; - if (impl->decl->args) for (k = 0; k < impl->decl->args->count; ++k) { - decl_arg *set_arg = impl->decl->args->args[k]; - - if (!strcmp(set_var->name, set_arg->var->name)) { - check = 1; - set_var->arg = set_arg; - if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) { - return 0; + if (impl->decl->args) { + for (k = 0; k < impl->decl->args->count; ++k) { + decl_arg *set_arg = impl->decl->args->args[k]; + + if (!strcmp(set_var->name, set_arg->var->name)) { + check = 1; + set_var->arg = set_arg; + if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) { + return 0; + } + break; + } + } + } + if (!check) { + for (k = 0; k < impl->stmts->let.count; ++k) { + let_stmt *let = impl->stmts->let.list[k]; + + /* check temp vars */ + if (let->val && let->val->kind == PSI_LET_TMP) { + if (!strcmp(set_var->name, let->var->name)) { + check = 1; + set_var->arg = let->var->arg; + if (!validate_set_value(data, set->val, 1, &set_var->arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) { + return 0; + } + break; + } } - break; } } @@ -1363,20 +1403,29 @@ void PSI_ContextDump(PSI_Context *C, int fd) dprintf(fd, "\tlet %s", let->var->name); if (let->val) { - dprintf(fd, " = %s", let->val->is_reference ? "&" : ""); - if (let->val->func) { - dprintf(fd, "%s(", let->val->func->name); - if (let->val->func->alloc) { - dump_num_exp(fd, let->val->func->alloc->nmemb); - dprintf(fd, ", "); - dump_num_exp(fd, let->val->func->alloc->size); - } else { - dprintf(fd, "$%s", let->val->var->name); - } - dprintf(fd, ");\n"); - } else { - dprintf(fd, "NULL;\n"); + dprintf(fd, " = %s", let->val->flags.one.is_reference ? "&" : ""); + switch (let->val->kind) { + case PSI_LET_NULL: + dprintf(fd, "NULL"); + break; + case PSI_LET_TMP: + dump_decl_var(fd, let->val->data.var); + break; + case PSI_LET_CALLOC: + dprintf(fd, "calloc("); + dump_num_exp(fd, let->val->data.alloc->nmemb); + dprintf(fd, ", "); + dump_num_exp(fd, let->val->data.alloc->size); + dprintf(fd, ")"); + break; + case PSI_LET_FUNC: + dprintf(fd, "%s($%s)", let->val->data.func->name, + let->val->data.func->var->name); + break; + + EMPTY_SWITCH_DEFAULT_CASE(); } + dprintf(fd, ";\n"); } } for (j = 0; j < impl->stmts->ret.count; ++j) { diff --git a/src/module.c b/src/module.c index 9d97a3e..bde40a4 100644 --- a/src/module.c +++ b/src/module.c @@ -373,6 +373,10 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) token_t t = real_decl_type(var->arg->type)->type; impl_val tmp, *ret_val = deref_impl_val(r_val, var); + if ((intptr_t) ret_val->ptr <= (intptr_t) 0) { + RETURN_NULL(); + } + array_init(return_value); if (t == PSI_T_STRUCT) { @@ -425,38 +429,6 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) add_next_index_zval(return_value, &ele); } return; - } else if (set->vars->count > 1) { - /* to_array(arr_var, cnt_var[, cnt_var...], to_int(*arr_var)) - * check for length in second var - * / - size_t count = 0; - zval ele; - - if (set->outer.set) { - / * struct *//* - for (i = 1; i < set->vars->count; ++i) { - impl_val *tmp = NULL, *cnt_val; - decl_var *cnt_var = set->vars->vars[i]; - - cnt_val = struct_member_ref(cnt_var->arg, set->outer.val, &tmp); - count += deref_impl_val(cnt_val, cnt_var)->lval; - - if (tmp) { - free(tmp); - } - } - } else { - ZEND_ASSERT(0); - } - - for (i = 0; i < count; ++i) { - size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); - impl_val *ptr = iterate(ret_val, size, i, &tmp); - - set->inner[0]->func->handler(&ele, set->inner[0], ptr); - add_next_index_zval(return_value, &ele); - } - */ } else if (set->num) { /* to_array(arr_var, num_expr, to_int(*arr_var)) */ @@ -481,7 +453,7 @@ void psi_to_object(zval *return_value, set_value *set, impl_val *r_val) impl_val *ret_val = deref_impl_val(r_val, var); psi_object *obj; - if (ret_val->ptr) { + if ((intptr_t) ret_val->ptr > (intptr_t) 0) { object_init_ex(return_value, psi_class_entry); obj = PSI_OBJ(return_value, NULL); obj->data = ret_val->ptr; @@ -507,39 +479,6 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i return rv; } - /* set up defaults */ - for (i = 0; i < impl->func->args->count; ++i) { - iarg = impl->func->args->args[i]; - - if (i < EX_NUM_ARGS()) { - iarg->_zv = ++zarg; - ZVAL_DEREF(iarg->_zv); -// if (iarg->var->reference) { -// zval_dtor(iarg->_zv); -// ZVAL_NULL(iarg->_zv); -// } - } - - if (iarg->def) { - switch (iarg->type->type) { - case PSI_T_BOOL: - iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; - break; - case PSI_T_INT: - iarg->val.zend.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); - break; - case PSI_T_FLOAT: - case PSI_T_DOUBLE: - iarg->val.dval = zend_strtod(iarg->def->text, NULL); - break; - case PSI_T_STRING: - /* FIXME */ - iarg->val.zend.str = zend_string_init(&iarg->def->text[1], strlen(iarg->def->text) - 2, 0); - break; - } - } - } - ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->count) nextarg: iarg = impl->func->args->args[_i]; @@ -547,25 +486,15 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i Z_PARAM_OPTIONAL; } if (PSI_T_BOOL == iarg->type->type) { - if (iarg->def) { - iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; - } Z_PARAM_BOOL(iarg->val.zend.bval); } else if (PSI_T_INT == iarg->type->type) { - if (iarg->def) { - iarg->val.zend.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); - } Z_PARAM_LONG(iarg->val.zend.lval); } else if (PSI_T_FLOAT == iarg->type->type || PSI_T_DOUBLE == iarg->type->type) { - if (iarg->def) { - iarg->val.dval = zend_strtod(iarg->def->text, NULL); - } Z_PARAM_DOUBLE(iarg->val.dval); } else if (PSI_T_STRING == iarg->type->type) { - zend_string *str = iarg->val.zend.str; Z_PARAM_STR_EX(iarg->val.zend.str, 1, iarg->var->reference); - if (str && str != iarg->val.zend.str) { - zend_string_release(str); + if (iarg->val.zend.str) { + zend_string_addref(iarg->val.zend.str); } } else if (PSI_T_ARRAY == iarg->type->type) { Z_PARAM_PROLOGUE(0); @@ -583,6 +512,33 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i return FAILURE ); + /* set up defaults */ + for (i = 0; i < impl->func->args->count; ++i) { + iarg = impl->func->args->args[i]; + + if (i < EX_NUM_ARGS()) { + iarg->_zv = ++zarg; + ZVAL_DEREF(iarg->_zv); + } else if (iarg->def) { + switch (iarg->type->type) { + case PSI_T_BOOL: + iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; + break; + case PSI_T_INT: + iarg->val.zend.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); + break; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + iarg->val.dval = zend_strtod(iarg->def->text, NULL); + break; + case PSI_T_STRING: + /* FIXME */ + iarg->val.zend.str = zend_string_init(&iarg->def->text[1], strlen(iarg->def->text) - 2, 0); + break; + } + } + } + zend_restore_error_handling(&zeh); return SUCCESS; } @@ -599,24 +555,31 @@ static inline void *psi_do_let(let_stmt *let) { decl_arg *darg = let->var->arg; impl_val *arg_val = darg->ptr; + impl_arg *iarg; - if (!let->val) { + switch (let->val ? let->val->kind : PSI_LET_NULL) { + case PSI_LET_TMP: + arg_val->ptr = deref_impl_val(let->val->data.var->arg->val.ptr, let->var); + break; + case PSI_LET_NULL: if (darg->var->array_size) { arg_val->ptr = ecalloc(darg->var->array_size, sizeof(*arg_val)); darg->mem = arg_val->ptr; } else { memset(arg_val, 0, sizeof(*arg_val)); } - } else if (let->val->num) { - arg_val->zend.lval = psi_long_num_exp(darg->let->val->num, NULL); - } else { - impl_arg *iarg = darg->let->arg; + break; + case PSI_LET_CALLOC: + arg_val->ptr = psi_do_calloc(let->val->data.alloc); + darg->mem = arg_val->ptr; + break; + case PSI_LET_NUMEXP: + arg_val->zend.lval = psi_long_num_exp(let->val->data.num, NULL); + break; + case PSI_LET_FUNC: + iarg = let->val->data.func->arg; - switch (let->val->func->type) { - case PSI_T_CALLOC: - arg_val->ptr = psi_do_calloc(let->val->func->alloc); - darg->mem = arg_val->ptr; - break; + switch (let->val->data.func->type) { case PSI_T_BOOLVAL: if (iarg->type->type == PSI_T_BOOL) { arg_val->cval = iarg->val.zend.bval; @@ -634,16 +597,19 @@ static inline void *psi_do_let(let_stmt *let) case PSI_T_PATHVAL: case PSI_T_STRVAL: if (iarg->type->type == PSI_T_STRING) { - arg_val->ptr = estrdup(iarg->val.zend.str->val); - darg->mem = arg_val->ptr; - zend_string_release(iarg->val.zend.str); + if (iarg->val.zend.str) { + arg_val->ptr = estrdup(iarg->val.zend.str->val); + darg->mem = arg_val->ptr; + } else { + arg_val->ptr = ""; + } } else { zend_string *zs = zval_get_string(iarg->_zv); arg_val->ptr = estrdup(zs->val); darg->mem = arg_val->ptr; zend_string_release(zs); } - if (PSI_T_PATHVAL == darg->let->val->func->type) { + if (PSI_T_PATHVAL == darg->let->val->data.func->type) { if (SUCCESS != php_check_open_basedir(arg_val->ptr)) { efree(arg_val->ptr); return NULL; @@ -652,8 +618,11 @@ static inline void *psi_do_let(let_stmt *let) break; case PSI_T_STRLEN: if (iarg->type->type == PSI_T_STRING) { - arg_val->lval = iarg->val.zend.str->len; - zend_string_release(iarg->val.zend.str); + if (iarg->val.zend.str) { + arg_val->lval = iarg->val.zend.str->len; + } else { + arg_val->lval = 0; + } } else { zend_string *zs = zval_get_string(iarg->_zv); arg_val->lval = zs->len; @@ -688,10 +657,10 @@ static inline void *psi_do_let(let_stmt *let) } } - if (darg->let->val && darg->let->val->is_reference) { - return darg->let->ptr = &darg->ptr; + if (let->val && let->val->flags.one.is_reference) { + return let->ptr = &darg->ptr; } else { - return darg->let->ptr = darg->ptr; + return let->ptr = darg->ptr; } } diff --git a/src/parser.h b/src/parser.h index 0bac3ef..796705d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -617,58 +617,98 @@ static inline void free_let_calloc(let_calloc *alloc) { typedef struct let_func { token_t type; char *name; - let_calloc *alloc; + impl_var *var; + impl_arg *arg; } let_func; -static inline let_func *init_let_func(token_t type, const char *name, let_calloc *alloc) { +static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) { let_func *func = calloc(1, sizeof(*func)); func->type = type; func->name = strdup(name); - func->alloc = alloc; + func->var = var; return func; } static inline void free_let_func(let_func *func) { - if (func->alloc) { - free_let_calloc(func->alloc); - } + free_impl_var(func->var); free(func->name); free(func); } -typedef struct let_value { - let_func *func; - impl_var *var; - num_exp *num; - unsigned is_reference:1; -} let_value; - -static inline let_value *init_let_value(let_func *func, impl_var *var, int is_reference) { - let_value *val = calloc(1, sizeof(*val)); - val->is_reference = is_reference; - val->func = func; - val->var = var; - return val; +#define PSI_LET_REFERENCE 0x1; +typedef struct let_val { + enum let_val_kind { + PSI_LET_NULL, + PSI_LET_NUMEXP, + PSI_LET_CALLOC, + PSI_LET_FUNC, + PSI_LET_TMP, + } kind; + union { + num_exp *num; + let_calloc *alloc; + let_func *func; + decl_var *var; + } data; + union { + struct { + unsigned is_reference:1; + } one; + unsigned all; + } flags; +} let_val; + +static inline let_val *init_let_val(enum let_val_kind kind, void *data) { + let_val *let = calloc(1, sizeof(*let)); + switch (let->kind = kind) { + case PSI_LET_NULL: + break; + case PSI_LET_NUMEXP: + let->data.num = data; + break; + case PSI_LET_CALLOC: + let->data.alloc = data; + break; + case PSI_LET_FUNC: + let->data.func = data; + break; + case PSI_LET_TMP: + let->data.var = data; + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + return let; } -static inline void free_let_value(let_value *val) { - if (val->func) { - free_let_func(val->func); - } - if (val->var) { - free_impl_var(val->var); +static inline void free_let_val(let_val *let) { + switch (let->kind) { + case PSI_LET_NULL: + break; + case PSI_LET_NUMEXP: + free_num_exp(let->data.num); + break; + case PSI_LET_CALLOC: + free_let_calloc(let->data.alloc); + break; + case PSI_LET_FUNC: + free_let_func(let->data.func); + break; + case PSI_LET_TMP: + free_decl_var(let->data.var); + break; + EMPTY_SWITCH_DEFAULT_CASE(); } - free(val); + free(let); } typedef struct let_stmt { decl_var *var; - let_value *val; - impl_arg *arg; + let_val *val; + void *ptr; } let_stmt; -static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) { +static inline let_stmt *init_let_stmt(decl_var *var, let_val *val) { let_stmt *let = calloc(1, sizeof(*let)); let->var = var; let->val = val; @@ -678,7 +718,7 @@ static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) { static inline void free_let_stmt(let_stmt *stmt) { free_decl_var(stmt->var); if (stmt->val) { - free_let_value(stmt->val); + free_let_val(stmt->val); } free(stmt); } diff --git a/src/parser.re b/src/parser.re index d5a0f8e..affe901 100644 --- a/src/parser.re +++ b/src/parser.re @@ -216,6 +216,7 @@ token_t PSI_ParserScan(PSI_Parser *P) 'SET' {RETURN(PSI_T_SET);} 'RETURN' {RETURN(PSI_T_RETURN);} 'FREE' {RETURN(PSI_T_FREE);} + 'TEMP' {RETURN(PSI_T_TEMP);} 'STRLEN' {RETURN(PSI_T_STRLEN);} 'STRVAL' {RETURN(PSI_T_STRVAL);} 'PATHVAL' {RETURN(PSI_T_PATHVAL);} diff --git a/src/parser_proc.h b/src/parser_proc.h index 615581d..64cfe82 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -3,64 +3,65 @@ #define PSI_T_MINUS 3 #define PSI_T_SLASH 4 #define PSI_T_ASTERISK 5 -#define PSI_T_FREE 6 -#define PSI_T_SET 7 -#define PSI_T_LET 8 -#define PSI_T_RETURN 9 -#define PSI_T_LIB 10 -#define PSI_T_INT 11 -#define PSI_T_UNSIGNED 12 -#define PSI_T_EOF 13 -#define PSI_T_QUOTED_STRING 14 -#define PSI_T_EOS 15 -#define PSI_T_STRUCT 16 -#define PSI_T_LBRACE 17 -#define PSI_T_RBRACE 18 -#define PSI_T_COLON 19 -#define PSI_T_LPAREN 20 -#define PSI_T_NUMBER 21 -#define PSI_T_RPAREN 22 -#define PSI_T_BOOL 23 -#define PSI_T_FLOAT 24 -#define PSI_T_STRING 25 -#define PSI_T_CONST 26 -#define PSI_T_NSNAME 27 -#define PSI_T_EQUALS 28 -#define PSI_T_TYPEDEF 29 -#define PSI_T_VOID 30 -#define PSI_T_LBRACKET 31 -#define PSI_T_RBRACKET 32 -#define PSI_T_COMMA 33 -#define PSI_T_DOUBLE 34 -#define PSI_T_INT8 35 -#define PSI_T_UINT8 36 -#define PSI_T_INT16 37 -#define PSI_T_UINT16 38 -#define PSI_T_INT32 39 -#define PSI_T_UINT32 40 -#define PSI_T_INT64 41 -#define PSI_T_UINT64 42 -#define PSI_T_FUNCTION 43 -#define PSI_T_AMPERSAND 44 -#define PSI_T_NULL 45 -#define PSI_T_TRUE 46 -#define PSI_T_FALSE 47 -#define PSI_T_DOLLAR 48 -#define PSI_T_CALLOC 49 -#define PSI_T_OBJVAL 50 -#define PSI_T_ARRVAL 51 -#define PSI_T_PATHVAL 52 -#define PSI_T_STRLEN 53 -#define PSI_T_STRVAL 54 -#define PSI_T_FLOATVAL 55 -#define PSI_T_INTVAL 56 -#define PSI_T_BOOLVAL 57 -#define PSI_T_TO_OBJECT 58 -#define PSI_T_TO_ARRAY 59 -#define PSI_T_TO_STRING 60 -#define PSI_T_TO_INT 61 -#define PSI_T_TO_FLOAT 62 -#define PSI_T_TO_BOOL 63 -#define PSI_T_MIXED 64 -#define PSI_T_ARRAY 65 -#define PSI_T_OBJECT 66 +#define PSI_T_TEMP 6 +#define PSI_T_FREE 7 +#define PSI_T_SET 8 +#define PSI_T_LET 9 +#define PSI_T_RETURN 10 +#define PSI_T_LIB 11 +#define PSI_T_INT 12 +#define PSI_T_UNSIGNED 13 +#define PSI_T_EOF 14 +#define PSI_T_QUOTED_STRING 15 +#define PSI_T_EOS 16 +#define PSI_T_STRUCT 17 +#define PSI_T_LBRACE 18 +#define PSI_T_RBRACE 19 +#define PSI_T_COLON 20 +#define PSI_T_LPAREN 21 +#define PSI_T_NUMBER 22 +#define PSI_T_RPAREN 23 +#define PSI_T_BOOL 24 +#define PSI_T_FLOAT 25 +#define PSI_T_STRING 26 +#define PSI_T_CONST 27 +#define PSI_T_NSNAME 28 +#define PSI_T_EQUALS 29 +#define PSI_T_TYPEDEF 30 +#define PSI_T_VOID 31 +#define PSI_T_LBRACKET 32 +#define PSI_T_RBRACKET 33 +#define PSI_T_COMMA 34 +#define PSI_T_DOUBLE 35 +#define PSI_T_INT8 36 +#define PSI_T_UINT8 37 +#define PSI_T_INT16 38 +#define PSI_T_UINT16 39 +#define PSI_T_INT32 40 +#define PSI_T_UINT32 41 +#define PSI_T_INT64 42 +#define PSI_T_UINT64 43 +#define PSI_T_FUNCTION 44 +#define PSI_T_AMPERSAND 45 +#define PSI_T_NULL 46 +#define PSI_T_TRUE 47 +#define PSI_T_FALSE 48 +#define PSI_T_DOLLAR 49 +#define PSI_T_CALLOC 50 +#define PSI_T_OBJVAL 51 +#define PSI_T_ARRVAL 52 +#define PSI_T_PATHVAL 53 +#define PSI_T_STRLEN 54 +#define PSI_T_STRVAL 55 +#define PSI_T_FLOATVAL 56 +#define PSI_T_INTVAL 57 +#define PSI_T_BOOLVAL 58 +#define PSI_T_TO_OBJECT 59 +#define PSI_T_TO_ARRAY 60 +#define PSI_T_TO_STRING 61 +#define PSI_T_TO_INT 62 +#define PSI_T_TO_FLOAT 63 +#define PSI_T_TO_BOOL 64 +#define PSI_T_MIXED 65 +#define PSI_T_ARRAY 66 +#define PSI_T_OBJECT 67 diff --git a/src/parser_proc.y b/src/parser_proc.y index 06e4be5..c5eecba 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -25,7 +25,7 @@ %nonassoc NAME. %left PLUS MINUS. %left SLASH ASTERISK. -%fallback NAME FREE SET LET RETURN LIB INT UNSIGNED. +%fallback NAME TEMP FREE SET LET RETURN LIB INT UNSIGNED. file ::= blocks. @@ -370,46 +370,64 @@ num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). { %type let_stmt {let_stmt*} %destructor let_stmt {free_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, init_let_val(PSI_LET_NULL, NULL)); +}/* +let_stmt(let) ::= LET decl_var(var) EQUALS let_val(val) EOS. { + let = init_let_stmt(var, val); +}*/ +let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) let_val(val) EOS. { + val->flags.one.is_reference = r ? 1 : 0; let = init_let_stmt(var, val); } -let_stmt(let) ::= decl_arg(arg) EQUALS decl_var(var_) EOS. { - let = init_let_stmt(arg->var, NULL); +let_stmt(let) ::= TEMP decl_var(var) EQUALS decl_var(val) EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_TMP, val)); } -%type let_value {let_value*} -%destructor let_value {free_let_value($$);} -let_value(val) ::= reference(r) CALLOC(F) LPAREN let_calloc(alloc) RPAREN. { - val = init_let_value(init_let_func(F->type, F->text, alloc), NULL, r); - free(F); +%type let_val {let_val*} +%destructor let_val {free_let_val($$);} +let_val(val) ::= NULL. { + val = init_let_val(PSI_LET_NULL, NULL); +} +let_val(val) ::= num_exp(exp). { + val = init_let_val(PSI_LET_NUMEXP, exp); +} +let_val(val) ::= CALLOC LPAREN let_calloc(alloc) RPAREN. { + val = init_let_val(PSI_LET_CALLOC, alloc); +} +let_val(val) ::= let_func(func). { + val = init_let_val(PSI_LET_FUNC, func); +} +/* +let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) NULL EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_NULL, NULL, r?PSI_LET_REFERENCE:0)); +} +let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) num_exp(exp) EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_NUMEXP, exp, r?PSI_LET_REFERENCE:0)); +} +let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) CALLOC LPAREN let_calloc(alloc) RPAREN EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_CALLOC, alloc, r?PSI_LET_REFERENCE:0)); } +let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) let_func(func) EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_FUNC, func, r?PSI_LET_REFERENCE:0)); +} +let_stmt(let) ::= LET decl_var(var) EQUALS decl_var(val) EOS. { + let = init_let_stmt(var, init_let_val(PSI_LET_VAR, val, 0)); +} +*/ %type let_calloc {let_calloc*} %destructor let_calloc {free_let_calloc($$);} let_calloc(alloc) ::= num_exp(nmemb) COMMA num_exp(size). { alloc = init_let_calloc(nmemb, size); } - -let_value(val) ::= reference(r) num_exp(exp). { - val = init_let_value(NULL, NULL, r); - val->num = exp; -} -let_value(val) ::= reference(r) let_func(func) LPAREN impl_var(var) RPAREN. { - val = init_let_value(func, var, r); -} -let_value(val) ::= reference(r) NULL. { - val = init_let_value(NULL, NULL, r); -} - %token_class let_func_token OBJVAL ARRVAL PATHVAL STRLEN STRVAL FLOATVAL INTVAL BOOLVAL. %type let_func {let_func*} %destructor let_func {free_let_func($$);} -let_func(func) ::= let_func_token(T). { - func = init_let_func(T->type, T->text, NULL); +let_func(func) ::= let_func_token(T) LPAREN impl_var(var) RPAREN. { + func = init_let_func(T->type, T->text, var); free(T); } + %type set_stmt {set_stmt*} %destructor set_stmt {free_set_stmt($$);} set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. { diff --git a/tests/iconv/iconv.psi b/tests/iconv/iconv.psi new file mode 100644 index 0000000..e414dc0 --- /dev/null +++ b/tests/iconv/iconv.psi @@ -0,0 +1,25 @@ +extern void *iconv_open(char *tocode, char *fromcode); +function psi\iconv_open(string $to, string $from) : object { + let tocode = strval($to); + let fromcode = strval($from); + return to_object(iconv_open); +} + +extern size_t iconv (void *cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); +function psi\iconv(object $iconv, string &$inbuf, string &$outbuf) : int { + let cd = objval($iconv); + let inbuf = &strval($inbuf); + let inbytesleft = &strlen($inbuf); + let outbytesleft = &8192; + let outbuf = &calloc(1, 8192); + temp result = *outbuf; + return to_int(iconv); + set $inbuf = to_string(*inbuf, *inbytesleft); + set $outbuf = to_string(result, 8192 - *outbytesleft); +} + +extern int iconv_close(void *cd); +function psi\iconv_close(object $iconv) : int { + let cd = objval($iconv); + return to_int(iconv_close); +} diff --git a/tests/iconv/iconv001.phpt b/tests/iconv/iconv001.phpt new file mode 100644 index 0000000..6227c2a --- /dev/null +++ b/tests/iconv/iconv001.phpt @@ -0,0 +1,28 @@ +--TEST-- +iconv +--SKIPIF-- + +--INI-- +psi.directory={PWD}/../../psi.d:{PWD} +--FILE-- +===TEST=== + +===DONE=== +--EXPECT-- +===TEST=== +bool(true) +bool(true) +int(0) +===DONE=== diff --git a/tests/iconv/iconv002.phpt b/tests/iconv/iconv002.phpt new file mode 100644 index 0000000..16095b5 --- /dev/null +++ b/tests/iconv/iconv002.phpt @@ -0,0 +1,79 @@ +--TEST-- +iconv abstraction +--INI-- +psi.directory={PWD}/../../psi.d:{PWD} +--SKIPIF-- + +--FILE-- +===TEST=== +cd = psi\iconv_open($to, $from)) { + throw new Exception(psi\strerror(psi\errno())); + } + } + + function __destruct() { + psi\iconv_close($this->cd); + } + + function update(string $data) : string { + if (0 > psi\iconv($this->cd, $data, $result)) { + throw new Exception(psi\strerror(psi\errno())); + } + return $result; + } +} + +$ic = new iconv_stream("utf8", "latin1"); + +foreach (["föö", "bää", "baßß"] as $str) { + var_dump(array_map("ord", str_split($ic->update($str)))); +} + +$bc = new iconv_stream("latin1", "utf8"); +foreach (["föö", "bää", "baßß"] as $str) { + var_dump($bc->update($ic->update($str))); +} + +?> +===DONE=== +--EXPECT-- +===TEST=== +array(3) { + [0]=> + int(102) + [1]=> + int(246) + [2]=> + int(246) +} +array(3) { + [0]=> + int(98) + [1]=> + int(228) + [2]=> + int(228) +} +array(4) { + [0]=> + int(98) + [1]=> + int(97) + [2]=> + int(223) + [3]=> + int(223) +} +string(5) "föö" +string(5) "bää" +string(6) "baßß" +===DONE=== -- 2.30.2