57b6f4d0c0b936ad7b2b48eed3e860d5582d10c0
[m6w6/ext-psi] / src / data.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include "php_psi.h"
28 #include "data.h"
29
30 #include "php_globals.h"
31 #include "zend_types.h"
32
33 #include <dlfcn.h>
34 #include <ctype.h>
35
36 #if PSI_THREADED_PARSER
37 # include <pthread.h>
38
39 pthread_mutex_t psi_string_mutex = PTHREAD_MUTEX_INITIALIZER;
40
41 zend_string *psi_string_init_interned(const char *buf, size_t len, int p)
42 {
43 zend_string *str;
44
45 pthread_mutex_lock(&psi_string_mutex);
46 str = zend_string_init_interned(buf, len, p);
47 pthread_mutex_unlock(&psi_string_mutex);
48
49 return str;
50 }
51
52 zend_string *psi_new_interned_string(zend_string *str)
53 {
54 zend_string *new_str;
55
56 pthread_mutex_lock(&psi_string_mutex);
57 new_str = zend_new_interned_string(str);
58 pthread_mutex_unlock(&psi_string_mutex);
59
60 return new_str;
61 }
62
63 #endif
64
65 static void psi_data_ctor_internal(struct psi_data *data,
66 psi_error_cb error, unsigned flags)
67 {
68 data->error = error;
69 data->flags = flags;
70
71 if (data->flags & PSI_DEBUG) {
72 int fd = psi_fdopen(getenv("PSI_DEBUG"));
73
74 if (fd > 0) {
75 data->debug_fd = fd;
76 } else {
77 data->debug_fd = STDERR_FILENO;
78 }
79 }
80 }
81
82 struct psi_data *psi_data_ctor_with_dtors(struct psi_data *data,
83 psi_error_cb error, unsigned flags)
84 {
85 if (!data) {
86 data = pecalloc(1, sizeof(*data), 1);
87 }
88
89 psi_data_ctor_internal(data, error, flags);
90
91 if (!data->file.libnames) {
92 data->file.libnames = psi_plist_init((psi_plist_dtor) psi_names_free);
93 }
94 if (!data->file.dlopened) {
95 data->file.dlopened = psi_plist_init((psi_plist_dtor) psi_libs_free);
96 }
97
98 if (!data->consts) {
99 data->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
100 }
101 if (!data->types) {
102 data->types = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
103 }
104 if (!data->structs) {
105 data->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
106 }
107 if (!data->unions) {
108 data->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
109 }
110 if (!data->enums) {
111 data->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
112 }
113 if (!data->decls) {
114 data->decls = psi_plist_init((psi_plist_dtor) psi_decl_free);
115 }
116 if (!data->vars) {
117 data->vars = psi_plist_init((psi_plist_dtor) psi_decl_extvar_free);
118 }
119 if (!data->impls) {
120 data->impls = psi_plist_init((psi_plist_dtor) psi_impl_free);
121 }
122 return data;
123 }
124
125 struct psi_data *psi_data_ctor(struct psi_data *data, psi_error_cb error,
126 unsigned flags)
127 {
128 if (!data) {
129 data = pecalloc(1, sizeof(*data), 1);
130 }
131
132 psi_data_ctor_internal(data, error, flags);
133
134 if (!data->file.libnames) {
135 data->file.libnames = psi_plist_init(NULL);
136 }
137 if (!data->file.dlopened) {
138 data->file.dlopened = psi_plist_init(NULL);
139 }
140
141 if (!data->consts) {
142 data->consts = psi_plist_init(NULL);
143 }
144 if (!data->types) {
145 data->types = psi_plist_init(NULL);
146 }
147 if (!data->structs) {
148 data->structs = psi_plist_init(NULL);
149 }
150 if (!data->unions) {
151 data->unions = psi_plist_init(NULL);
152 }
153 if (!data->enums) {
154 data->enums = psi_plist_init(NULL);
155 }
156 if (!data->decls) {
157 data->decls = psi_plist_init(NULL);
158 }
159 if (!data->vars) {
160 data->vars = psi_plist_init(NULL);
161 }
162 if (!data->impls) {
163 data->impls = psi_plist_init(NULL);
164 }
165 return data;
166 }
167
168 struct psi_data *psi_data_exchange(struct psi_data *dest, struct psi_data *src)
169 {
170 if (!dest) {
171 dest = pemalloc(sizeof(*dest), 1);
172 }
173 *dest = *src;
174 memset(src, 0, sizeof(*src));
175 return dest;
176 }
177
178 void psi_data_dtor(struct psi_data *data)
179 {
180 if (data->debug_fd) {
181 close(data->debug_fd);
182 }
183 if (data->consts) {
184 psi_plist_free(data->consts);
185 }
186 if (data->types) {
187 psi_plist_free(data->types);
188 }
189 if (data->structs) {
190 psi_plist_free(data->structs);
191 }
192 if (data->unions) {
193 psi_plist_free(data->unions);
194 }
195 if (data->enums) {
196 psi_plist_free(data->enums);
197 }
198 if (data->decls) {
199 psi_plist_free(data->decls);
200 }
201 if (data->vars) {
202 psi_plist_free(data->vars);
203 }
204 if (data->impls) {
205 psi_plist_free(data->impls);
206 }
207
208 psi_decl_file_dtor(&data->file);
209 }
210
211 void psi_data_dump(struct psi_dump *dump, struct psi_data *D)
212 {
213 size_t i = 0;
214 char *libname;
215
216 if (D->file.filename) {
217 PSI_DUMP(dump, "// filename=%s (%u errors)\n", D->file.filename->val, D->errors);
218 }
219 while (psi_plist_get(D->file.libnames, i++, &libname)) {
220 PSI_DUMP(dump, "lib \"%s\";\n", libname);
221 }
222 if (psi_plist_count(D->types)) {
223 size_t i = 0;
224 struct psi_decl_arg *def;
225
226 while (psi_plist_get(D->types, i++, &def)) {
227 PSI_DUMP(dump, "typedef ");
228 psi_decl_arg_dump(dump, def, 0);
229 PSI_DUMP(dump, ";\n");
230 }
231 PSI_DUMP(dump, "\n");
232 }
233 if (psi_plist_count(D->unions)) {
234 size_t i = 0;
235 struct psi_decl_union *unn;
236
237 while (psi_plist_get(D->unions, i++, &unn)) {
238 if (!psi_decl_type_is_anon(unn->name, "union")) {
239 psi_decl_union_dump(dump, unn);
240 PSI_DUMP(dump, "\n");
241 }
242 }
243 PSI_DUMP(dump, "\n");
244 }
245 if (psi_plist_count(D->structs)) {
246 size_t i = 0;
247 struct psi_decl_struct *strct;
248
249 while (psi_plist_get(D->structs, i++, &strct)) {
250 if (!psi_decl_type_is_anon(strct->name, "struct")) {
251 psi_decl_struct_dump(dump, strct);
252 PSI_DUMP(dump, "\n");
253 }
254 }
255 PSI_DUMP(dump, "\n");
256 }
257 if (psi_plist_count(D->enums)) {
258 size_t i = 0;
259 struct psi_decl_enum *enm;
260
261 while (psi_plist_get(D->enums, i++, &enm)) {
262 if (true || !psi_decl_type_is_anon(enm->name, "enum")) {
263 psi_decl_enum_dump(dump, enm, 0);
264 PSI_DUMP(dump, "\n");
265 }
266 }
267 PSI_DUMP(dump, "\n");
268 }
269 if (psi_plist_count(D->consts)) {
270 size_t i = 0;
271 struct psi_const *c;
272
273 while (psi_plist_get(D->consts, i++, &c)) {
274 psi_const_dump(dump, c);
275 PSI_DUMP(dump, "\n");
276 }
277 PSI_DUMP(dump, "\n");
278 }
279 if (psi_plist_count(D->decls)) {
280 size_t i = 0;
281 struct psi_decl *decl;
282
283 while (psi_plist_get(D->decls, i++, &decl)) {
284 if (decl->extvar) {
285 PSI_DUMP(dump, "/* extvar accessor \n");
286 }
287 psi_decl_dump(dump, decl);
288 if (decl->extvar) {
289 PSI_DUMP(dump, " */");
290 }
291 PSI_DUMP(dump, "\n");
292 }
293 PSI_DUMP(dump, "\n");
294 }
295 if (psi_plist_count(D->vars)) {
296 size_t i = 0;
297 struct psi_decl_extvar *evar;
298
299 while (psi_plist_get(D->vars, i++, &evar)) {
300 psi_decl_extvar_dump(dump, evar);
301 }
302 PSI_DUMP(dump, "\n");
303 }
304 if (psi_plist_count(D->impls)) {
305 size_t i = 0;
306 struct psi_impl *impl;
307
308 while (psi_plist_get(D->impls, i++, &impl)) {
309 psi_impl_dump(dump, impl);
310 PSI_DUMP(dump, "\n");
311 }
312 PSI_DUMP(dump, "\n");
313 }
314 }