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