+} decl_file;
+
+static inline void free_decl_file(decl_file *file) {
+ if (file->ln) {
+ free(file->ln);
+ }
+ if (file->fn) {
+ free(file->fn);
+ }
+ memset(file, 0, sizeof(*file));
+}
+
+typedef struct decl_libs {
+ void **dl;
+ size_t count;
+} decl_libs;
+
+static inline void free_decl_libs(decl_libs *libs) {
+ if (libs->dl) {
+ size_t i;
+ for (i = 0; i < libs->count; ++i) {
+ if (libs->dl[i]) {
+ dlclose(libs->dl[i]);
+ }
+ }
+ free(libs->dl);
+ }
+ memset(libs, 0, sizeof(*libs));
+}
+
+static inline void add_decl_lib(decl_libs *libs, void *dlopened) {
+ libs->dl = realloc(libs->dl, ++libs->count * sizeof(*libs->dl));
+ libs->dl[libs->count-1] = dlopened;
+}
+
+static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) {
+ unsigned i;
+
+ if (var->arg->var != var) for (i = 1; i < var->pointer_level; ++i) {
+ ret_val = *(void **) ret_val;
+ }
+ return ret_val;
+}
+
+static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
+ impl_val *val, *val_ptr;
+ unsigned i;
+
+ if (!var->pointer_level && real_decl_type(var->arg->type)->type != PSI_T_STRUCT) {
+ return ptr;
+ }
+ val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *));
+ for (i = 1; i < var->pointer_level; ++i) {
+ val_ptr->ptr = (void **) val_ptr + 1;
+ val_ptr = val_ptr->ptr;
+ }
+ val_ptr->ptr = ptr;
+ return val;
+}
+
+static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) {
+ void *ptr = (char *) struct_ptr->ptr + set_arg->layout->pos;
+ impl_val *val = enref_impl_val(ptr, set_arg->var);
+
+ if (val != ptr) {
+ *to_free = val;
+ }
+
+ return val;
+}
+
+#define PSI_ERROR 16
+#define PSI_WARNING 32
+typedef void (*psi_error_cb)(int type, const char *msg, ...);
+
+#define PSI_DATA(D) ((PSI_Data *) (D))
+#define PSI_DATA_MEMBERS \
+ constants *consts; \
+ decl_typedefs *defs; \
+ decl_structs *structs; \
+ decls *decls; \
+ impls *impls; \
+ union { \
+ decl_file file; \
+ decl_libs libs; \
+ } psi; \
+ psi_error_cb error
+typedef struct PSI_Data {
+ PSI_DATA_MEMBERS;