static zend_object_handlers psi_object_handlers;
static zend_class_entry *psi_class_entry;
-void psi_error(int type, const char *msg, ...)
+void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...)
{
- char buf[0x1000];
va_list argv;
va_start(argv, msg);
- vslprintf(buf, 0x1000, msg, argv);
+ psi_verror(type, t?t->file:"Unknown", t?*t->line:0, msg, argv);
va_end(argv);
+}
+void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...)
+{
+ va_list argv;
- php_error(type, buf);
+ va_start(argv, msg);
+ psi_verror(type, fn, ln, msg, argv);
+ va_end(argv);
+}
+void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv)
+{
+ zend_error_cb(type, fn, ln, msg, argv);
}
size_t psi_t_alignment(token_t t)
zend_internal_arg_info *ai = &aip[impl->func->args->count];
ai->name = vararg->var->name;
+ ai->allow_null = 1;
ai->type_hint = psi_internal_type(vararg->type);
if (vararg->var->reference) {
ai->pass_by_reference = 1;
if (iarg->var->reference) {
ai->pass_by_reference = 1;
}
- if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) {
+ //if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) {
ai->allow_null = 1;
- }
+ //}
}
return aip;
void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val)
{
+ char *str;
decl_var *var = set->vars->vars[0];
token_t t = real_decl_type(var->arg->type)->type;
switch (t) {
- case PSI_T_VOID:
- case PSI_T_INT8:
- case PSI_T_UINT8:
+ case PSI_T_FLOAT:
+ RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval);
+ break;
+ case PSI_T_DOUBLE:
+ RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
+ break;
+ default:
if (!var->arg->var->pointer_level) {
RETVAL_STRINGL(&ret_val->cval, 1);
} else {
ret_val = deref_impl_val(ret_val, var);
- if (ret_val && ret_val->ptr) {
+ if (var->arg->var->array_size) {
+ str = (char *) ret_val;
+ } else {
+ str = ret_val->ptr;
+ }
+ if (str) {
if (set->num) {
- RETVAL_STRINGL(ret_val->ptr, psi_long_num_exp(set->num, set->outer.val));
+ zend_long n = psi_long_num_exp(set->num, set->outer.val);
+ RETVAL_STRINGL(str, n);
} else {
- RETVAL_STRING(ret_val->ptr);
+ RETVAL_STRING(str);
}
} else {
RETVAL_EMPTY_STRING();
}
}
return;
- case PSI_T_FLOAT:
- RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval);
- break;
- case PSI_T_DOUBLE:
- RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
- break;
- default:
- psi_to_int(return_value, set, ret_val);
- break;
}
convert_to_string(return_value);
}
static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp)
{
memset(tmp, 0, sizeof(*tmp));
- memcpy(tmp, ((void*) val->ptr) + size * i, size);
+ memcpy(tmp, ((void*) val) + size * i, size);
return tmp;
}
return mem;
}
+void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val)
+{
+ set->outer.set->func->handler(return_value, set, r_val);
+}
+
void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
{
size_t i;
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) {
+ if ((intptr_t) ret_val <= (intptr_t) 0) {
RETURN_NULL();
}
set_value *sub_set = set->inner[i];
decl_var *sub_var = sub_set->vars->vars[0];
- sub_set->outer.val = r_val;
+ sub_set->outer.val = ret_val;
if (sub_var->arg) {
impl_val *tmp = NULL, *val;
zval ztmp;
- val = deref_impl_val(struct_member_ref(sub_var->arg, ret_val, &tmp), sub_var);
+ val = struct_member_ref(sub_var->arg, ret_val, &tmp);
sub_set->func->handler(&ztmp, sub_set, val);
add_assoc_zval(return_value, sub_var->name, &ztmp);
}
return;
} else if (set->num) {
- /* to_array(arr_var, num_expr, to_int(*arr_var))
- */
+ /* to_array(arr_var, num_expr, to_int(*arr_var)) */
zval ele;
+ char *ptr;
zend_long i, n = psi_long_num_exp(set->num, set->outer.val);
+ size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
+ set_value *sub_set = set->inner[0];
+ sub_set->outer.val = set->outer.val;
for (i = 0; i < n; ++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);
+ ptr = (char *) ret_val->ptr + i * size;
+ sub_set->func->handler(&ele, sub_set, (void *) ptr);
add_next_index_zval(return_value, &ele);
}
} else {
- ZEND_ASSERT(0);
+ /* to_array(arr_var, to_int(*arr_var)) */
+ zval ele;
+ char *ptr = ret_val->ptr;
+ size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
+ set_value *sub_set = set->inner[0];
+
+ sub_set->outer.val = set->outer.val;
+ while (*(void **) ptr) {
+ sub_set->func->handler(&ele, sub_set, (void *) ptr);
+ add_next_index_zval(return_value, &ele);
+ ptr += size;
+ }
}
}
static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl)
{
size_t i;
- zval *zarg = ZEND_CALL_ARG(execute_data, 0);
impl_arg *iarg;
zend_error_handling zeh;
/* set up defaults */
for (i = 0; i < impl->func->args->count; ++i) {
- iarg = impl->func->args->args[i];
+ if (i >= EX_NUM_ARGS() && iarg->def) {
+ iarg = impl->func->args->args[i];
- if (i < EX_NUM_ARGS()) {
- } else if (iarg->def) {
switch (iarg->type->type) {
case PSI_T_BOOL:
iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
zend_long n = psi_long_num_exp(alloc->nmemb, NULL), s = psi_long_num_exp(alloc->size, NULL);
void *mem = safe_emalloc(n, s, sizeof(void *));
memset(mem, 0, n * s + sizeof(void *));
+#if 0
+ fprintf(stderr, "calloc: %p\n", mem);
+#endif
return mem;
}
case PSI_T_STRVAL:
if (iarg->type->type == PSI_T_STRING) {
if (iarg->val.zend.str) {
- arg_val->ptr = estrdup(iarg->val.zend.str->val);
+ arg_val->ptr = estrndup(iarg->val.zend.str->val, iarg->val.zend.str->len);
*to_free = arg_val->ptr;
} else {
arg_val->ptr = "";
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);
+ memcpy(arg_val, deref_impl_val(let->val->data.var->arg->let->ptr, let->val->data.var), sizeof(*arg_val));
+#if 0
+ fprintf(stderr, "LET TMP: %p -> %p\n",
+ let->val->data.var->arg->let->ptr,
+ arg_val->ptr);
+#endif
break;
case PSI_LET_NULL:
if (darg->var->array_size) {
static inline void psi_do_set(zval *return_value, set_value *set)
{
+ decl_arg *set_arg = set->vars->vars[0]->arg;
+
zval_dtor(return_value);
- set->func->handler(return_value, set, set->vars->vars[0]->arg->ptr);
+ set->func->handler(return_value, set, set_arg->let ? set_arg->let->ptr : set_arg->ptr);
}
static inline void psi_do_return(zval *return_value, return_stmt *ret)
}
}
+static inline void psi_clean_array_struct(decl_arg *darg) {
+ if (darg->let
+ && darg->let->val->kind == PSI_LET_FUNC
+ && darg->let->val->data.func->type == PSI_T_ARRVAL) {
+ decl_type *type = real_decl_type(darg->type);
+
+ if (type->type == PSI_T_STRUCT) {
+ void **ptr = (void **) ((char *) darg->mem + type->strct->size);
+
+ while (*ptr) {
+ efree(*ptr++);
+ }
+ }
+ }
+}
+
static inline void psi_do_clean(impl *impl)
{
size_t i;
decl_arg *darg = impl->decl->args->args[i];
if (darg->mem) {
- decl_type *type = real_decl_type(darg->type);
-
- if (type->type == PSI_T_STRUCT) {
- void **ptr = (void **) ((char *) darg->mem + type->strct->size);
-
- while (*ptr) {
- efree(*ptr++);
- }
- }
+ psi_clean_array_struct(darg);
efree(darg->mem);
darg->mem = NULL;
}
case PSI_T_NAME:
if (strct) {
ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
+ } else if (exp->u.dvar->arg->let) {
+ ref = exp->u.dvar->arg->let->ptr;
} else {
ref = exp->u.dvar->arg->ptr;
}
return FAILURE;
}
- PSI_ContextInit(&PSI_G(context), ops, psi_error);
+ PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper);
PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
if (psi_check_env("PSI_DUMP")) {