}
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;
}
}
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 */
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) {
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;
}
}
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) {
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) {
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))
*/
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;
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];
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);
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;
}
{
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;
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;
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;
}
}
- 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;
}
}
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;
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);
}
'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);}
#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
%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.
%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. {
--- /dev/null
+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);
+}
--- /dev/null
+--TEST--
+iconv
+--SKIPIF--
+<?php
+extension_loaded("psi") or die("skip - need ext/psi");
+function_exists("psi\\iconv_open") or die("skip - need iconv");
+?>
+--INI--
+psi.directory={PWD}/../../psi.d:{PWD}
+--FILE--
+===TEST===
+<?php
+
+$cd = psi\iconv_open("latin1", "utf8");
+$in = "ß";
+$rc = psi\iconv($cd, $in, $tr);
+var_dump($tr === "\xdf");
+var_dump($in === "");
+var_dump(psi\iconv_close($cd));
+
+?>
+===DONE===
+--EXPECT--
+===TEST===
+bool(true)
+bool(true)
+int(0)
+===DONE===
--- /dev/null
+--TEST--
+iconv abstraction
+--INI--
+psi.directory={PWD}/../../psi.d:{PWD}
+--SKIPIF--
+<?php
+extension_loaded("psi") or die("skip - need ext/psi");
+function_exists("psi\\iconv_open") or die("skip - need iconv");
+?>
+--FILE--
+===TEST===
+<?php
+
+class iconv_stream {
+ private $cd;
+
+ function __construct($from, $to) {
+ if (!$this->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===