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