e81d92315a9abadc8760adb23d2490f3b53be5f8
[m6w6/ext-psi] / idl / validator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <dlfcn.h>
5 #include <sys/param.h>
6
7 #include "validator.h"
8
9 #if INTERFACE
10 typedef struct PSI_Validator {
11 decl_typedefs *defs;
12 decls *decls;
13 impls *impls;
14 char *lib;
15 char *fn;
16 void *dlopened;
17 } PSI_Validator;
18 #endif
19
20 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Lexer *L)
21 {
22 if (!V) {
23 V = malloc(sizeof(*V));
24 }
25 memset(V, 0, sizeof(*V));
26
27 PSI_DataExchange((PSI_Data *) V, (PSI_Data *) L);
28
29 return V;
30 }
31
32 void PSI_ValidatorDtor(PSI_Validator *V)
33 {
34 if (V->defs) {
35 free_decl_typedefs(V->defs);
36 }
37 if (V->decls) {
38 free_decls(V->decls);
39 }
40 if (V->impls) {
41 free_impls(V->impls);
42 }
43 if (V->fn) {
44 free(V->fn);
45 }
46 memset(V, 0, sizeof(*V));
47 }
48
49 void PSI_ValidatorFree(PSI_Validator **V)
50 {
51 if (*V) {
52 PSI_ValidatorDtor(*V);
53 free(*V);
54 *V = NULL;
55 }
56 }
57
58 static inline int validate_lib(PSI_Validator *V) {
59 char lib[MAXPATHLEN];
60 const char *ptr = V->lib;
61 size_t len;
62
63 if (!ptr) {
64 /* FIXME: assume stdlib */
65 return 1;
66 fprintf(stderr, "No import library defined;"
67 " use 'lib \"<libname>\";' statement.\n");
68 } else if (!strchr(ptr, '/')) {
69 #ifdef DARWIN
70 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
71 #else
72 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
73 #endif
74 if (MAXPATHLEN == len) {
75 fprintf(stderr, "Library name too long: '%s'\n", ptr);
76 }
77 lib[len] = 0;
78 ptr = lib;
79 }
80 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
81 perror(ptr);
82 return 0;
83 }
84 return 1;
85 }
86 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
87 size_t i;
88
89 if (type->real) {
90 return 1;
91 }
92 for (i = 0; i < defs->count; ++i) {
93 if (!strcmp(defs->list[i]->alias, type->name)) {
94 type->real = defs->list[i]->type;
95 return 1;
96 }
97 }
98 return 0;
99 }
100 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
101 if (type->type == PSI_T_NAME) {
102 size_t i;
103
104 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
105 fprintf(stderr, "Cannot use '%s' as type for '%s';"
106 " Use 'typedef <type> <basic_type>;' statement.\n",
107 type->name, arg->var->name);
108 }
109 }
110 return 1;
111 }
112 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
113 /* FIXME: check def->alias */
114 if (def->type->type == PSI_T_NAME) {
115 fprintf(stderr, "Type '%s' cannot be aliased to '%s'\n",
116 def->type->name, def->alias);
117 return 0;
118 }
119 return 1;
120 }
121 static inline int validate_typedefs(PSI_Validator *V) {
122 size_t i;
123
124 for (i = 0; i < V->defs->count; ++i) {
125 if (!validate_typedef(V, V->defs->list[i])) {
126 return 0;
127 }
128 }
129
130 return 1;
131 }
132 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
133 {
134 void *dlptr;
135
136 if (!strcmp(func->var->name, "dlsym")) {
137 fprintf(stderr, "Cannot dlsym dlsym (sic!)\n");
138 return 0;
139 }
140
141 if (!validate_decl_type(V, func, func->type)) {
142 return 0;
143 }
144
145 decl->dlptr = dlsym(V->dlopened ?: RTLD_DEFAULT, func->var->name);
146 if (!decl->dlptr) {
147 fprintf(stderr, "Failed to located symbol '%s': %s\n",
148 func->var->name, dlerror());
149 }
150 return 1;
151 }
152 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
153 if (strcasecmp(abi->convention, "default")) {
154 fprintf(stderr, "Invalid calling convention: '%s'\n", abi->convention);
155 return 0;
156 }
157 /* FIXME */
158 return 1;
159 }
160 static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) {
161 if (!validate_decl_type(V, arg, arg->type)) {
162 return 0;
163 }
164 return 1;
165 }
166 static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) {
167 size_t i;
168
169 for (i = 0; i < args->count; ++i) {
170 if (!validate_decl_arg(V, decl, args->args[i])) {
171 return 0;
172 }
173 }
174 return 1;
175 }
176 static inline int validate_decl(PSI_Validator *V, decl *decl) {
177 if (!validate_decl_abi(V, decl->abi)) {
178 return 0;
179 }
180 if (!validate_decl_func(V, decl, decl->func)) {
181 return 0;
182 }
183 if (decl->args && !validate_decl_args(V, decl, decl->args)) {
184 return 0;
185 }
186 return 1;
187 }
188 static inline int validate_decls(PSI_Validator *V) {
189 size_t i;
190
191 for (i = 0; i < V->decls->count; ++i) {
192 if (!validate_decl(V, V->decls->list[i])) {
193 return 0;
194 }
195 }
196 return 1;
197 }
198
199 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
200 /* FIXME */
201 return 1;
202 }
203 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
204 return 1;
205 }
206 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
207 size_t i;
208
209 for (i = 0; i < args->count; ++i) {
210 if (!validate_impl_arg(V, impl, args->args[i])) {
211 return 0;
212 }
213 }
214 return 1;
215 }
216 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
217 /* FIXME: does name need any validation? */
218 if (!validate_impl_type(V, impl, func->return_type)) {
219 return 0;
220 }
221 if (func->args && !validate_impl_args(V, impl, func->args)) {
222 return 0;
223 }
224 return 1;
225 }
226 static inline int validate_impl(PSI_Validator *V, impl *impl) {
227 if (!validate_impl_func(V, impl, impl->func)) {
228 return 0;
229 }
230 if (!validate_impl_stmts(V, impl, impl->stmts)) {
231 return 0;
232 }
233 return 1;
234 }
235 static inline int validate_impls(PSI_Validator *V) {
236 size_t i;
237
238 for (i = 0; i < V->impls->count; ++i) {
239 if (!validate_impl(V, V->impls->list[i])) {
240 return 0;
241 }
242 }
243 return 1;
244 }
245
246 int PSI_ValidatorValidate(PSI_Validator *V)
247 {
248 if (V->defs && !validate_typedefs(V)) {
249 return 0;
250 }
251 if (V->decls && !validate_decls(V)) {
252 return 0;
253 }
254 if (V->impls && !validate_impls(V)) {
255 return 0;
256 }
257 return 1;
258 }