flush
[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 fprintf(stderr, "No import library defined;"
47 " use 'lib \"<libname>\";' statement.\n");
48 } else if (!strchr(ptr, '/')) {
49 #ifdef DARWIN
50 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
51 #else
52 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
53 #endif
54 if (MAXPATHLEN == len) {
55 fprintf(stderr, "Library name too long: '%s'\n", ptr);
56 }
57 lib[len] = 0;
58 ptr = lib;
59 }
60 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
61 fprintf(stderr, "Could not open library '%s': %s.\n", V->lib, dlerror());
62 return 0;
63 }
64 return 1;
65 }
66 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
67 size_t i;
68
69 if (type->real) {
70 return 1;
71 }
72 for (i = 0; i < defs->count; ++i) {
73 if (!strcmp(defs->list[i]->alias, type->name)) {
74 type->real = defs->list[i]->type;
75 return 1;
76 }
77 }
78 return 0;
79 }
80 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
81 if (type->type == PSI_T_NAME) {
82 size_t i;
83
84 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
85 fprintf(stderr, "Cannot use '%s' as type for '%s';"
86 " Use 'typedef <type> <basic_type>;' statement.\n",
87 type->name, arg->var->name);
88 }
89 }
90 return 1;
91 }
92 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
93 /* FIXME: check def->alias */
94 if (def->type->type == PSI_T_NAME) {
95 fprintf(stderr, "Type '%s' cannot be aliased to '%s'\n",
96 def->type->name, def->alias);
97 return 0;
98 }
99 return 1;
100 }
101 static inline int validate_typedefs(PSI_Validator *V) {
102 size_t i;
103
104 for (i = 0; i < V->defs->count; ++i) {
105 if (!validate_typedef(V, V->defs->list[i])) {
106 return 0;
107 }
108 }
109
110 return 1;
111 }
112 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
113 {
114 void *dlptr;
115
116 if (!strcmp(func->var->name, "dlsym")) {
117 fprintf(stderr, "Cannot dlsym dlsym (sic!)\n");
118 return 0;
119 }
120
121 if (!validate_decl_type(V, func, func->type)) {
122 return 0;
123 }
124
125 decl->dlptr = dlsym(V->dlopened ?: RTLD_DEFAULT, func->var->name);
126 if (!decl->dlptr) {
127 fprintf(stderr, "Failed to located symbol '%s': %s\n",
128 func->var->name, dlerror());
129 }
130 return 1;
131 }
132 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
133 if (strcasecmp(abi->convention, "default")) {
134 fprintf(stderr, "Invalid calling convention: '%s'\n", abi->convention);
135 return 0;
136 }
137 /* FIXME */
138 return 1;
139 }
140 static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) {
141 if (!validate_decl_type(V, arg, arg->type)) {
142 return 0;
143 }
144 return 1;
145 }
146 static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) {
147 size_t i;
148
149 for (i = 0; i < args->count; ++i) {
150 if (!validate_decl_arg(V, decl, args->args[i])) {
151 return 0;
152 }
153 }
154 return 1;
155 }
156 static inline int validate_decl(PSI_Validator *V, decl *decl) {
157 if (!validate_decl_abi(V, decl->abi)) {
158 return 0;
159 }
160 if (!validate_decl_func(V, decl, decl->func)) {
161 return 0;
162 }
163 if (decl->args && !validate_decl_args(V, decl, decl->args)) {
164 return 0;
165 }
166 return 1;
167 }
168 static inline int validate_decls(PSI_Validator *V) {
169 size_t i;
170
171 for (i = 0; i < V->decls->count; ++i) {
172 if (!validate_decl(V, V->decls->list[i])) {
173 return 0;
174 }
175 }
176 return 1;
177 }
178
179 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
180 /* FIXME */
181 return 1;
182 }
183 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
184 return 1;
185 }
186 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
187 size_t i;
188
189 for (i = 0; i < args->count; ++i) {
190 if (!validate_impl_arg(V, impl, args->args[i])) {
191 return 0;
192 }
193 }
194 return 1;
195 }
196 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
197 /* FIXME: does name need any validation? */
198 if (!validate_impl_type(V, impl, func->return_type)) {
199 return 0;
200 }
201 if (func->args && !validate_impl_args(V, impl, func->args)) {
202 return 0;
203 }
204 return 1;
205 }
206 static inline decl *locate_impl_decl(decls *decls, ret_stmt *ret) {
207 size_t i;
208
209 for (i = 0; i < decls->count; ++i) {
210 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
211 return decls->list[i];
212 }
213 }
214 return NULL;
215 }
216 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
217 /* okay,
218 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
219 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
220 * - we can have any count of set stmts; processing out vars, etc.
221 */
222 size_t i, j;
223 ret_stmt *ret;
224 decl *decl;
225 int *check;
226
227 if (!stmts) {
228 fprintf(stderr, "Missing body for implementation %s!\n", impl->func->name);
229 return 0;
230 }
231 if (stmts->ret.count != 1) {
232 if (stmts->ret.count > 1) {
233 fprintf(stderr, "Too many `ret` statements for implmentation %s; found %zu, exactly one is needed.\n",
234 impl->func->name, stmts->ret.count);
235 } else {
236 fprintf(stderr, "Missing `ret` statement for implementation %s.\n", impl->func->name);
237 }
238 return 0;
239 }
240
241 ret = stmts->ret.list[0];
242 decl = locate_impl_decl(V->decls, ret);
243 if (!decl) {
244 fprintf(stderr, "Missing declaration for implementation %s.\n", impl->func->name);
245 return 0;
246 }
247
248 /* check that we have a let stmt for every decl arg */
249 check = calloc(decl->args->count, sizeof(int));
250 for (i = 0; i < stmts->let.count; ++i) {
251 let_stmt *let = stmts->let.list[i];
252
253 for (j = 0; j < decl->args->count; ++j) {
254 if (!strcmp(decl->args->args[j]->var->name, let->var->name)) {
255 check[j] = 1;
256 break;
257 }
258 }
259 }
260 for (i = 0; i < decl->args->count; ++i) {
261 if (!check[i]) {
262 fprintf(stderr, "Missing `let` statement for arg '%s %.*s%s' of declaration '%s' for implementation '%s'.\n",
263 decl->args->args[i]->type->name, (int) decl->args->args[i]->var->pointer_level, "*****", decl->args->args[i]->var->name, decl->func->var->name, impl->func->name);
264 free(check);
265 return 0;
266 }
267 }
268 free(check);
269
270 impl->decl = decl;
271
272 return 1;
273 }
274
275 static inline int validate_impl(PSI_Validator *V, impl *impl) {
276 if (!validate_impl_func(V, impl, impl->func)) {
277 return 0;
278 }
279 if (!validate_impl_stmts(V, impl, impl->stmts)) {
280 return 0;
281 }
282 return 1;
283 }
284 static inline int validate_impls(PSI_Validator *V) {
285 size_t i;
286
287 for (i = 0; i < V->impls->count; ++i) {
288 if (!validate_impl(V, V->impls->list[i])) {
289 return 0;
290 }
291 }
292 return 1;
293 }
294
295 int PSI_ValidatorValidate(PSI_Validator *V)
296 {
297 if (!validate_lib(V)) {
298 return 0;
299 }
300 if (V->defs && !validate_typedefs(V)) {
301 return 0;
302 }
303 if (V->decls && !validate_decls(V)) {
304 return 0;
305 }
306 if (V->impls && !validate_impls(V)) {
307 return 0;
308 }
309 return 1;
310 }