set psi as module for register functions
[m6w6/ext-psi] / src / context.c
index 995a0010498aa1d11c75f236b57183f130dbf55a..9b5730ed64736fe121866a0f04c2d807f34c233a 100644 (file)
 
 #include "php_psi_posix.h"
 
+PHP_MINIT_FUNCTION(psi_context)
+{
+       unsigned flags = 0;
+       struct psi_context_ops *ops = NULL;
+
+#ifdef HAVE_LIBJIT
+       if (!strcasecmp(PSI_G(engine), "jit")) {
+               ops = psi_libjit_ops();
+       } else
+#endif
+#ifdef HAVE_LIBFFI
+               ops = psi_libffi_ops();
+#endif
+
+       if (!ops) {
+               php_error(E_WARNING, "No PSI engine found");
+               return FAILURE;
+       }
+
+       PSI_G(ops) = ops;
+       if (ops->load && SUCCESS != ops->load()) {
+               return FAILURE;
+       }
+
+       if (psi_check_env("PSI_DEBUG")) {
+               flags |= PSI_DEBUG;
+       }
+       if (psi_check_env("PSI_SILENT")) {
+               flags |= PSI_SILENT;
+       }
+
+       PSI_G(context) = psi_context_init(NULL, PSI_G(ops), psi_error_wrapper, flags);
+       psi_context_build(PSI_G(context), PSI_G(directory));
+
+       return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(psi_context)
+{
+       if (psi_check_env("PSI_DUMP")) {
+               struct psi_dump dump = {{.hn = stdout}, (psi_dump_cb) fprintf};
+
+               psi_context_dump(&dump, PSI_G(context));
+       }
+
+       psi_context_free(&PSI_G(context));
+
+       if (PSI_G(ops)->free) {
+               PSI_G(ops)->free();
+       }
+
+       return SUCCESS;
+}
+
 struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_error_cb error, unsigned flags)
 {
        if (!C) {
-               C = malloc(sizeof(*C));
+               C = pemalloc(sizeof(*C), 1);
        }
        memset(C, 0, sizeof(*C));
 
@@ -92,11 +146,11 @@ static bool psi_context_add(struct psi_context *C, struct psi_parser *P)
        struct psi_data *D;
        struct psi_validate_scope scope = {0};
 
-       C->data = realloc(C->data, (C->count + 1) * sizeof(*C->data));
+       C->data = safe_perealloc(C->data, (C->count + 1), sizeof(*C->data), 0, 1);
        D = psi_data_exchange(&C->data[C->count++], PSI_DATA(P));
 
        psi_validate_scope_ctor(&scope);
-       scope.defs = &P->preproc->defs;
+       scope.cpp = P->preproc;
        valid = psi_validate(&scope, PSI_DATA(C), D);
        psi_validate_scope_dtor(&scope);
 
@@ -142,7 +196,7 @@ void psi_context_build(struct psi_context *C, const char *paths)
                                psi_parser_parse(&P, I);
                                psi_context_add(C, &P);
                                psi_parser_dtor(&P);
-                               free(I);
+                               psi_parser_input_free(&I);
                        }
                }
 
@@ -157,13 +211,35 @@ void psi_context_build(struct psi_context *C, const char *paths)
        } while (sep);
 
 
-       if (psi_context_compile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
-               C->error(PSI_DATA(C), NULL, PSI_WARNING, "Failed to register functions!");
+       if (psi_context_compile(C)) {
+               /* zend_register_functions depends on EG(current_module) pointing into module */
+               EG(current_module) = zend_hash_str_find_ptr(&module_registry, "psi", sizeof("psi") - 1);
+               if (SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
+                       C->error(PSI_DATA(C), NULL, PSI_WARNING, "Failed to register functions!");
+               }
+               EG(current_module) = NULL;
        }
 
        free(cpy);
 }
 
+#include <ctype.h>
+static inline bool prefix_match(zend_string *a, zend_string *b)
+{
+       size_t i;
+
+       for (i = 0; i < a->len && i < b->len; ++i) {
+               if (tolower(a->val[i]) != tolower(b->val[i])) {
+                       return false;
+               }
+               if (i && a->val[i] == '_') {
+                       break;
+               }
+       }
+
+       return true;
+}
+
 zend_function_entry *psi_context_compile(struct psi_context *C)
 {
        zend_constant zc;
@@ -181,26 +257,7 @@ zend_function_entry *psi_context_compile(struct psi_context *C)
                        }
 
                        zc.name = zend_string_copy(c->name);
-
-                       switch (c->type->type) {
-                       case PSI_T_BOOL:
-                               ZVAL_BOOL(&zc.value, c->val->ival.zend.bval);
-                               break;
-                       case PSI_T_INT:
-                               ZVAL_LONG(&zc.value, c->val->ival.zend.lval);
-                               break;
-                       case PSI_T_FLOAT:
-                       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));
-                               break;
-                       default:
-                               assert(0);
-                               break;
-                       }
+                       psi_impl_def_val_get_zval(c->val, c->type ? c->type->type : PSI_T_MIXED, &zc.value);
 
                        zend_register_constant(&zc);
                }
@@ -217,9 +274,11 @@ zend_function_entry *psi_context_compile(struct psi_context *C)
                        while (psi_plist_get(e->items, j++, &item)) {
                                zend_string *name;
 
-                               if (psi_decl_type_is_anon(e->name, "enum")) {
+                               if (psi_decl_type_is_anon(e->name, "enum")
+                                               || prefix_match(e->name, item->name)) {
                                        name = strpprintf(0, "psi\\%s", item->name->val);
                                } else {
+
                                        name = strpprintf(0, "psi\\%s\\%s", e->name->val, item->name->val);
                                }
 
@@ -321,15 +380,21 @@ void psi_context_free(struct psi_context **C)
        }
 }
 
-void psi_context_dump(struct psi_context *C, int fd)
+void psi_context_dump(struct psi_dump *dump, struct psi_context *C)
 {
-       size_t i;
-
-       dprintf(fd, "// psi.engine=%s\n// %lu files\n",
+       PSI_DUMP(dump, "// 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]);
+       psi_data_dump(dump, PSI_DATA(C));
+
+#if 0
+       if (C->flags & PSI_DEBUG) {
+               size_t i;
+
+               for (i = 0; i < C->count; ++i) {
+                       psi_data_dump(dump, &C->data[i]);
+               }
        }
+#endif
 }