flush
[m6w6/ext-psi] / src / module.c
1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include <jit/jit.h>
7 #include <dirent.h>
8 #include <fnmatch.h>
9
10 #include "php.h"
11 #include "php_ini.h"
12 #include "ext/standard/info.h"
13 #include "php_scandir.h"
14
15 #include "php_psi.h"
16
17 #include "parser.h"
18 #include "validator.h"
19 #include "compiler.h"
20
21 ZEND_DECLARE_MODULE_GLOBALS(psi);
22
23 PHP_INI_BEGIN()
24 STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals)
25 PHP_INI_END();
26
27 static void psi_error(int type, const char *msg, ...)
28 {
29 char buf[0x1000];
30 va_list argv;
31
32 va_start(argv, msg);
33 vslprintf(buf, 0x1000, msg, argv);
34 va_end(argv);
35
36 php_error(type, buf);
37 }
38
39 static int psi_select_dirent(const struct dirent *entry)
40 {
41 #ifndef FNM_CASEFOLD
42 #define FNM_CASEFOLD 0
43 #endif
44 return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
45 }
46
47 PHP_MINIT_FUNCTION(psi)
48 {
49 jit_context_t ctx;
50 int i, n;
51 struct dirent **entries = NULL;
52
53 REGISTER_INI_ENTRIES();
54
55 jit_init();
56
57 if (!(ctx = jit_context_create())) {
58 zend_error(E_WARNING, "Could not initialize libjit!");
59 return FAILURE;
60 }
61
62 PSI_G(context) = ctx;
63
64 n = php_scandir(PSI_G(directory), &entries, psi_select_dirent, alphasort);
65 if (n < 0) {
66 php_error(E_WARNING, "Failed to scan PSI directory '%s'", PSI_G(directory));
67 } else for (i = 0; i < n; ++i) {
68 char psi[MAXPATHLEN];
69 PSI_Parser P;
70 PSI_Validator V;
71
72 if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", PSI_G(directory), entries[i]->d_name)) {
73 php_error(E_WARNING, "Path to PSI file too long: %s/%s",
74 PSI_G(directory), entries[i]->d_name);
75 }
76 if (!PSI_ParserInit(&P, psi, psi_error, 0)) {
77 php_error(E_WARNING, "Failed to init PSI parser (%s): %s",
78 psi, strerror(errno));
79 continue;
80 }
81
82 while (-1 != PSI_ParserScan(&P)) {
83 PSI_ParserParse(&P, PSI_TokenAlloc(&P));
84 };
85 PSI_ParserParse(&P, NULL);
86
87 if (!PSI_ValidatorInit(&V, &P)) {
88 php_error(E_WARNING, "Failed to init PSI validator");
89 break;
90 }
91 PSI_ParserDtor(&P);
92
93 if (PSI_ValidatorValidate(&V)) {
94 PSI_Compiler C;
95
96 jit_context_build_start(ctx);
97 if (PSI_CompilerInit(&C, &V, ctx)) {
98 zend_function_entry *closures = PSI_CompilerCompile(&C);
99
100 if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) {
101 psi_error(E_WARNING, "Failed to register functions!");
102 }
103 //PSI_CompilerDtor(&C);
104 }
105 jit_context_build_end(ctx);
106 }
107 PSI_ValidatorDtor(&V);
108 }
109 if (entries) {
110 for (i = 0; i < n; ++i) {
111 free(entries[i]);
112 }
113 free(entries);
114 }
115 return SUCCESS;
116 }
117 PHP_MSHUTDOWN_FUNCTION(psi)
118 {
119 jit_context_t ctx = PSI_G(context);
120 jit_context_destroy(ctx);
121
122 UNREGISTER_INI_ENTRIES();
123
124 return SUCCESS;
125 }
126
127 /* Remove if there's nothing to do at request start */
128 /* {{{ PHP_RINIT_FUNCTION
129 */
130 PHP_RINIT_FUNCTION(psi)
131 {
132 #if defined(COMPILE_DL_PSI) && defined(ZTS)
133 ZEND_TSRMLS_CACHE_UPDATE();
134 #endif
135 return SUCCESS;
136 }
137 /* }}} */
138
139 /* Remove if there's nothing to do at request end */
140 /* {{{ PHP_RSHUTDOWN_FUNCTION
141 */
142 PHP_RSHUTDOWN_FUNCTION(psi)
143 {
144 return SUCCESS;
145 }
146 /* }}} */
147
148 PHP_MINFO_FUNCTION(psi)
149 {
150 php_info_print_table_start();
151 php_info_print_table_header(2, "psi support", "enabled");
152 php_info_print_table_end();
153
154 DISPLAY_INI_ENTRIES();
155 }
156 const zend_function_entry psi_functions[] = {
157 PHP_FE_END
158 };
159
160 zend_module_entry psi_module_entry = {
161 STANDARD_MODULE_HEADER,
162 "psi",
163 psi_functions,
164 PHP_MINIT(psi),
165 PHP_MSHUTDOWN(psi),
166 PHP_RINIT(psi), /* Replace with NULL if there's nothing to do at request start */
167 PHP_RSHUTDOWN(psi), /* Replace with NULL if there's nothing to do at request end */
168 PHP_MINFO(psi),
169 PHP_PSI_VERSION,
170 STANDARD_MODULE_PROPERTIES
171 };
172
173 #ifdef COMPILE_DL_PSI
174 #ifdef ZTS
175 ZEND_TSRMLS_CACHE_DEFINE();
176 #endif
177 ZEND_GET_MODULE(psi)
178 #endif
179
180 /*
181 * Local variables:
182 * tab-width: 4
183 * c-basic-offset: 4
184 * End:
185 * vim600: noet sw=4 ts=4 fdm=marker
186 * vim<600: noet sw=4 ts=4
187 */