# define PSI_ENGINE "ffi"
#endif
+#include <ndbm.h>
+
ZEND_DECLARE_MODULE_GLOBALS(psi);
PHP_INI_BEGIN()
va_list argv;
va_start(argv, msg);
- psi_verror(type, t?t->file:"Unknown", t?*t->line:0, 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, ...)
return ((s - 1) | (a - 1)) + 1;
}
+size_t psi_offset_padding(size_t diff, size_t alignment)
+{
+ if (diff && diff <= ((diff - 1) | (alignment -1)) + 1) {
+ diff = 0;
+ }
+
+ return diff;
+}
+
int psi_internal_type(impl_type *type)
{
switch (type->type) {
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;
case PSI_T_DOUBLE:
RETVAL_DOUBLE(v->dval);
break;
+#ifdef HAVE_LONG_DOUBLE
+ case PSI_T_LONG_DOUBLE:
+ RETVAL_DOUBLE((double) v->ldval);
+ break;
+#endif
case PSI_T_INT8:
RETVAL_DOUBLE((double) v->i8);
break;
case PSI_T_DOUBLE:
RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
break;
+#ifdef HAVE_LONG_DOUBLE
+ case PSI_T_LONG_DOUBLE:
+ RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->ldval);
+ break;
+#endif
default:
if (!var->arg->var->pointer_level) {
RETVAL_STRINGL(&ret_val->cval, 1);
case PSI_T_DOUBLE:
mem->dval = zval_get_double(zv);
break;
+ case PSI_T_VOID:
case PSI_T_INT8:
case PSI_T_UINT8:
if (spec->var->pointer_level) {
return mem;
}
-static inline ZEND_RESULT_CODE psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free)
+static inline impl_val *psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free)
{
switch (let_func) {
case PSI_T_BOOLVAL:
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 = "";
if (PSI_T_PATHVAL == let_func) {
if (SUCCESS != php_check_open_basedir(arg_val->ptr)) {
efree(arg_val->ptr);
- return FAILURE;
+ return NULL;
}
}
break;
break;
case PSI_T_ARRVAL:
if (iarg->type->type == PSI_T_ARRAY) {
- arg_val->ptr = psi_array_to_struct(strct, HASH_OF(iarg->_zv));
- *to_free = arg_val->ptr;
+ arg_val = psi_array_to_struct(strct, HASH_OF(iarg->_zv));
+ *to_free = arg_val;
}
break;
case PSI_T_OBJVAL:
psi_object *obj;
if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_class_entry)) {
- return FAILURE;
+ return NULL;
}
obj = PSI_OBJ(iarg->_zv, NULL);
break;
EMPTY_SWITCH_DEFAULT_CASE();
}
- return SUCCESS;
+ return arg_val;
}
static inline void *psi_do_let(let_stmt *let)
case PSI_LET_FUNC:
iarg = let->val->data.func->arg;
- if (SUCCESS != psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem)) {
+ if (!(darg->ptr = psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem))) {
return NULL;
}
}
for (j = 0; j < f->vars->count; ++j) {
decl_var *dvar = f->vars->vars[j];
decl_arg *darg = dvar->arg;
+ impl_val *fval = darg->let ? darg->let->ptr : darg->ptr;
- f->decl->call.args[j] = &darg->val;
+ f->decl->call.args[j] = deref_impl_val(fval, dvar);
}
/* FIXME: check in validate_* that free functions return scalar */
}
}
+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;
+ if (impl->decl->func->ptr != &impl->decl->func->val) {
+ efree(impl->decl->func->ptr);
+ impl->decl->func->ptr = &impl->decl->func->val;
+ }
for (i = 0; i < impl->func->args->count; ++i ) {
impl_arg *iarg = impl->func->args->args[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;
}
+ darg->ptr = &darg->val;
}
if (impl->func->args->vararg.args) {
#define PRIfval "f"
#define PRIdval "lf"
+#define PRIldval "Lf"
#define PSI_CALC_OP(var) do { \
const char *fmt = "calc %" PRI##var ", %" PRI##var ": %" PRI##var "\n"; \
res->vres = PSI_CALC(v1->var1, v2->var2); \
if (!res->vres) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \
} while(0)
+
+#ifdef HAVE_LONG_DOUBLE
+#define PSI_CALC_NO_LD
+#define PSI_CALC_OP_LD PSI_CALC_OP(ldval)
+#define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval)
+#define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2)
+#else
+#define PSI_CALC_NO_LD abort()
+#define PSI_CALC_OP_LD PSI_CALC_NO_LD
+#define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD
+#define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD
+#endif
+
#define PSI_CALC_FN(op) int psi_calc_##op(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res) \
{ \
if (t1 == t2) { \
switch (t1) { \
case PSI_T_FLOAT: PSI_CALC_OP(fval); break; \
case PSI_T_DOUBLE: PSI_CALC_OP(dval); break; \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP_LD; break; \
case PSI_T_INT8: PSI_CALC_OP(i8); break; \
case PSI_T_UINT8: PSI_CALC_OP(u8); break; \
case PSI_T_INT16: PSI_CALC_OP(i16); break; \
return t1; \
} else if (t1 == PSI_T_DOUBLE) { \
switch (t2) { \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(dval); return t2; \
case PSI_T_FLOAT: PSI_CALC_OP2(dval, dval, fval); break; \
case PSI_T_INT8: PSI_CALC_OP2(dval, dval, i8); break; \
case PSI_T_UINT8: PSI_CALC_OP2(dval, dval, u8); break; \
return t1; \
} else if (t2 == PSI_T_DOUBLE) { \
switch (t1) { \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(dval); return t1; \
case PSI_T_FLOAT: PSI_CALC_OP2(dval, fval, dval); break; \
case PSI_T_INT8: PSI_CALC_OP2(dval, i8, dval); break; \
case PSI_T_UINT8: PSI_CALC_OP2(dval, u8, dval); break; \
EMPTY_SWITCH_DEFAULT_CASE(); \
} \
return t2; \
+ } else if (t1 == PSI_T_LONG_DOUBLE) { \
+ PSI_CALC_NO_LD; \
+ switch (t2) { \
+ case PSI_T_DOUBLE: PSI_CALC_OP2_LD1(dval); break; \
+ case PSI_T_FLOAT: PSI_CALC_OP2_LD1(fval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2_LD1(i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2_LD1(u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2_LD1(i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2_LD1(u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2_LD1(i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2_LD1(u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2_LD1(i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2_LD1(u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ return t1; \
+ } else if (t2 == PSI_T_LONG_DOUBLE) { \
+ PSI_CALC_NO_LD; \
+ switch (t1) { \
+ case PSI_T_DOUBLE: PSI_CALC_OP2_LD2(dval); break; \
+ case PSI_T_FLOAT: PSI_CALC_OP2_LD2(fval); break; \
+ case PSI_T_INT8: PSI_CALC_OP2_LD2(i8); break; \
+ case PSI_T_UINT8: PSI_CALC_OP2_LD2(u8); break; \
+ case PSI_T_INT16: PSI_CALC_OP2_LD2(i16); break; \
+ case PSI_T_UINT16: PSI_CALC_OP2_LD2(u16); break; \
+ case PSI_T_INT32: PSI_CALC_OP2_LD2(i32); break; \
+ case PSI_T_UINT32: PSI_CALC_OP2_LD2(u32); break; \
+ case PSI_T_INT64: PSI_CALC_OP2_LD2(i64); break; \
+ case PSI_T_UINT64: PSI_CALC_OP2_LD2(u64); break; \
+ EMPTY_SWITCH_DEFAULT_CASE(); \
+ } \
+ return t2; \
} else if (t1 == PSI_T_FLOAT) { \
switch (t2) { \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD2(fval); return t2; \
case PSI_T_DOUBLE: PSI_CALC_OP2(dval, fval, dval); return t2; \
case PSI_T_INT8: PSI_CALC_OP2(fval, fval, i8); break; \
case PSI_T_UINT8: PSI_CALC_OP2(fval, fval, u8); break; \
return t1; \
} else if (t2 == PSI_T_FLOAT) { \
switch (t1) { \
+ case PSI_T_LONG_DOUBLE: PSI_CALC_OP2_LD1(fval); return t1; \
case PSI_T_DOUBLE: PSI_CALC_OP2(dval, dval, fval); return t1; \
case PSI_T_INT8: PSI_CALC_OP2(fval, i8, fval); break; \
case PSI_T_UINT8: PSI_CALC_OP2(fval, u8, fval); break; \
for (i = 0; i < impl->decl->args->count; ++i) {
impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr;
}
+
+ if (!impl->decl->func->var->pointer_level) {
+ decl_type *real = real_decl_type(impl->decl->func->type);
+
+ switch (real->type) {
+ case PSI_T_STRUCT:
+ impl->decl->func->ptr = psi_array_to_struct(real->strct, NULL);
+ break;
+ }
+ }
}
static inline impl_vararg *psi_do_varargs(impl *impl) {
}
va->types[i] = vatype;
- psi_let_val(let_fn, vaarg, &va->values[i], NULL, &to_free);
+ /* FIXME: varargs with struct-by-value :) */
+ if (!psi_let_val(let_fn, vaarg, &va->values[i], NULL, &to_free)) {
+ return NULL;
+ }
if (to_free) {
if (!va->free_list) {