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