4e38929e1d42f9411468af53676f7b8b49233e9b
[m6w6/ext-psi] / src / validator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/param.h>
5 #include <dlfcn.h>
6
7 #include <jit/jit.h>
8
9 #include "validator.h"
10
11 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
12 {
13 if (!V) {
14 V = malloc(sizeof(*V));
15 }
16 memset(V, 0, sizeof(*V));
17
18 PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
19
20 return V;
21 }
22
23 void PSI_ValidatorDtor(PSI_Validator *V)
24 {
25 PSI_DataDtor((PSI_Data *) V);
26 memset(V, 0, sizeof(*V));
27 }
28
29 void PSI_ValidatorFree(PSI_Validator **V)
30 {
31 if (*V) {
32 PSI_ValidatorDtor(*V);
33 free(*V);
34 *V = NULL;
35 }
36 }
37
38 static int validate_lib(PSI_Validator *V) {
39 char lib[MAXPATHLEN];
40 const char *ptr = V->lib;
41 size_t len;
42
43 if (!ptr) {
44 /* FIXME: assume stdlib */
45 return 1;
46 } else if (!strchr(ptr, '/')) {
47 #ifdef DARWIN
48 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
49 #else
50 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
51 #endif
52 if (MAXPATHLEN == len) {
53 V->error(PSI_WARNING, "Library name too long: '%s'", ptr);
54 }
55 lib[len] = 0;
56 ptr = lib;
57 }
58 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
59 V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror());
60 return 0;
61 }
62 return 1;
63 }
64 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
65 size_t i;
66
67 if (type->real) {
68 return 1;
69 }
70 for (i = 0; i < defs->count; ++i) {
71 if (!strcmp(defs->list[i]->alias, type->name)) {
72 type->real = defs->list[i]->type;
73 return 1;
74 }
75 }
76 return 0;
77 }
78 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
79 if (type->type == PSI_T_NAME) {
80 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
81 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
82 " Use 'typedef <type> <basic_type>;' statement",
83 type->name, arg->var->name);
84 return 0;
85 }
86 }
87 return 1;
88 }
89 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
90 /* FIXME: check def->alias */
91 if (def->type->type == PSI_T_NAME) {
92 V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
93 def->type->name, def->alias);
94 return 0;
95 }
96 return 1;
97 }
98 static inline int validate_typedefs(PSI_Validator *V) {
99 size_t i;
100
101 for (i = 0; i < V->defs->count; ++i) {
102 if (!validate_typedef(V, V->defs->list[i])) {
103 return 0;
104 }
105 }
106
107 return 1;
108 }
109 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
110 {
111 if (!strcmp(func->var->name, "dlsym")) {
112 V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
113 return 0;
114 }
115
116 if (!validate_decl_type(V, func, func->type)) {
117 return 0;
118 }
119
120 decl->dlptr = dlsym(V->dlopened, func->var->name);
121 if (!decl->dlptr) {
122 V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
123 func->var->name, dlerror());
124 }
125 return 1;
126 }
127 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
128 if (strcasecmp(abi->convention, "default")) {
129 V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
130 return 0;
131 }
132 /* FIXME */
133 return 1;
134 }
135 static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) {
136 if (!validate_decl_type(V, arg, arg->type)) {
137 return 0;
138 }
139 return 1;
140 }
141 static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) {
142 size_t i;
143
144 for (i = 0; i < args->count; ++i) {
145 if (!validate_decl_arg(V, decl, args->args[i])) {
146 return 0;
147 }
148 }
149 return 1;
150 }
151 static inline int validate_decl(PSI_Validator *V, decl *decl) {
152 if (!validate_decl_abi(V, decl->abi)) {
153 return 0;
154 }
155 if (!validate_decl_func(V, decl, decl->func)) {
156 return 0;
157 }
158 if (decl->args && !validate_decl_args(V, decl, decl->args)) {
159 return 0;
160 }
161 return 1;
162 }
163 static inline int validate_decls(PSI_Validator *V) {
164 size_t i;
165
166 for (i = 0; i < V->decls->count; ++i) {
167 if (!validate_decl(V, V->decls->list[i])) {
168 return 0;
169 }
170 }
171 return 1;
172 }
173
174 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
175 /* FIXME */
176 return 1;
177 }
178 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
179 return 1;
180 }
181 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
182 size_t i;
183
184 for (i = 0; i < args->count; ++i) {
185 if (!validate_impl_arg(V, impl, args->args[i])) {
186 return 0;
187 }
188 }
189 return 1;
190 }
191 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
192 /* FIXME: does name need any validation? */
193 if (!validate_impl_type(V, impl, func->return_type)) {
194 return 0;
195 }
196 if (func->args && !validate_impl_args(V, impl, func->args)) {
197 return 0;
198 }
199 return 1;
200 }
201 static inline decl *locate_impl_decl(decls *decls, ret_stmt *ret) {
202 size_t i;
203
204 for (i = 0; i < decls->count; ++i) {
205 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
206 return decls->list[i];
207 }
208 }
209 return NULL;
210 }
211
212 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
213 /* okay,
214 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
215 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
216 * - we can have any count of set stmts; processing out vars, etc.
217 */
218 size_t i, j;
219 ret_stmt *ret;
220 decl *decl;
221
222 if (!stmts) {
223 V->error(PSI_WARNING, "Missing body for implementation %s!",
224 impl->func->name);
225 return 0;
226 }
227 if (stmts->ret.count != 1) {
228 if (stmts->ret.count > 1) {
229 V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
230 "found %zu, exactly one is needed",
231 impl->func->name, stmts->ret.count);
232 } else {
233 V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
234 impl->func->name);
235 }
236 return 0;
237 }
238
239 ret = stmts->ret.list[0];
240 decl = locate_impl_decl(V->decls, ret);
241 if (!decl) {
242 V->error(PSI_WARNING, "Missing declaration for implementation %s",
243 impl->func->name);
244 return 0;
245 }
246
247 /* check that we have a let stmt for every decl arg */
248 for (i = 0; i < decl->args->count; ++i) {
249 decl_arg *darg = decl->args->args[i];
250 int check = 0;
251
252 for (j = 0; j < stmts->let.count; ++j) {
253 let_stmt *let = stmts->let.list[j];
254
255 if (!strcmp(let->var->name, darg->var->name)) {
256 darg->let = let;
257 check = 1;
258 break;
259 }
260 }
261 if (!check) {
262 V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
263 "of declaration '%s' for implementation '%s'",
264 darg->type->name, (int) darg->var->pointer_level, "*****",
265 darg->var->name, decl->func->var->name, impl->func->name);
266 return 0;
267 }
268 }
269 /* check that the let_value references a known variable or NULL */
270 for (i = 0; i < stmts->let.count; ++i) {
271 let_stmt *let = stmts->let.list[i];
272 int check = 0;
273
274 if (let->val->var) {
275 for (j = 0; j < impl->func->args->count; ++j) {
276 impl_arg *iarg = impl->func->args->args[j];
277
278 if (!strcmp(let->val->var->name, iarg->var->name)) {
279 let->arg = iarg;
280 check = 1;
281 break;
282 }
283 }
284 if (!check) {
285 V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
286 " for variable '%s' of implementation '%s'",
287 let->val->var->name, let->var->name, impl->func->name);
288 return 0;
289 }
290 }
291 }
292
293 impl->decl = decl;
294
295 return 1;
296 }
297
298 static inline int validate_impl(PSI_Validator *V, impl *impl) {
299 if (!validate_impl_func(V, impl, impl->func)) {
300 return 0;
301 }
302 if (!validate_impl_stmts(V, impl, impl->stmts)) {
303 return 0;
304 }
305 return 1;
306 }
307 static inline int validate_impls(PSI_Validator *V) {
308 size_t i;
309
310 for (i = 0; i < V->impls->count; ++i) {
311 if (!validate_impl(V, V->impls->list[i])) {
312 return 0;
313 }
314 }
315 return 1;
316 }
317
318 int PSI_ValidatorValidate(PSI_Validator *V)
319 {
320 if (!validate_lib(V)) {
321 return 0;
322 }
323 if (V->defs && !validate_typedefs(V)) {
324 return 0;
325 }
326 if (V->decls && !validate_decls(V)) {
327 return 0;
328 }
329 if (V->impls && !validate_impls(V)) {
330 return 0;
331 }
332 return 1;
333 }