flush
authorMichael Wallner <mike@php.net>
Thu, 28 Jan 2016 16:41:04 +0000 (17:41 +0100)
committerMichael Wallner <mike@php.net>
Thu, 28 Jan 2016 16:41:04 +0000 (17:41 +0100)
m4/psi_type.m4
src/context.c
src/context_dump.c
src/context_validate.c
src/engine.c
src/parser.h
src/parser_proc.y

index 21484ad..050f805 100644 (file)
@@ -205,25 +205,30 @@ AC_DEFUN(PSI_CHECK_STD_TYPES, [
        AC_CHECK_ALIGNOF(long double)
 
        PSI_STDTYPE(char, int)
+       AC_CHECK_ALIGNOF(char)
        PSI_STDTYPE(signed char, int)
        PSI_STDTYPE(unsigned char, uint)
        PSI_STDTYPE(short, int)
+       AC_CHECK_ALIGNOF(short)
        PSI_STDTYPE(short int, int)
        PSI_STDTYPE(signed short, int)
        PSI_STDTYPE(signed short int, int)
        PSI_STDTYPE(unsigned short, uint)
        PSI_STDTYPE(unsigned short int, uint)
        PSI_STDTYPE(int, int)
+       AC_CHECK_ALIGNOF(int)
        PSI_STDTYPE(signed int, int)
        PSI_STDTYPE(signed, int)
        PSI_STDTYPE(unsigned int, uint)
        PSI_STDTYPE(unsigned, uint)
        PSI_STDTYPE(long, int)
+       AC_CHECK_ALIGNOF(long)
        PSI_STDTYPE(long int, int)
        PSI_STDTYPE(signed long int, int)
        PSI_STDTYPE(unsigned long, uint)
        PSI_STDTYPE(unsigned long int, uint)
        PSI_STDTYPE(long long, int)
+       AC_CHECK_ALIGNOF(long long)
        PSI_STDTYPE(signed long long, int)
        PSI_STDTYPE(signed long long int, int)
        PSI_STDTYPE(unsigned long long, uint)
index 3fe6c3f..d1c1655 100644 (file)
@@ -66,7 +66,8 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr
 
        for (predef_type = &psi_predef_types[0]; predef_type->type_tag; ++predef_type) {
                decl_type *type = init_decl_type(predef_type->type_tag, predef_type->type_name);
-               decl_typedef *def = init_decl_typedef(predef_type->alias, type);
+               decl_var *var = init_decl_var(predef_type->alias, 0, 0); /* FIXME: indirection */
+               decl_arg *def = init_decl_arg(type, var);
 
                T.defs = add_decl_typedef(T.defs, def);
        }
index cb1825f..708b36f 100644 (file)
@@ -111,18 +111,21 @@ static inline void dump_impl_set_value(int fd, set_value *set, unsigned level, i
        }
 }
 
-static inline void dump_typedef(int fd, decl_typedef *tdef) {
+static inline void dump_typedef(int fd, decl_arg *tdef) {
        dprintf(fd, "typedef ");
+       dump_decl_arg(fd, tdef);
+       /*
        dump_decl_type(fd, tdef->type);
        dprintf(fd, " %s%s;", tdef->type->type == PSI_T_POINTER ? "*":"",
                        tdef->alias);
+       */
 }
 
 static inline void dump_typedefs(int fd, decl_typedefs *defs) {
        size_t i;
 
        for (i = 0; i < defs->count; ++i) {
-               decl_typedef *tdef = defs->list[i];
+               decl_arg *tdef = defs->list[i];
 
                dump_typedef(fd, tdef);
                dprintf(fd, "\n");
index 6a89d6e..7c7a245 100644 (file)
@@ -48,10 +48,10 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
        if (type->real) {
                return 1;
        }
-       for (i = 0; i < defs->count; ++i) {
-               decl_typedef *def = defs->list[i];
+       if (defs) for (i = 0; i < defs->count; ++i) {
+               decl_arg *def = defs->list[i];
 
-               if (def->type->type != type->type && !strcmp(def->alias, type->name)) {
+               if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
                        type->real = def->type;
                        return 1;
                }
@@ -72,7 +72,7 @@ static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type
        if (type->strct) {
                return 1;
        }
-       for (i = 0; i < structs->count; ++i) {
+       if (structs) for (i = 0; i < structs->count; ++i) {
                if (!strcmp(structs->list[i]->name, type->name)) {
                        type->strct = structs->list[i];
                        return 1;
@@ -87,7 +87,7 @@ static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
        if (type->enm) {
                return 1;
        }
-       for (i = 0; i < enums->count; ++i) {
+       if (enums) for (i = 0; i < enums->count; ++i) {
                if (!strcmp(enums->list[i]->name, type->name)) {
                        type->enm = enums->list[i];
                        return 1;
@@ -103,7 +103,7 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
        case PSI_T_INT:
        case PSI_T_LONG:
        case PSI_T_NAME:
-               if (!data->defs || !locate_decl_type_alias(data->defs, type)) {
+               if (!locate_decl_type_alias(data->defs, type)) {
                        return 0;
                }
                if (type->real) {
@@ -111,25 +111,25 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
                }
                return 1;
        case PSI_T_STRUCT:
-               if (!data->structs || !locate_decl_type_struct(data->structs, type)) {
+               if (!locate_decl_type_struct(data->structs, type)) {
                        return 0;
                }
                break;
        case PSI_T_ENUM:
-               if (!data->enums || !locate_decl_type_enum(data->enums, type)) {
+               if (!locate_decl_type_enum(data->enums, type)) {
                        return 0;
                }
        }
        return 1;
 }
-static inline int validate_decl_typedef(PSI_Data *data, decl_typedef *def) {
+static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
        if (!validate_decl_type(data, def->type)) {
                data->error(def->token, PSI_WARNING,
                        "Type '%s' cannot be aliased to %s'%s'",
-                       def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",def->alias);
+                       def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",
+                       def->var->name);
                return 0;
        }
-       /* FIXME: check def->alias */
        return 1;
 }
 
@@ -230,7 +230,17 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
                                t = real_decl_type(darg->type)->type;
                        }
 
-                       size = psi_t_size(t) * (darg->var->array_size ?: 1);
+                       switch (t) {
+                       case PSI_T_STRUCT:
+                               if (!validate_decl_struct(data, real_decl_type(darg->type)->strct)) {
+                                       return 0;
+                               }
+                               size = real_decl_type(darg->type)->strct->size;
+                               break;
+                       default:
+                               size = psi_t_size(t) * (darg->var->array_size ?: 1);
+                               break;
+                       }
 
                        if (i) {
                                decl_arg *last = s->args->args[i-1];
@@ -935,6 +945,7 @@ static inline int validate_impl_args(PSI_Data *data, impl *impl) {
 
        return 1;
 }
+
 static inline int validate_impl(PSI_Data *data, impl *impl) {
        if (!validate_impl_args(data, impl)) {
                return 0;
@@ -947,41 +958,89 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
 {
        PSI_Data *D;
        void *dlopened = NULL;
-       size_t count = C->count++;
+       size_t i, count = C->count++, check_round, check_count;
+       decl_typedefs *check_defs = P->defs;
+       decl_structs *check_structs = P->structs;
+       decl_enums *check_enums = P->enums;
 
        C->data = realloc(C->data, C->count * sizeof(*C->data));
        D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
-
+/*
        if (D->defs) {
-               size_t i;
-
                for (i = 0; i < D->defs->count; ++i) {
                        if (validate_decl_typedef(PSI_DATA(C), D->defs->list[i])) {
                                C->defs = add_decl_typedef(C->defs, D->defs->list[i]);
+                       } else {
+                               check_defs = add_decl_typedef(check_defs, D->defs->list[i]);
                        }
                }
        }
        if (D->structs) {
-               size_t i;
-
                for (i = 0; i < D->structs->count; ++i) {
                        if (validate_decl_struct(PSI_DATA(C), D->structs->list[i])) {
                                C->structs = add_decl_struct(C->structs, D->structs->list[i]);
+                       } else {
+                               check_structs = add_decl_struct(check_structs, D->structs->list[i]);
                        }
                }
        }
        if (D->enums) {
-               size_t i;
-
                for (i = 0; i < D->enums->count; ++i) {
                        if (validate_decl_enum(PSI_DATA(C), D->enums->list[i])) {
                                C->enums = add_decl_enum(C->enums, D->enums->list[i]);
+                       } else {
+                               check_enums = add_decl_enum(check_enums, D->enums->list[i]);
                        }
                }
        }
-       if (D->consts) {
-               size_t i;
+*/
+#define REVALIDATE(what) do { \
+               if (check_round && check_ ##what) { \
+                       free(check_ ##what->list); \
+                       free(check_ ##what); \
+               } \
+               check_ ##what = recheck_ ##what; \
+} while (0)
+#define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
+#define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
+
+       for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
+               decl_typedefs *recheck_defs = NULL;
+               decl_structs *recheck_structs = NULL;
+               decl_enums *recheck_enums = NULL;
+
+               check_count = CHECK_TOTAL;
+               fprintf(stderr, "### Validation round %zu with %zu checks\n", check_round, check_count);
+
+               for (i = 0; i < CHECK_COUNT(defs); ++i) {
+                       if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
+                               C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
+                       } else {
+                               recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
+                       }
+               }
+               for (i = 0; i < CHECK_COUNT(structs); ++i) {
+                       if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
+                               C->structs = add_decl_struct(C->structs, check_structs->list[i]);
+                       } else {
+                               recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
+                       }
+               }
+               for (i = 0; i < CHECK_COUNT(enums); ++i) {
+                       if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
+                               C->enums = add_decl_enum(C->enums, check_enums->list[i]);
+                       } else {
+                               recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
+                       }
+               }
 
+               REVALIDATE(defs);
+               REVALIDATE(structs);
+               REVALIDATE(enums);
+       }
+
+
+       if (D->consts) {
                for (i = 0; i < D->consts->count; ++i) {
                        if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
                                C->consts = add_constant(C->consts, D->consts->list[i]);
@@ -996,8 +1055,6 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
        add_decl_lib(&C->psi.libs, dlopened);
 
        if (D->decls) {
-               size_t i;
-
                for (i = 0; i < D->decls->count; ++i) {
                        if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
                                C->decls = add_decl(C->decls, D->decls->list[i]);
@@ -1005,8 +1062,6 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
                }
        }
        if (D->impls) {
-               size_t i;
-
                for (i = 0; i < D->impls->count; ++i) {
                        if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
                                C->impls = add_impl(C->impls, D->impls->list[i]);
@@ -1023,7 +1078,7 @@ int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
        int errors = 0;
 
        if (source->defs) for (i = 0; i < source->defs->count; ++i) {
-               decl_typedef *def = source->defs->list[i];
+               decl_arg *def = source->defs->list[i];
 
                if (validate_decl_typedef(source, def)) {
                        if (dest) {
index c3e95c5..d14bac7 100644 (file)
@@ -28,7 +28,11 @@ size_t psi_t_alignment(token_t t)
        case PSI_T_DOUBLE:
                return ALIGNOF_DOUBLE;
        case PSI_T_POINTER:
+       case PSI_T_FUNCTION:
+       case PSI_T_STRUCT:
                return ALIGNOF_VOID_P;
+       case PSI_T_ENUM:
+               return ALIGNOF_INT;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
        return 0;
@@ -51,7 +55,10 @@ size_t psi_t_size(token_t t)
        case PSI_T_DOUBLE:
                return SIZEOF_DOUBLE;
        case PSI_T_POINTER:
+       case PSI_T_FUNCTION:
                return SIZEOF_VOID_P;
+       case PSI_T_ENUM:
+               return SIZEOF_INT;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
        return 0;
index 41741c0..0f5671d 100644 (file)
@@ -27,6 +27,8 @@ typedef struct PSI_Token {
        char buf[1];
 } PSI_Token;
 
+static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
+
 typedef union impl_val {
        char cval;
        int8_t i8;
@@ -78,60 +80,18 @@ static inline decl_type *real_decl_type(decl_type *type) {
        return type;
 }
 
+static inline void free_decl(struct decl *decl);
 static inline void free_decl_type(decl_type *type) {
        if (type->token) {
                free(type->token);
        }
+       if (type->type == PSI_T_FUNCTION) {
+               free_decl(type->func);
+       }
        free(type->name);
        free(type);
 }
 
-typedef struct decl_typedef {
-       PSI_Token *token;
-       char *alias;
-       decl_type *type;
-} decl_typedef;
-
-static inline decl_typedef *init_decl_typedef(const char *name, decl_type *type) {
-       decl_typedef *t = calloc(1, sizeof(*t));
-       t->alias = strdup(name);
-       t->type = type;
-       return t;
-}
-
-static inline void free_decl_typedef(decl_typedef *t) {
-       if (t->token) {
-               free(t->token);
-       }
-       free(t->alias);
-       free_decl_type(t->type);
-       free(t);
-}
-
-typedef struct decl_typedefs {
-       size_t count;
-       decl_typedef **list;
-} decl_typedefs;
-
-static inline decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_typedef *def) {
-       if (!defs) {
-               defs = calloc(1, sizeof(*defs));
-       }
-       defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list));
-       defs->list[defs->count-1] = def;
-       return defs;
-}
-
-static void free_decl_typedefs(decl_typedefs *defs) {
-       size_t i;
-
-       for (i = 0; i < defs->count; ++i) {
-               free_decl_typedef(defs->list[i]);
-       }
-       free(defs->list);
-       free(defs);
-}
-
 typedef struct decl_var {
        PSI_Token *token;
        char *name;
@@ -148,6 +108,17 @@ static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as
        return v;
 }
 
+static inline decl_var *copy_decl_var(decl_var *src) {
+       decl_var *dest = calloc(1, sizeof(*dest));
+
+       memcpy(dest, src, sizeof(*dest));
+       dest->name = strdup(dest->name);
+       if (dest->token) {
+               dest->token = PSI_TokenCopy(dest->token);
+       }
+       return dest;
+}
+
 static inline void free_decl_var(decl_var *var) {
        if (var->token) {
                free(var->token);
@@ -203,6 +174,30 @@ static inline void free_decl_arg(decl_arg *arg) {
        free(arg);
 }
 
+typedef struct decl_typedefs {
+       size_t count;
+       decl_arg **list;
+} decl_typedefs;
+
+static inline decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_arg *def) {
+       if (!defs) {
+               defs = calloc(1, sizeof(*defs));
+       }
+       defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list));
+       defs->list[defs->count-1] = def;
+       return defs;
+}
+
+static void free_decl_typedefs(decl_typedefs *defs) {
+       size_t i;
+
+       for (i = 0; i < defs->count; ++i) {
+               free_decl_arg(defs->list[i]);
+       }
+       free(defs->list);
+       free(defs);
+}
+
 typedef struct decl_vars {
        decl_var **vars;
        size_t count;
@@ -641,7 +636,6 @@ static inline num_exp *init_num_exp(token_t t, void *num) {
        return exp;
 }
 
-static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
 static inline num_exp *copy_num_exp(num_exp *exp) {
        decl_var *dvar;
        num_exp *num = calloc(1, sizeof(*num));
@@ -1511,6 +1505,7 @@ static inline PSI_Token *PSI_TokenAppend(PSI_Token *T, unsigned argc, ...) {
        return T;
 }
 
+char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen);
 static inline PSI_Token *PSI_TokenTranslit(PSI_Token *T, char *from, char *to) {
        php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
        return T;
index ac856ed..e488c0e 100644 (file)
@@ -61,6 +61,9 @@ block ::= decl_typedef(def). {
        if (def->type->strct) {
                P->structs = add_decl_struct(P->structs, def->type->strct);
        }
+       if (def->type->enm) {
+               P->enums = add_decl_enum(P->enums, def->type->enm);
+       }
 }
 block ::= constant(constant). {
        P->consts = add_constant(P->consts, constant);
@@ -90,7 +93,6 @@ enum_name(n) ::= ENUM(E) optional_name(N). {
        }
 }
 
-
 %type decl_enum {decl_enum *}
 %destructor decl_enum {free_decl_enum($$);}
 decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
@@ -176,47 +178,72 @@ constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val)
        free(T);
 }
 
-%type decl_typedef {decl_typedef*}
-%destructor decl_typedef {free_decl_typedef($$);}
-decl_typedef(def) ::= TYPEDEF decl_typedef_body(def_) EOS. {
+%type decl_typedef {decl_arg*}
+%destructor decl_typedef {
+       free_decl_arg($$);
+       if ($$->type->strct) {
+               free_decl_struct($$->type->strct);
+       }
+       if ($$->type->enm) {
+               free_decl_enum($$->type->enm);
+       }
+       if ($$->type->func) {
+               free_decl($$->type->func);
+       }
+}
+decl_typedef(def) ::= TYPEDEF(T) decl_typedef_body(def_) EOS. {
        def = def_;
+       def->token = T;
 }
-%type decl_typedef_body_ex {decl_typedef*}
-%destructor decl_typedef_body_ex {free_decl_typedef($$);}
-decl_typedef_body_ex(def) ::= struct_name(N) struct_size(size_) decl_struct_args_block(args) NAME(ALIAS). {
-       def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, N->text));
-       def->token = ALIAS;
+%type decl_typedef_body_ex {decl_arg*}
+%destructor decl_typedef_body_ex {
+       free_decl_arg($$);
+       if ($$->type->strct) {
+               free_decl_struct($$->type->strct);
+       }
+       if ($$->type->enm) {
+               free_decl_enum($$->type->enm);
+       }
+       if ($$->type->func) {
+               free_decl($$->type->func);
+       }
+}
+decl_typedef_body_ex(def) ::= struct_name(N) struct_size(size_) decl_struct_args_block(args) decl_var(var). {
+       def = init_decl_arg(init_decl_type(PSI_T_STRUCT, N->text), var);
        def->type->token = PSI_TokenCopy(N);
        def->type->strct = init_decl_struct(N->text, args);
        def->type->strct->token = N;
        def->type->strct->size = size_;
 }
 decl_typedef_body_ex(def) ::= decl_enum(e) NAME(ALIAS). {
-       def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_ENUM, e->name));
+       def = init_decl_arg(init_decl_type(PSI_T_ENUM, e->name), init_decl_var(ALIAS->text, 0, 0));
+       def->var->token = ALIAS;
        def->type->token = PSI_TokenCopy(e->token);
-       def->token = ALIAS;
        def->type->enm = e;
 }
-%type decl_typedef_body {decl_typedef*}
-%destructor decl_typedef_body {free_decl_typedef($$);}
+%type decl_typedef_body {decl_arg*}
+%destructor decl_typedef_body {
+       free_decl_arg($$);
+       if ($$->type->strct) {
+               free_decl_struct($$->type->strct);
+       }
+       if ($$->type->enm) {
+               free_decl_enum($$->type->enm);
+       }
+       if ($$->type->func) {
+               free_decl($$->type->func);
+       }
+}
 decl_typedef_body(def) ::= decl_typedef_body_ex(def_). {
        def = def_;
 }
-decl_typedef_body(def) ::= decl_type(type) NAME(ALIAS). {
-       def = init_decl_typedef(ALIAS->text, type);
-       def->token = ALIAS;
-}
-/* support opaque types */
-decl_typedef_body(def) ::= VOID(V) indirection(i) NAME(ALIAS). {
-       def = init_decl_typedef(ALIAS->text, init_decl_type(i?PSI_T_POINTER:V->type, V->text));
-       def->token = ALIAS;
-       def->type->token = V;
+decl_typedef_body(def) ::= decl_func(func_) LPAREN decl_args(args) RPAREN. {
+       def = init_decl_arg(init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var));
+       def->type->token = PSI_TokenCopy(func_->token);
+       def->type->func = init_decl(init_decl_abi("default"), func_, args);
 }
-decl_typedef_body(def) ::= decl_func(func) LPAREN decl_args(args) RPAREN. {
-       def = init_decl_typedef(func->var->name, init_decl_type(PSI_T_FUNCTION, func->var->name));
-       def->type->token = PSI_TokenCopy(func->token);
-       def->type->func = init_decl(init_decl_abi("default"), func, args);
-       def->token = PSI_TokenCopy(func->token);
+decl_typedef_body(def) ::= decl_arg(arg). {
+       def = arg;
 }
 
 %type decl {decl*}
@@ -237,7 +264,6 @@ decl_func(func) ::= VOID(T) NAME(N). {
                init_decl_var(N->text, 0, 0)
        );
        func->type->token = T;
-       //free(T);
        free(N);
 }
 
@@ -319,12 +345,7 @@ struct_args(args) ::= struct_args(args_) struct_arg(arg). {
 %type struct_arg {decl_arg*}
 %destructor struct_arg {free_decl_arg($$);}
 struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. {
-       arg_ = init_decl_arg(def->type, init_decl_var(def->alias, 0, 0));
-       arg_->var->arg = arg_;
-       arg_->token = PSI_TokenCopy(def->type->token);
-       arg_->var->token = def->token;
-       free(def->alias);
-       free(def);
+       arg_ = def;
 }
 struct_arg(arg) ::= decl_arg(arg_) struct_layout(layout_) EOS. {
        arg_->layout = layout_;