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