interned strings
[m6w6/ext-psi] / src / context.c
index b4e73ad2015df02e3d06a91335bf0417a5aa6ce1..8fdbf22f41a2701b60833ce59407f3c48b078122 100644 (file)
 #include "token.h"
 #include "parser.h"
 
-#include "php_psi_types.h"
-#include "php_psi_consts.h"
-#include "php_psi_decls.h"
-#include "php_psi_va_decls.h"
-#include "php_psi_fn_decls.h"
-#include "php_psi_structs.h"
-#include "php_psi_unions.h"
+#include "php_psi_posix.h"
 
 struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_error_cb error, unsigned flags)
 {
-       struct psi_data T;
-       struct psi_predef_type *predef_type;
-       struct psi_predef_const *predef_const;
-       struct psi_predef_struct *predef_struct;
-       struct psi_predef_union *predef_union;
-       struct psi_predef_decl *predef_decl;
-
        if (!C) {
                C = malloc(sizeof(*C));
        }
@@ -88,132 +75,6 @@ struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_o
        assert(ops->call != NULL);
        assert(ops->compile != NULL);
 
-       /* build up predefs in a temporary PSI_Data for validation */
-       memset(&T, 0, sizeof(T));
-       psi_data_ctor_with_dtors(&T, error, flags);
-
-       for (predef_type = &psi_predef_types[0]; predef_type->type_tag; ++predef_type) {
-               struct psi_decl_type *type = psi_decl_type_init(predef_type->type_tag, predef_type->type_name);
-               struct psi_decl_var *var = psi_decl_var_init(predef_type->alias, 0, 0); /* FIXME: indirection */
-               struct psi_decl_arg *def = psi_decl_arg_init(type, var);
-
-               T.types = psi_plist_add(T.types, &def);
-       }
-       for (predef_const = &psi_predef_consts[0]; predef_const->type_tag; ++predef_const) {
-               struct psi_impl_def_val *val = psi_impl_def_val_init(predef_const->val_type_tag, predef_const->val_text);
-               struct psi_const_type *type = psi_const_type_init(predef_const->type_tag, predef_const->type_name);
-               struct psi_const *constant = psi_const_init(type, predef_const->var_name, val);
-
-               T.consts = psi_plist_add(T.consts, &constant);
-       }
-       for (predef_struct = &psi_predef_structs[0]; predef_struct->type_tag; ++predef_struct) {
-               struct psi_predef_struct *member;
-               struct psi_plist *dargs = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-               struct psi_decl_struct *dstruct = psi_decl_struct_init(predef_struct->var_name, dargs);
-
-               dstruct->size = predef_struct->size;
-               dstruct->align = predef_struct->offset;
-               for (member = &predef_struct[1]; member->type_tag; ++member) {
-                       struct psi_decl_type *type;
-                       struct psi_decl_var *dvar;
-                       struct psi_decl_arg *darg;
-
-                       type = psi_decl_type_init(member->type_tag, member->type_name);
-                       dvar = psi_decl_var_init(member->var_name, member->pointer_level, member->array_size);
-                       darg = psi_decl_arg_init(type, dvar);
-                       darg->layout = psi_layout_init(member->offset, member->size);
-                       dstruct->args = psi_plist_add(dstruct->args, &darg);
-               }
-
-               T.structs = psi_plist_add(T.structs, &dstruct);
-               predef_struct = member;
-       }
-       for (predef_union = &psi_predef_unions[0]; predef_union->type_tag; ++predef_union) {
-               struct psi_predef_union *member;
-               struct psi_plist *dargs = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-               struct psi_decl_union *dunion = psi_decl_union_init(predef_union->var_name, dargs);
-
-               dunion->size = predef_union->size;
-               dunion->align = predef_union->offset;
-               for (member = &predef_union[1]; member->type_tag; ++member) {
-                       struct psi_decl_type *type;
-                       struct psi_decl_var *dvar;
-                       struct psi_decl_arg *darg;
-
-                       type = psi_decl_type_init(member->type_tag, member->type_name);
-                       dvar = psi_decl_var_init(member->var_name, member->pointer_level, member->array_size);
-                       darg = psi_decl_arg_init(type, dvar);
-                       darg->layout = psi_layout_init(member->offset, member->size);
-                       dunion->args = psi_plist_add(dunion->args, &darg);
-               }
-
-               T.unions = psi_plist_add(T.unions, &dunion);
-               predef_union = member;
-       }
-       for (predef_decl = &psi_predef_decls[0]; predef_decl->type_tag; ++predef_decl) {
-               struct psi_predef_decl *farg;
-               struct psi_decl_type *ftype = psi_decl_type_init(predef_decl->type_tag, predef_decl->type_name);
-               struct psi_decl_var *fname = psi_decl_var_init(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
-               struct psi_decl_arg *func = psi_decl_arg_init(ftype, fname);
-               struct psi_plist *args = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-               struct psi_decl *decl = psi_decl_init(psi_decl_abi_init("default"), func, args);
-
-               for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
-                       struct psi_decl_type *arg_type = psi_decl_type_init(farg->type_tag, farg->type_name);
-                       struct psi_decl_var *arg_var = psi_decl_var_init(farg->var_name, farg->pointer_level, farg->array_size);
-                       struct psi_decl_arg *darg = psi_decl_arg_init(arg_type, arg_var);
-                       decl->args = psi_plist_add(decl->args, &darg);
-               }
-
-               T.decls = psi_plist_add(T.decls, &decl);
-               predef_decl = farg;
-       }
-
-       for (predef_decl = &psi_predef_vararg_decls[0]; predef_decl->type_tag; ++predef_decl) {
-               struct psi_predef_decl *farg;
-               struct psi_decl_type *ftype = psi_decl_type_init(predef_decl->type_tag, predef_decl->type_name);
-               struct psi_decl_var *fname = psi_decl_var_init(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
-               struct psi_decl_arg *func = psi_decl_arg_init(ftype, fname);
-               struct psi_plist *args = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-               struct psi_decl *decl = psi_decl_init(psi_decl_abi_init("default"), func, args);
-
-               for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
-                       struct psi_decl_type *arg_type = psi_decl_type_init(farg->type_tag, farg->type_name);
-                       struct psi_decl_var *arg_var = psi_decl_var_init(farg->var_name, farg->pointer_level, farg->array_size);
-                       struct psi_decl_arg *darg = psi_decl_arg_init(arg_type, arg_var);
-                       decl->args = psi_plist_add(decl->args, &darg);
-               }
-               decl->varargs = 1;
-
-               T.decls = psi_plist_add(T.decls, &decl);
-               predef_decl = farg;
-       }
-
-       for (predef_decl = &psi_predef_functor_decls[0]; predef_decl->type_tag; ++predef_decl) {
-               struct psi_predef_decl *farg;
-               struct psi_decl_type *dtype, *ftype = psi_decl_type_init(predef_decl->type_tag, predef_decl->type_name);
-               struct psi_decl_var *fname = psi_decl_var_init(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
-               struct psi_decl_arg *tdef, *func = psi_decl_arg_init(ftype, fname);
-               struct psi_plist *args = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-               struct psi_decl *decl = psi_decl_init(psi_decl_abi_init("default"), func, args);
-
-               for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
-                       struct psi_decl_type *arg_type = psi_decl_type_init(farg->type_tag, farg->type_name);
-                       struct psi_decl_var *arg_var = psi_decl_var_init(farg->var_name, farg->pointer_level, farg->array_size);
-                       struct psi_decl_arg *darg = psi_decl_arg_init(arg_type, arg_var);
-                       decl->args = psi_plist_add(decl->args, &darg);
-               }
-
-               dtype = psi_decl_type_init(PSI_T_FUNCTION, fname->name);
-               dtype->real.func = decl;
-               tdef = psi_decl_arg_init(dtype, psi_decl_var_copy(fname));
-               T.types = psi_plist_add(T.types, &tdef);
-
-               predef_decl = farg;
-       }
-
-       psi_context_add_data(C, &T);
-
        return C;
 }
 
@@ -225,6 +86,23 @@ static int psi_select_dirent(const struct dirent *entry)
        return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
 }
 
+static bool psi_context_add(struct psi_context *C, struct psi_parser *P)
+{
+       bool valid;
+       struct psi_data *D;
+       struct psi_validate_scope scope = {0};
+
+       C->data = realloc(C->data, (C->count + 1) * sizeof(*C->data));
+       D = psi_data_exchange(&C->data[C->count++], PSI_DATA(P));
+
+       psi_validate_scope_ctor(&scope);
+       scope.defs = &P->preproc->defs;
+       valid = psi_validate(&scope, PSI_DATA(C), D);
+       psi_validate_scope_dtor(&scope);
+
+       return valid;
+}
+
 void psi_context_build(struct psi_context *C, const char *paths)
 {
        int i, n;
@@ -245,6 +123,7 @@ void psi_context_build(struct psi_context *C, const char *paths)
                        for (i = 0; i < n; ++i) {
                                char psi[MAXPATHLEN];
                                struct psi_parser P;
+                               struct psi_parser_input *I;
 
                                if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) {
                                        C->error(PSI_DATA(C), NULL, PSI_WARNING, "Path to PSI file too long: %s/%s",
@@ -255,22 +134,15 @@ void psi_context_build(struct psi_context *C, const char *paths)
                                                psi, strerror(errno));
                                        continue;
                                }
-                               if (!psi_parser_open_file(&P, psi)) {
+                               if (!(I = psi_parser_open_file(&P, psi, true))) {
                                        C->error(PSI_DATA(C), NULL, PSI_WARNING, "Failed to open PSI file (%s): %s",
                                                psi, strerror(errno));
                                        continue;
                                }
-
-                               while (0 < psi_parser_scan(&P)) {
-                                       psi_parser_parse(&P, psi_token_alloc(&P));
-                                       if (P.num == PSI_T_EOF) {
-                                               break;
-                                       }
-                               }
-
-                               psi_parser_parse(&P, NULL);
-                               psi_context_add_data(C, PSI_DATA(&P));
+                               psi_parser_parse(&P, I);
+                               psi_context_add(C, &P);
                                psi_parser_dtor(&P);
+                               psi_parser_input_free(&I);
                        }
                }
 
@@ -296,36 +168,47 @@ zend_function_entry *psi_context_compile(struct psi_context *C)
 {
        zend_constant zc;
 
-       zc.flags = CONST_PERSISTENT|CONST_CS;
-       zc.module_number = EG(current_module)->module_number;
+       ZEND_CONSTANT_SET_FLAGS(&zc, CONST_CS|CONST_PERSISTENT, EG(current_module)->module_number);
 
        if (C->consts) {
                size_t i = 0;
                struct psi_const *c;
 
                while (psi_plist_get(C->consts, i++, &c)) {
-                       zc.name = zend_string_init(c->name + (c->name[0] == '\\'), strlen(c->name) - (c->name[0] == '\\'), 1);
-                       ZVAL_NEW_STR(&zc.value, zend_string_init(c->val->text, strlen(c->val->text), 1));
+
+                       if (zend_get_constant(c->name)) {
+                               continue;
+                       }
+
+                       zc.name = zend_string_copy(c->name);
 
                        switch (c->type->type) {
                        case PSI_T_BOOL:
-                               convert_to_boolean(&zc.value);
+                               ZVAL_BOOL(&zc.value, c->val->ival.zend.bval);
                                break;
                        case PSI_T_INT:
-                               convert_to_long(&zc.value);
+                               ZVAL_LONG(&zc.value, c->val->ival.zend.lval);
                                break;
                        case PSI_T_FLOAT:
-                               convert_to_double(&zc.value);
+                       case PSI_T_DOUBLE:
+                               ZVAL_DOUBLE(&zc.value, c->val->ival.dval);
                                break;
                        case PSI_T_STRING:
                        case PSI_T_QUOTED_STRING:
+                               ZVAL_NEW_STR(&zc.value, zend_string_copy(c->val->ival.zend.str));
+                               if (ZSTR_IS_INTERNED(Z_STR(zc.value))) {
+                                       Z_TYPE_FLAGS(zc.value) = 0;
+                               }
                                break;
                        default:
                                assert(0);
+                               break;
                        }
+
                        zend_register_constant(&zc);
                }
        }
+
        if (C->enums) {
                size_t i = 0;
                struct psi_decl_enum *e;
@@ -335,10 +218,21 @@ zend_function_entry *psi_context_compile(struct psi_context *C)
                        struct psi_decl_enum_item *item;
 
                        while (psi_plist_get(e->items, j++, &item)) {
-                               zend_string *name = strpprintf(0, "psi\\%s\\%s", e->name, item->name);
+                               zend_string *name;
+
+                               if (psi_decl_type_is_anon(e->name, "enum")) {
+                                       name = strpprintf(0, "psi\\%s", item->name->val);
+                               } else {
+                                       name = strpprintf(0, "psi\\%s\\%s", e->name->val, item->name->val);
+                               }
+
+                               if (zend_get_constant(name)) {
+                                       zend_string_release(name);
+                                       continue;
+                               }
 
                                zc.name = zend_string_dup(name, 1);
-                               ZVAL_LONG(&zc.value, psi_long_num_exp(item->num, NULL));
+                               ZVAL_LONG(&zc.value, psi_num_exp_get_long(item->num, NULL, NULL));
                                zend_register_constant(&zc);
                                zend_string_release(name);
                        }
@@ -370,7 +264,22 @@ ZEND_RESULT_CODE psi_context_call(struct psi_context *C, zend_execute_data *exec
                return FAILURE;
        }
 
-       psi_call_frame_do_call(frame);
+       if (SUCCESS != psi_call_frame_do_assert(frame, PSI_ASSERT_PRE)) {
+               psi_call_frame_do_return(frame, return_value);
+               psi_call_frame_free(frame);
+
+               return FAILURE;
+       }
+
+       C->ops->call(frame);
+
+       if (SUCCESS != psi_call_frame_do_assert(frame, PSI_ASSERT_POST)) {
+               psi_call_frame_do_return(frame, return_value);
+               psi_call_frame_free(frame);
+
+               return FAILURE;
+       }
+
        psi_call_frame_do_return(frame, return_value);
        psi_call_frame_do_set(frame);
        psi_call_frame_do_free(frame);
@@ -415,29 +324,15 @@ void psi_context_free(struct psi_context **C)
        }
 }
 
-bool psi_context_add_data(struct psi_context *C, struct psi_data *P)
-{
-       struct psi_data *D;
-
-       C->data = realloc(C->data, (C->count + 1) * sizeof(*C->data));
-       D = psi_data_exchange(&C->data[C->count++], P);
-
-       return psi_data_validate(PSI_DATA(C), D);
-}
-
 void psi_context_dump(struct psi_context *C, int fd)
 {
+       size_t i;
 
-       dprintf(fd, "// psi.engine=%s\n",
-                       (char *) C->ops->query(C, PSI_CONTEXT_QUERY_SELF, NULL));
-
-       psi_data_dump(fd, PSI_DATA(C));
-
-//     size_t i;
-//     dprintf(fd, "/* parsed\n");
-//     for (i = 0; i < C->count; ++i) {
-//             psi_data_dump(fd, &C->data[i]);
-//     }
-//     dprintf(fd, "*/\n");
+       dprintf(fd, "// psi.engine=%s\n// %lu files\n",
+                       (char *) C->ops->query(C, PSI_CONTEXT_QUERY_SELF, NULL),
+                       C->count);
 
+       for (i = 0; i < C->count; ++i) {
+               psi_data_dump(fd, &C->data[i]);
+       }
 }