Merge branch 'slimconfigure'
[m6w6/ext-psi] / src / types / decl_type.c
index f3b500a935f5c5127142f81b2137b0955ca5c80c..dfded25d5ad0307e257e6749d57b80f9cd6d1950 100644 (file)
@@ -55,6 +55,20 @@ void psi_decl_type_free(struct psi_decl_type **type_ptr)
        }
 }
 
+struct psi_decl_type *psi_decl_type_copy(struct psi_decl_type *src)
+{
+       struct psi_decl_type *dst = calloc(1, sizeof(*dst));
+
+       dst->type = src->type;
+       if (src->name) {
+               dst->name = strdup(src->name);
+       }
+       if (src->token) {
+               dst->token = psi_token_copy(src->token);
+       }
+       return dst;
+}
+
 struct psi_plist *psi_decl_type_get_args(struct psi_decl_type *dtyp,
                struct psi_decl_type **real_typ_ptr)
 {
@@ -87,9 +101,9 @@ size_t psi_decl_type_get_size(struct psi_decl_type *dtyp,
 
        switch (var_typ->type) {
        case PSI_T_STRUCT:
-               return var_typ->real.strct->size;
+               return var_typ->real.strct ? var_typ->real.strct->size : 0;
        case PSI_T_UNION:
-               return var_typ->real.unn->size;
+               return var_typ->real.unn ? var_typ->real.unn->size : 0;
        default:
                return psi_t_size(var_typ->type);
        }
@@ -104,14 +118,14 @@ bool psi_decl_type_get_alias(struct psi_decl_type *type, struct psi_plist *defs)
        if (type->real.def) {
                return true;
        }
-       if (defs)
+       if (defs) {
                while (psi_plist_get(defs, i++, &def)) {
-                       if (def->type->type != type->type
-                                       && !strcmp(def->var->name, type->name)) {
+                       if (!strcmp(def->var->name, type->name)) {
                                type->real.def = def;
                                return true;
                        }
                }
+       }
        for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
                if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
                        type->type = stdtyp->type_tag;
@@ -199,36 +213,62 @@ bool psi_decl_type_get_decl(struct psi_decl_type *type, struct psi_plist *decls)
 }
 
 bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
-               struct psi_decl_arg *def)
+               struct psi_decl_arg *def, struct psi_validate_scope *scope)
 {
        if (psi_decl_type_is_weak(type)) {
                if (!psi_decl_type_get_alias(type, data->types)) {
-                       return false;
+                       if (!psi_validate_scope_has_type(scope, type->name)) {
+                               return false;
+                       }
+                       type->real.def = psi_validate_scope_get_type(scope, type->name);
                }
                if (type->real.def) {
-                       return psi_decl_type_validate(data, type->real.def->type,
-                                       type->real.def);
+                       if (!psi_decl_type_validate(data, type->real.def->type,
+                                       type->real.def, scope)) {
+                               return false;
+                       }
+                       if (def) {
+                               def->var->pointer_level += type->real.def->var->pointer_level;
+                       }
                }
                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_scope_has_struct(scope, type->name)) {
+                               type->real.strct = psi_validate_scope_get_struct(scope, type->name);
+                       } else if (def && def->var->pointer_level) {
+                               return true;
+                       } else {
+                               data->error(data, type->token, PSI_WARNING,
+                                               "Unknown struct '%s'", type->name);
+                               return false;
+                       }
+               }
+               if (!psi_decl_struct_validate(data, type->real.strct, scope)) {
                        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_scope_has_union(scope, type->name)) {
+                               type->real.unn = psi_validate_scope_get_union(scope, type->name);
+                       } else if (def && def->var->pointer_level) {
+                               return true;
+                       } else {
+                               data->error(data, type->token, PSI_WARNING,
+                                               "Unknown union '%s'", type->name);
+                               return false;
+                       }
+               }
+               if (!psi_decl_union_validate(data, type->real.unn, scope)) {
                        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;
@@ -240,11 +280,14 @@ bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
                                        "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, scope)) {
                        return false;
                }
                break;
+       default:
+               break;
        }
+
        return true;
 }
 
@@ -261,8 +304,15 @@ void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
                while (psi_plist_get(args, i++, &sarg)) {
                        dprintf(fd, "%s", psi_t_indent(level));
                        psi_decl_arg_dump(fd, sarg, level);
-                       dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
-                                       sarg->layout->len);
+                       if (sarg->layout) {
+                               if (sarg->layout->bfw) {
+                                       dprintf(fd, ":%zu", sarg->layout->bfw->len);
+                               }
+                               dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
+                                               sarg->layout->len);
+                       } else {
+                               dprintf(fd, ";\n");
+                       }
                }
                --level;
        }
@@ -293,7 +343,7 @@ void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
                                }
                        }
                        --level;
-                       dprintf(fd, "%s} ", psi_t_indent(level));
+                       dprintf(fd, "%s\n} ", psi_t_indent(level));
                        return;
                }
                break;
@@ -313,7 +363,11 @@ void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
                        return;
                }
                break;
+
+       default:
+               break;
        }
+
        dprintf(fd, "%s", t->name);
 }
 
@@ -324,6 +378,8 @@ int psi_decl_type_is_weak(struct psi_decl_type *type)
        case PSI_T_SHORT:
        case PSI_T_INT:
        case PSI_T_LONG:
+       case PSI_T_UNSIGNED:
+       case PSI_T_SIGNED:
        case PSI_T_NAME:
                return type->type;
        default:
@@ -354,6 +410,7 @@ size_t psi_decl_type_get_align(struct psi_decl_type *t)
        case PSI_T_ENUM:
        default:
                align = psi_t_alignment(real->type);
+               break;
        }
 
        return align;