struct psi_plist *check_enums = src->enums;
unsigned flags = dst->flags;
unsigned errors = src->errors;
+ struct psi_validate_stack type_stack;
/* fail early if library is not found */
if (!psi_decl_file_validate(dst, src, &dlopened)) {
return false;
}
+ psi_validate_stack_ctor(&type_stack);
+
dst->flags |= PSI_SILENT;
while (check_count) {
while (psi_plist_get(check_types, i++, &def)) {
*dst->last_error = 0;
+ dst->types = psi_plist_add(dst->types, &def);
PSI_DEBUG_PRINT(dst, "PSI: validate typedef %s ", def->var->name);
- if (psi_decl_arg_validate_typedef(PSI_DATA(dst), def)) {
+ if (psi_decl_arg_validate_typedef(PSI_DATA(dst), def, &type_stack)) {
PSI_DEBUG_PRINT(dst, "%s\n", "✔");
- dst->types = psi_plist_add(dst->types, &def);
} else {
PSI_DEBUG_PRINT(dst, "%s (%s)\n", "✘", dst->last_error);
recheck_types = psi_plist_add(recheck_types, &def);
+ psi_plist_pop(dst->types, NULL);
}
}
}
*dst->last_error = 0;
dst->structs = psi_plist_add(dst->structs, &str);
PSI_DEBUG_PRINT(dst, "PSI: validate struct %s ", str->name);
- if (psi_decl_struct_validate(PSI_DATA(dst), str)) {
+ if (psi_decl_struct_validate(PSI_DATA(dst), str, &type_stack)) {
PSI_DEBUG_PRINT(dst, "%s ::(%zu, %zu)\n", "✔", str->align, str->size);
} else {
PSI_DEBUG_PRINT(dst, "%s (%s)\n", "✘", dst->last_error);
*dst->last_error = 0;
dst->unions = psi_plist_add(dst->unions, &unn);
PSI_DEBUG_PRINT(dst, "PSI: validate union %s ", unn->name);
- if (psi_decl_union_validate(PSI_DATA(dst), unn)) {
+ if (psi_decl_union_validate(PSI_DATA(dst), unn, &type_stack)) {
PSI_DEBUG_PRINT(dst, "%s ::(%zu, %zu)\n", "✔", unn->align, unn->size);
} else {
while (psi_plist_get(src->decls, i++, &decl)) {
*dst->last_error = 0;
PSI_DEBUG_PRINT(dst, "PSI: validate decl %s ", decl->func->var->name);
- if (psi_decl_validate(PSI_DATA(dst), decl, dlopened)) {
+ if (psi_decl_validate(PSI_DATA(dst), decl, dlopened, &type_stack)) {
PSI_DEBUG_PRINT(dst, "%s\n", "✔");
dst->decls = psi_plist_add(dst->decls, &decl);
} else {
}
}
+ psi_validate_stack_dtor(&type_stack);
+
return true;
}
void psi_data_dtor(struct psi_data *data);
void psi_data_dump(int fd, struct psi_data *data);
+struct psi_validate_stack {
+ HashTable types;
+ HashTable structs;
+ HashTable unions;
+};
+
+static inline void psi_validate_stack_ctor(struct psi_validate_stack *stack)
+{
+ zend_hash_init(&stack->types, 0, NULL, NULL, 0);
+ zend_hash_init(&stack->structs, 0, NULL, NULL, 0);
+ zend_hash_init(&stack->unions, 0, NULL, NULL, 0);
+}
+
+static inline void psi_validate_stack_dtor(struct psi_validate_stack *stack)
+{
+ zend_hash_destroy(&stack->types);
+ zend_hash_destroy(&stack->structs);
+ zend_hash_destroy(&stack->unions);
+}
+
+#define psi_validate_stack_has_type(s, t) \
+ ((s) ? zend_hash_str_exists(&(s)->types, (t), strlen(t)) : false)
+#define psi_validate_stack_has_struct(s, t) \
+ ((s) ? zend_hash_str_exists(&(s)->structs, (t), strlen(t)) : false)
+#define psi_validate_stack_has_union(s, t) \
+ ((s) ? zend_hash_str_exists(&(s)->unions, (t), strlen(t)) : false)
+
+#define psi_validate_stack_add_type(s, t, p) \
+ do { if (s) zend_hash_str_add_ptr(&(s)->types, (t), strlen(t), (p)); } while(0)
+#define psi_validate_stack_add_struct(s, t, p) \
+ do { if (s) zend_hash_str_add_ptr(&(s)->structs, (t), strlen(t), (p)); } while(0)
+#define psi_validate_stack_add_union(s, t, p) \
+ do { if (s) zend_hash_str_add_ptr(&(s)->unions, (t), strlen(t), (p)); } while(0)
+
+#define psi_validate_stack_get_type(s, t) \
+ ((s) ? zend_hash_str_find_ptr(&(s)->types, (t), strlen(t)) : NULL)
+#define psi_validate_stack_get_struct(s, t) \
+ ((s) ? zend_hash_str_find_ptr(&(s)->structs, (t), strlen(t)) : NULL)
+#define psi_validate_stack_get_union(s, t) \
+ ((s) ? zend_hash_str_find_ptr(&(s)->unions, (t), strlen(t)) : NULL)
+
+#define psi_validate_stack_del_type(s, t) \
+ do { if (s) zend_hash_str_del(&(s)->types, (t), strlen(t)); } while(0)
+#define psi_validate_stack_del_struct(s, t) \
+ do { if (s) zend_hash_str_del(&(s)->structs, (t), strlen(t)); } while(0)
+#define psi_validate_stack_del_union(s, t) \
+ do { if (s) zend_hash_str_del(&(s)->unions, (t), strlen(t)); } while(0)
+
#endif
/*
* ?
*/
-impl_val *psi_let_void(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_void(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
return tmp;
}
/*
* let dvar = zval($ivar)
*/
-impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
*to_free = tmp->ptr = emalloc(sizeof(zval));
ZVAL_COPY_VALUE(tmp->ptr, zvalue);
/*
* let dvar = boolval($ivar)
*/
-impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
zend_bool boolval;
- token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_UINT8;
+ token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_UINT8;
if (ival && impl_type == PSI_T_BOOL) {
boolval = ival->zend.bval;
case PSI_T_UINT32: RETVAL_LONG(v->u32); break;
case PSI_T_INT64: RETVAL_LONG(v->i64); break;
case PSI_T_UINT64: RETVAL_LONG_U64(v->u64); break;
- case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break;
- case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break;
+ case PSI_T_FLOAT:
+ RETVAL_DOUBLE((double) v->fval);
+ convert_to_long(return_value);
+ break;
+ case PSI_T_DOUBLE:
+ RETVAL_DOUBLE(v->dval);
+ convert_to_long(return_value);
+ break;
#ifdef HAVE_LONG_DOUBLE
- case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break;
+ case PSI_T_LONG_DOUBLE:
+ RETVAL_DOUBLE((double) v->ldval);
+ convert_to_long(return_value);
+ break;
#endif
EMPTY_SWITCH_DEFAULT_CASE();
}
-
- convert_to_long(return_value);
}
static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) {
/*
* let dvar = intval($ivar)
*/
-impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
zend_long intval;
- token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_LONG;
+ token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_LONG;
if (ival && impl_type == PSI_T_INT) {
intval = ival->zend.lval;
/*
* let dvar = floatval($ivar)
*/
-impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
double floatval;
- token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_DOUBLE;
+ token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_DOUBLE;
if (ival && (impl_type == PSI_T_FLOAT || impl_type == PSI_T_DOUBLE)) {
floatval = ival->dval;
/*
* let dvar = strval($ivar)
*/
-impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
if (ival && impl_type == PSI_T_STRING) {
if (ival->zend.str) {
/*
* let dvar = pathval($ivar)
*/
-impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
tmp = psi_let_strval(tmp, spec, impl_type, ival, zvalue, to_free);
if (SUCCESS != php_check_open_basedir(tmp->ptr)) {
/*
* let dvar = strlen($ivar)
*/
-impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
if (ival && impl_type == PSI_T_STRING) {
if (ival->zend.str) {
}
}
-//impl_val *psi_let_arrval(impl_val *tmp, decl_type *spec, decl_var *spec_var, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
-//{
-// decl_type *real = real_decl_type(spec);
-// HashTable *arr;
-// zval *zv;
-// size_t i, sz;
-// decl_arg tmp_arg = {0};
-//
-// if (impl_type != PSI_T_ARRAY) {
-// SEPARATE_ARG_IF_REF(zvalue);
-// convert_to_array(zvalue);
-// }
-// arr = HASH_OF(zvalue);
-//
-// switch (real->type) {
-// case PSI_T_STRUCT:
-// *to_free = tmp = psi_array_to_struct(real->real.strct, arr);
-// break;
-// case PSI_T_UNION:
-// *to_free = tmp = psi_array_to_union(real->real.unn, arr);
-// break;
-// default:
-// sz = psi_t_size(real->type);
-// tmp = *to_free = ecalloc(zend_hash_num_elements(arr), sz);
-// tmp_arg.type = spec;
-// tmp_arg.var = spec_var;
-// ZEND_HASH_FOREACH_VAL_IND(arr, zv)
-// {
-// void *ptr = ((char *) tmp) + (i++ * sz);
-// psi_from_zval_ex(NULL, (impl_val **) &ptr, &tmp_arg, 0, zv, NULL);
-// }
-// ZEND_HASH_FOREACH_END();
-// }
-//
-// return tmp;
-//}
-
/*
* let dvar = count($ivar)
*/
-impl_val *psi_let_count(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_count(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
- return psi_val_intval(tmp, psi_decl_type_get_real(spec)->type, psi_zval_count(zvalue));
+ return psi_val_intval(tmp, psi_decl_type_get_real(spec->type)->type, psi_zval_count(zvalue));
}
/*
/*
* let dvar = objval($ivar)
*/
-impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
+impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
{
psi_object *obj;
struct psi_let_exp;
struct psi_set_exp;
-struct psi_decl_type;
+struct psi_decl_arg;
struct psi_call_frame;
struct psi_impl;
struct psi_impl_type;
int psi_internal_type(struct psi_impl_type *type);
typedef void (*psi_marshal_set)(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame);
-typedef impl_val *(*psi_marshal_let)(impl_val *tmp, struct psi_decl_type *psi_decl_type, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+typedef impl_val *(*psi_marshal_let)(impl_val *tmp, struct psi_decl_arg *type_spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
void psi_set_void(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame);
void psi_set_to_bool(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame);
void psi_set_to_object(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame);
void psi_set_zval(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame);
-impl_val *psi_let_void(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
-impl_val *psi_let_count(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free);
+impl_val *psi_let_void(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ivalue, zval *zvalue, void **to_free);
+impl_val *psi_let_count(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free);
#endif
return true;
}
-bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, void *dl)
+bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, void *dl,
+ struct psi_validate_stack *type_stack)
{
- if (!psi_decl_validate_nodl(data, decl)) {
+ if (!psi_decl_validate_nodl(data, decl, type_stack)) {
return false;
}
if (!psi_decl_validate_func(data, decl, decl->func, dl)) {
return true;
}
-bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl)
+bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl,
+ struct psi_validate_stack *type_stack)
{
if (!decl->abi) {
decl->abi = psi_decl_abi_init("default");
"Invalid calling convention: '%s'", decl->abi->token->text);
return false;
}
- if (!psi_decl_arg_validate(data, decl->func)) {
+ if (!psi_decl_arg_validate(data, decl->func, type_stack)) {
return false;
}
if (decl->args) {
struct psi_decl_arg *arg;
while (psi_plist_get(decl->args, i++, &arg)) {
- if (!psi_decl_arg_validate(data, arg)) {
+ if (!psi_decl_arg_validate(data, arg, type_stack)) {
return false;
}
}
void psi_decl_free(struct psi_decl **d_ptr);
void psi_decl_dump(int fd, struct psi_decl *decl);
-bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, void *dl);
-bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl);
+bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, void *dl, struct psi_validate_stack *type_stack);
+bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl, struct psi_validate_stack *type_stack);
static inline struct psi_decl_arg *psi_decl_get_arg(struct psi_decl *decl, struct psi_decl_var *var) {
return psi_decl_arg_get_by_var(var, decl->args, decl->func);
}
}
-bool psi_decl_arg_validate(struct psi_data *data, struct psi_decl_arg *arg)
+bool psi_decl_arg_validate(struct psi_data *data, struct psi_decl_arg *arg,
+ struct psi_validate_stack *type_stack)
{
- if (!psi_decl_type_validate(data, arg->type, NULL)) {
+ if (!psi_decl_type_validate(data, arg->type, type_stack)) {
data->error(data, arg->type->token, PSI_WARNING,
"Cannot use '%s' as type for '%s': %s", arg->type->name,
arg->var->name, data->last_error);
return true;
}
-bool psi_decl_arg_validate_typedef(struct psi_data *data, struct psi_decl_arg *def)
+bool psi_decl_arg_validate_typedef(struct psi_data *data,
+ struct psi_decl_arg *def, struct psi_validate_stack *type_stack)
{
- if (!psi_decl_type_validate(data, def->type, def)) {
- const char *pre;
-
- switch (def->type->type) {
- case PSI_T_STRUCT:
- pre = "struct ";
- break;
- case PSI_T_UNION:
- pre = "union ";
- break;
- case PSI_T_ENUM:
- pre = "enum ";
- break;
- default:
- pre = "";
- break;
- }
- data->error(data, def->token, PSI_WARNING,
- "Type '%s' cannot be aliased to '%s%s': %s", def->var->name, pre,
- def->type->name, data->last_error);
- return false;
+ if (psi_validate_stack_has_type(type_stack, def->var->name)) {
+ return true;
}
+ psi_validate_stack_add_type(type_stack, def->var->name, def);
+
if (def->type->type == PSI_T_VOID) {
if (def->var->pointer_level) {
def->type->type = PSI_T_POINTER;
"Type '%s' cannot be aliased to 'void'", def->type->name);
return false;
}
+ } else if (!def->var->pointer_level) {
+ if (!psi_decl_type_validate(data, def->type, type_stack)) {
+ const char *pre;
+
+ switch (def->type->type) {
+ case PSI_T_STRUCT:
+ pre = "struct ";
+ break;
+ case PSI_T_UNION:
+ pre = "union ";
+ break;
+ case PSI_T_ENUM:
+ pre = "enum ";
+ break;
+ default:
+ pre = "";
+ break;
+ }
+ data->error(data, def->token, PSI_WARNING,
+ "Type '%s' cannot be aliased to '%s%s': %s", def->var->name, pre,
+ def->type->name, data->last_error);
+ return false;
+ }
}
return true;
{
size_t align = psi_decl_arg_get_align(darg);
- assert(align > 0);
-
- *len = psi_decl_arg_get_size(darg);
- *pos = psi_align(align, *pos);
+ if (align) {
+ *len = psi_decl_arg_get_size(darg);
+ *pos = psi_align(align, *pos);
+ }
return align;
}
struct psi_decl_type;
struct psi_decl_var;
struct psi_layout;
+struct psi_validate_stack;
struct psi_decl_arg {
struct psi_token *token;
void psi_decl_arg_free(struct psi_decl_arg **arg_ptr);
void psi_decl_arg_dump(int fd, struct psi_decl_arg *arg, unsigned level);
-bool psi_decl_arg_validate(struct psi_data *data, struct psi_decl_arg *arg);
-bool psi_decl_arg_validate_typedef(struct psi_data *data, struct psi_decl_arg *def);
+bool psi_decl_arg_validate(struct psi_data *data, struct psi_decl_arg *arg, struct psi_validate_stack *type_stack);
+bool psi_decl_arg_validate_typedef(struct psi_data *data, struct psi_decl_arg *def, struct psi_validate_stack *type_stack);
size_t psi_decl_arg_align(struct psi_decl_arg *darg, size_t *pos, size_t *len);
size_t psi_decl_arg_get_align(struct psi_decl_arg *darg);
return NULL;
}
-bool psi_decl_struct_validate(struct psi_data *data, struct psi_decl_struct *s)
+bool psi_decl_struct_validate(struct psi_data *data, struct psi_decl_struct *s,
+ struct psi_validate_stack *type_stack)
{
size_t i, pos, len, size, align;
struct psi_decl_arg *darg, *prev_arg;
+ if (psi_validate_stack_has_struct(type_stack, s->name)) {
+ return true;
+ }
+ psi_validate_stack_add_struct(type_stack, s->name, s);
+
if (!s->size && !psi_plist_count(s->args)) {
data->error(data, s->token, PSI_WARNING,
"Cannot compute size of empty struct '%s'", s->name);
for (i = 0; psi_plist_get(s->args, i, &darg); ++i) {
darg->var->arg = darg;
- if (!psi_decl_arg_validate(data, darg)) {
+ if (!psi_decl_arg_validate(data, darg, type_stack)) {
return false;
}
pos = darg->layout->pos;
align = psi_decl_arg_align(darg, &pos, &len);
+ if (!align) {
+ data->error(data, darg->token, PSI_WARNING,
+ "Computed zero alignment of %s.%s of type '%s'",
+ len, s->name, darg->var->name, darg->type->name);
+ return false;
+ }
+
if (darg->layout->len != len) {
data->error(data, darg->token, PSI_WARNING,
"Computed size %zu of %s.%s does not match"
struct psi_token;
struct psi_plist;
struct psi_decl_var;
+struct psi_validate_stack;
struct psi_decl_struct {
struct psi_token *token;
void psi_decl_struct_free(struct psi_decl_struct **s_ptr);
void psi_decl_struct_dump(int fd, struct psi_decl_struct *strct);
-bool psi_decl_struct_validate(struct psi_data *data, struct psi_decl_struct *s);
+bool psi_decl_struct_validate(struct psi_data *data, struct psi_decl_struct *s, struct psi_validate_stack *type_stack);
struct psi_decl_arg *psi_decl_struct_get_arg(struct psi_decl_struct *s, struct psi_decl_var *var);
size_t psi_decl_struct_get_align(struct psi_decl_struct *s);
}
bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
- struct psi_decl_arg *def)
+ struct psi_validate_stack *type_stack)
{
if (psi_decl_type_is_weak(type)) {
if (!psi_decl_type_get_alias(type, data->types)) {
- return false;
+ if (!psi_validate_stack_has_type(type_stack, type->name)) {
+ return false;
+ }
+ type->real.def = psi_validate_stack_get_type(type_stack, type->name);
}
if (type->real.def) {
return psi_decl_type_validate(data, type->real.def->type,
- type->real.def);
+ type_stack);
}
return true;
}
switch (type->type) {
case PSI_T_STRUCT:
- if (!psi_decl_type_get_struct(type, data->structs) && !def) {
- data->error(data, type->token, PSI_WARNING,
- "Unknown struct '%s'", type->name);
+ if (!psi_decl_type_get_struct(type, data->structs)) {
+ if (psi_validate_stack_has_struct(type_stack, type->name)) {
+ type->real.strct = psi_validate_stack_get_struct(type_stack, type->name);
+ } else {
+ data->error(data, type->token, PSI_WARNING,
+ "Unknown struct '%s'", type->name);
+ return false;
+ }
+ }
+ if (!psi_decl_struct_validate(data, type->real.strct, type_stack)) {
return false;
}
break;
case PSI_T_UNION:
- if (!psi_decl_type_get_union(type, data->unions) && !def) {
- data->error(data, type->token, PSI_WARNING,
- "Unknown union '%s'", type->name);
+ if (!psi_decl_type_get_union(type, data->unions)) {
+ if (psi_validate_stack_has_union(type_stack, type->name)) {
+ type->real.unn = psi_validate_stack_get_union(type_stack, type->name);
+ } else {
+ data->error(data, type->token, PSI_WARNING,
+ "Unknown union '%s'", type->name);
+ return false;
+ }
+ }
+ if (!psi_decl_union_validate(data, type->real.unn, type_stack)) {
return false;
}
break;
case PSI_T_ENUM:
- if (!psi_decl_type_get_enum(type, data->enums) && !def) {
+ if (!psi_decl_type_get_enum(type, data->enums)) {
data->error(data, type->token, PSI_WARNING,
"Unknown enum '%s'", type->name);
return false;
"Unknown decl '%s'", type->name);
return false;
}
- if (!psi_decl_validate_nodl(data, type->real.func)) {
+ if (!psi_decl_validate_nodl(data, type->real.func, type_stack)) {
return false;
}
break;
+ default:
+ break;
}
+
return true;
}
struct psi_decl_union;
struct psi_decl_enum;
struct psi_decl;
+struct psi_validate_stack;
struct psi_decl_type {
struct psi_token *token;
struct psi_decl_type *psi_decl_type_copy(struct psi_decl_type *src);
void psi_decl_type_free(struct psi_decl_type **type_ptr);
void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level);
-bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type, struct psi_decl_arg *def);
+bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type, struct psi_validate_stack *type_stack);
bool psi_decl_type_validate_args(struct psi_data *data, struct psi_decl_type *decl_type, token_t type, void *current);
return NULL;
}
-bool psi_decl_union_validate(struct psi_data *data, struct psi_decl_union *u)
+bool psi_decl_union_validate(struct psi_data *data, struct psi_decl_union *u,
+ struct psi_validate_stack *type_stack)
{
size_t i, pos, len, size = 0, align;
struct psi_decl_arg *darg;
+ if (psi_validate_stack_has_union(type_stack, u->name)) {
+ return true;
+ }
+ psi_validate_stack_add_union(type_stack, u->name, u);
+
if (!u->size && !psi_plist_count(u->args)) {
data->error(data, u->token, PSI_WARNING,
"Cannot compute size of empty union %s", u->name);
for (i = 0; psi_plist_get(u->args, i, &darg); ++i) {
darg->var->arg = darg;
- if (!psi_decl_arg_validate(data, darg)) {
+ if (!psi_decl_arg_validate(data, darg, type_stack)) {
return false;
}
struct psi_token;
struct psi_plist;
struct psi_decl_var;
+struct psi_validate_stack;
struct psi_decl_union {
struct psi_token *token;
void psi_decl_union_free(struct psi_decl_union **u_ptr);
void psi_decl_union_dump(int fd, struct psi_decl_union *unn);
-bool psi_decl_union_validate(struct psi_data *data, struct psi_decl_union *u);
+bool psi_decl_union_validate(struct psi_data *data, struct psi_decl_union *u, struct psi_validate_stack *type_stack);
size_t psi_decl_union_get_align(struct psi_decl_union *u);
struct psi_decl_arg *psi_decl_union_get_arg(struct psi_decl_union *u, struct psi_decl_var *var);
}
}
- if (!psi_decl_validate_nodl(data, cb_func)) {
+ if (!psi_decl_validate_nodl(data, cb_func, NULL /* FIXME type_stack */)) {
return false;
}
struct psi_call_frame *frame);
void exec_let_func_arrval_seq(struct psi_let_func *func,
- struct psi_decl_arg *darg, struct psi_decl_type *darg_type,
+ struct psi_decl_arg *darg,
struct psi_call_frame_argument *frame_arg,
struct psi_let_exp *inner_let_exp, void *container,
struct psi_call_frame *frame)
impl_val val = {0}, *ptr, *sub;
if (let_fn) {
- ptr = let_fn(&val, darg_type, 0, NULL, zval_ptr, &temp);
+ ptr = let_fn(&val, darg, 0, NULL, zval_ptr, &temp);
if (temp) {
psi_call_frame_push_auto(frame, temp);
}
{
void *container = NULL;
struct psi_call_frame_argument *frame_arg;
- struct psi_decl_type *darg_type;
struct psi_plist *darg_members;
- darg_members = psi_decl_type_get_args(darg->type, &darg_type);
+ darg_members = psi_decl_type_get_args(darg->type, NULL);
frame_arg = psi_call_frame_get_argument(frame, func->var->fqn);
if (frame_arg->zval_ptr && Z_TYPE_P(frame_arg->zval_ptr) != IS_ARRAY) {
container = ecalloc(arcount + 1, psi_decl_var_get_size(inner->var));
inner->var->pointer_level -= inner->is_reference;
- exec_let_func_arrval_seq(func, darg, darg_type, frame_arg, inner,
- container, frame);
+ exec_let_func_arrval_seq(func, darg, frame_arg, inner, container, frame);
} else {
assert(0);
}
assert(iarg);
- frame_sym->ival_ptr = let_fn(&frame_sym->temp_val,
- psi_decl_type_get_real(darg->type),
+ frame_sym->ival_ptr = let_fn(&frame_sym->temp_val, darg,
iarg->spec ? iarg->spec->type->type : 0, iarg->ival_ptr,
iarg->zval_ptr, &temp);
if (temp) {
===DONE===
--EXPECTF--
===TEST===
-
-Warning: Cannot compute size of empty struct 'a' in %s on line 1
===DONE===