flush
[m6w6/ext-psi] / src / module.c
1
2 #ifdef HAVE_CONFIG_H
3 # include "config.h"
4 #endif
5
6 #include "php.h"
7 #include "php_ini.h"
8 #include "ext/standard/info.h"
9 #include "zend_constants.h"
10 #include "zend_operators.h"
11
12 #include "php_psi.h"
13
14 #if HAVE_LIBJIT
15 # include "libjit.h"
16 # ifndef HAVE_LIBFFI
17 # define PSI_ENGINE "jit"
18 # endif
19 #endif
20 #if HAVE_LIBFFI
21 # include "libffi.h"
22 # define PSI_ENGINE "ffi"
23 #endif
24
25 ZEND_DECLARE_MODULE_GLOBALS(psi);
26
27 PHP_INI_BEGIN()
28 STD_PHP_INI_ENTRY("psi.engine", PSI_ENGINE, PHP_INI_SYSTEM, OnUpdateString, engine, zend_psi_globals, psi_globals)
29 STD_PHP_INI_ENTRY("psi.directory", "psi.d", PHP_INI_SYSTEM, OnUpdateString, directory, zend_psi_globals, psi_globals)
30 PHP_INI_END();
31
32 static zend_object_handlers psi_object_handlers;
33 static zend_class_entry *psi_class_entry;
34
35 zend_class_entry *psi_object_get_class_entry()
36 {
37 return psi_class_entry;
38 }
39
40 void psi_error_wrapper(void *context, PSI_Token *t, int type, const char *msg, ...)
41 {
42 va_list argv;
43 const char *fn = NULL;
44 unsigned ln = 0;
45
46 if (context) {
47 if (PSI_DATA(context)->flags & PSI_PARSER_SILENT) {
48 return;
49 }
50 }
51
52 if (t) {
53 fn = t->file;
54 ln = t->line;
55 } else if (zend_is_executing()) {
56 fn = zend_get_executed_filename();
57 ln = zend_get_executed_lineno();
58 } else if (zend_is_compiling()) {
59 fn = zend_get_compiled_filename()->val;
60 ln = zend_get_compiled_lineno();
61 }
62
63 va_start(argv, msg);
64 psi_verror(type, fn, ln, msg, argv);
65 va_end(argv);
66 }
67
68 void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...)
69 {
70 va_list argv;
71
72 va_start(argv, msg);
73 psi_verror(type, fn, ln, msg, argv);
74 va_end(argv);
75 }
76
77 void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv)
78 {
79 zend_error_cb(type, fn, ln, msg, argv);
80 }
81
82 static void psi_object_free(zend_object *o)
83 {
84 psi_object *obj = PSI_OBJ(NULL, o);
85
86 if (obj->data) {
87 /* FIXME: how about registering a destructor?
88 // free(obj->data); */
89 obj->data = NULL;
90 }
91 zend_object_std_dtor(o);
92 }
93
94 static zend_object *psi_object_init(zend_class_entry *ce)
95 {
96 psi_object *o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce));
97
98 zend_object_std_init(&o->std, ce);
99 object_properties_init(&o->std, ce);
100 o->std.handlers = &psi_object_handlers;
101 return &o->std;
102 }
103
104 ZEND_BEGIN_ARG_INFO_EX(ai_psi_dump, 0, 0, 0)
105 ZEND_ARG_INFO(0, stream)
106 ZEND_END_ARG_INFO();
107 static PHP_FUNCTION(psi_dump) {
108 php_stream *s;
109 zval *r = NULL;
110 int fd = STDOUT_FILENO;
111
112 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &r)) {
113 return;
114 }
115 if (r) {
116 php_stream_from_zval(s, r);
117
118 if (SUCCESS != php_stream_cast(s, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL, (void **)&fd, 1)) {
119 RETURN_FALSE;
120 }
121 }
122 PSI_ContextDump(&PSI_G(context), fd);
123 }
124
125 ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate, 0, 0, 1)
126 ZEND_ARG_INFO(0, file)
127 ZEND_END_ARG_INFO();
128 static PHP_FUNCTION(psi_validate) {
129 zend_string *file;
130 PSI_Parser P;
131
132 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file)) {
133 return;
134 }
135
136 if (!PSI_ParserInit(&P, file->val, psi_error_wrapper, 0)) {
137 RETURN_FALSE;
138 }
139
140 while (0 < PSI_ParserScan(&P)) {
141 PSI_ParserParse(&P, PSI_TokenAlloc(&P));
142 if (P.num == PSI_T_EOF) {
143 break;
144 }
145 }
146 PSI_ParserParse(&P, NULL);
147
148 if (0 == PSI_ContextValidateData(NULL, PSI_DATA(&P)) && !P.errors) {
149 RETVAL_TRUE;
150 } else {
151 RETVAL_FALSE;
152 }
153 PSI_ParserDtor(&P);
154 }
155
156 static PHP_MINIT_FUNCTION(psi)
157 {
158 PSI_ContextOps *ops = NULL;
159 zend_class_entry ce = {0};
160 unsigned flags = psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG : (
161 psi_check_env("PSI_SILENT") ? PSI_PARSER_SILENT : 0);
162
163 REGISTER_INI_ENTRIES();
164
165 INIT_NS_CLASS_ENTRY(ce, "psi", "object", NULL);
166 psi_class_entry = zend_register_internal_class_ex(&ce, NULL);
167 psi_class_entry->create_object = psi_object_init;
168
169 memcpy(&psi_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
170 psi_object_handlers.offset = XtOffsetOf(psi_object, std);
171 psi_object_handlers.free_obj = psi_object_free;
172 psi_object_handlers.clone_obj = NULL;
173
174 #ifdef HAVE_LIBJIT
175 if (!strcasecmp(PSI_G(engine), "jit")) {
176 ops = PSI_Libjit();
177 } else
178 #endif
179 #ifdef HAVE_LIBFFI
180 ops = PSI_Libffi();
181 #endif
182
183 if (!ops) {
184 php_error(E_WARNING, "No PSI engine found");
185 return FAILURE;
186 }
187
188 PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper, flags);
189 PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
190
191 if (psi_check_env("PSI_DUMP")) {
192 PSI_ContextDump(&PSI_G(context), STDOUT_FILENO);
193 }
194
195 return SUCCESS;
196 }
197
198 static PHP_MSHUTDOWN_FUNCTION(psi)
199 {
200 PSI_ContextDtor(&PSI_G(context));
201
202 UNREGISTER_INI_ENTRIES();
203
204 return SUCCESS;
205 }
206
207 #if defined(COMPILE_DL_PSI) && defined(ZTS)
208 static PHP_RINIT_FUNCTION(psi)
209 {
210 ZEND_TSRMLS_CACHE_UPDATE();
211 return SUCCESS;
212 }
213 #endif
214
215 static PHP_MINFO_FUNCTION(psi)
216 {
217 php_info_print_table_start();
218 php_info_print_table_header(2, "psi support", "enabled");
219 php_info_print_table_end();
220
221 DISPLAY_INI_ENTRIES();
222 }
223
224 static const zend_function_entry psi_functions[] = {
225 PHP_FE(psi_dump, ai_psi_dump)
226 PHP_FE(psi_validate, ai_psi_validate)
227 PHP_FE_END
228 };
229
230 zend_module_entry psi_module_entry = {
231 STANDARD_MODULE_HEADER,
232 "psi",
233 psi_functions,
234 PHP_MINIT(psi),
235 PHP_MSHUTDOWN(psi),
236 #if defined(COMPILE_DL_PSI) && defined(ZTS)
237 PHP_RINIT(psi), /* Replace with NULL if there's nothing to do at request start */
238 #else
239 NULL,
240 #endif
241 NULL,
242 PHP_MINFO(psi),
243 PHP_PSI_VERSION,
244 STANDARD_MODULE_PROPERTIES
245 };
246
247 #ifdef COMPILE_DL_PSI
248 #ifdef ZTS
249 ZEND_TSRMLS_CACHE_DEFINE();
250 #endif
251 ZEND_GET_MODULE(psi)
252 #endif
253
254 /*
255 * Local variables:
256 * tab-width: 4
257 * c-basic-offset: 4
258 * End:
259 * vim600: noet sw=4 ts=4 fdm=marker
260 * vim<600: noet sw=4 ts=4
261 */