11 #include "validator.h"
13 PSI_Validator
*PSI_ValidatorInit(PSI_Validator
*V
, PSI_Parser
*P
)
16 V
= malloc(sizeof(*V
));
18 memset(V
, 0, sizeof(*V
));
20 PSI_DataExchange((PSI_Data
*) V
, (PSI_Data
*) P
);
25 void PSI_ValidatorDtor(PSI_Validator
*V
)
27 PSI_DataDtor((PSI_Data
*) V
);
28 memset(V
, 0, sizeof(*V
));
31 void PSI_ValidatorFree(PSI_Validator
**V
)
34 PSI_ValidatorDtor(*V
);
40 static int validate_lib(PSI_Validator
*V
) {
42 const char *ptr
= V
->lib
;
46 /* FIXME: assume stdlib */
48 } else if (!strchr(ptr
, '/')) {
50 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.dylib", ptr
);
52 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.so", ptr
);
54 if (MAXPATHLEN
== len
) {
55 V
->error(PSI_WARNING
, "Library name too long: '%s'", ptr
);
60 if (!(V
->dlopened
= dlopen(ptr
, RTLD_LAZY
|RTLD_LOCAL
))) {
61 V
->error(PSI_WARNING
, "Could not open library '%s': %s.", V
->lib
, dlerror());
67 static inline int locate_decl_type_alias(decl_typedefs
*defs
, decl_type
*type
) {
73 for (i
= 0; i
< defs
->count
; ++i
) {
74 if (!strcmp(defs
->list
[i
]->alias
, type
->name
)) {
75 type
->real
= defs
->list
[i
]->type
;
81 static inline int locate_decl_type_struct(decl_structs
*structs
, decl_type
*type
) {
87 for (i
= 0; i
< structs
->count
; ++i
) {
88 if (!strcmp(structs
->list
[i
]->name
, type
->name
)) {
89 type
->strct
= structs
->list
[i
];
95 static inline int validate_decl_type(PSI_Validator
*V
, decl_type
*type
) {
98 if (!V
->defs
|| !locate_decl_type_alias(V
->defs
, type
)) {
101 return validate_decl_type(V
, type
->real
);
103 if (!V
->structs
|| !locate_decl_type_struct(V
->structs
, type
)) {
110 static inline int validate_typedef(PSI_Validator
*V
, decl_typedef
*def
) {
111 /* FIXME: check def->alias */
112 if (def
->type
->type
== PSI_T_NAME
) {
113 V
->error(PSI_WARNING
, "Type '%s' cannot be aliased to '%s'",
114 def
->type
->name
, def
->alias
);
119 static inline int validate_typedefs(PSI_Validator
*V
) {
122 for (i
= 0; i
< V
->defs
->count
; ++i
) {
123 if (!validate_typedef(V
, V
->defs
->list
[i
])) {
130 static const char * const abi_ccs
[] = {
132 "extern", /* > - all the same */
137 static inline int validate_decl_abi(PSI_Validator
*V
, decl_abi
*abi
) {
140 for (i
= 0; i
< sizeof(abi_ccs
)/sizeof(char*); ++i
) {
141 if (strcasecmp(abi
->convention
, abi_ccs
[i
])) {
145 V
->error(PSI_WARNING
, "Invalid calling convention: '%s'", abi
->convention
);
148 static inline int validate_decl_arg(PSI_Validator
*V
, decl_arg
*arg
) {
149 if (!validate_decl_type(V
, arg
->type
)) {
150 V
->error(PSI_WARNING
, "Cannot use '%s' as type for '%s'",
151 arg
->type
->name
, arg
->var
->name
);
156 static inline int validate_decl_args(PSI_Validator
*V
, decl_args
*args
) {
159 for (i
= 0; i
< args
->count
; ++i
) {
160 if (!validate_decl_arg(V
, args
->args
[i
])) {
166 static inline int validate_decl_func(PSI_Validator
*V
, decl
*decl
, decl_arg
*func
)
168 if (!strcmp(func
->var
->name
, "dlsym")) {
169 V
->error(PSI_WARNING
, "Cannot dlsym dlsym (sic!)");
173 if (!validate_decl_arg(V
, func
)) {
177 # define RTLD_NEXT ((void *) -1l)
179 decl
->dlptr
= dlsym(V
->dlopened
?: RTLD_NEXT
, func
->var
->name
);
181 V
->error(PSI_WARNING
, "Failed to located symbol '%s': %s",
182 func
->var
->name
, dlerror());
186 static inline int validate_decl(PSI_Validator
*V
, decl
*decl
) {
187 if (!validate_decl_abi(V
, decl
->abi
)) {
190 if (!validate_decl_func(V
, decl
, decl
->func
)) {
193 if (decl
->args
&& !validate_decl_args(V
, decl
->args
)) {
198 static inline int validate_decls(PSI_Validator
*V
) {
201 for (i
= 0; i
< V
->decls
->count
; ++i
) {
202 if (!validate_decl(V
, V
->decls
->list
[i
])) {
208 static inline int validate_struct(PSI_Validator
*V
, decl_struct
*s
) {
211 if (!validate_decl_args(V
, s
->args
)) {
215 s
->layout
= calloc(s
->args
->count
, sizeof(*s
->layout
));
216 for (i
= 0; i
< s
->args
->count
; ++i
) {
217 decl_arg
*darg
= s
->args
->args
[i
];
220 if (!validate_decl_arg(V
, darg
)) {
224 t
= darg
->var
->pointer_level
226 : real_decl_type(darg
->type
)->type
;
229 decl_struct_layout
*l
= &s
->layout
[i
-1];
230 s
->layout
[i
].pos
= psi_t_align(t
, l
->pos
+ l
->len
);
232 s
->layout
[i
].pos
= 0;
234 s
->layout
[i
].len
= psi_t_size(t
);
238 static inline int validate_structs(PSI_Validator
*V
) {
241 for (i
= 0; i
< V
->structs
->count
; ++i
) {
242 if (!validate_struct(V
, V
->structs
->list
[i
])) {
249 static inline int validate_impl_type(PSI_Validator
*V
, impl
*impl
, impl_type
*type
) {
253 static inline int validate_impl_arg(PSI_Validator
*V
, impl
*impl
, impl_arg
*arg
) {
256 static inline int validate_impl_args(PSI_Validator
*V
, impl
*impl
, impl_args
*args
) {
259 for (i
= 0; i
< args
->count
; ++i
) {
260 if (!validate_impl_arg(V
, impl
, args
->args
[i
])) {
266 static inline int validate_impl_func(PSI_Validator
*V
, impl
*impl
, impl_func
*func
) {
267 /* FIXME: does name need any validation? */
268 if (!validate_impl_type(V
, impl
, func
->return_type
)) {
271 if (func
->args
&& !validate_impl_args(V
, impl
, func
->args
)) {
277 static inline decl
*locate_impl_decl(decls
*decls
, return_stmt
*ret
) {
280 for (i
= 0; i
< decls
->count
; ++i
) {
281 if (!strcmp(decls
->list
[i
]->func
->var
->name
, ret
->decl
->name
)) {
282 ret
->decl
->arg
= decls
->list
[i
]->func
;
283 return decls
->list
[i
];
288 static inline int validate_impl_ret_stmt(PSI_Validator
*V
, impl
*impl
) {
289 /* we must have exactly one ret stmt delcaring the native func to call */
290 /* and which type cast to apply */
291 if (impl
->stmts
->ret
.count
!= 1) {
292 if (impl
->stmts
->ret
.count
> 1) {
293 V
->error(PSI_WARNING
, "Too many `return` statements for implmentation %s;"
294 " found %zu, exactly one is needed",
295 impl
->func
->name
, impl
->stmts
->ret
.count
);
297 V
->error(PSI_WARNING
, "Missing `return` statement for implementation %s",
302 if (!(impl
->decl
= locate_impl_decl(V
->decls
, impl
->stmts
->ret
.list
[0]))) {
303 V
->error(PSI_WARNING
, "Missing declaration for implementation %s",
310 static inline int validate_impl_let_stmts(PSI_Validator
*V
, impl
*impl
) {
312 /* we can have multiple let stmts */
313 /* check that we have a let stmt for every decl arg */
314 if (impl
->decl
->args
) for (i
= 0; i
< impl
->decl
->args
->count
; ++i
) {
315 decl_arg
*darg
= impl
->decl
->args
->args
[i
];
318 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
319 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
321 if (!strcmp(let
->var
->name
, darg
->var
->name
)) {
328 V
->error(PSI_WARNING
, "Missing `let` statement for arg '%s %.*s%s'"
329 " of declaration '%s' for implementation '%s'",
330 darg
->type
->name
, (int) darg
->var
->pointer_level
, "*****",
331 darg
->var
->name
, impl
->decl
->func
->var
->name
, impl
->func
->name
);
335 /* check that the let_value references a known variable or NULL */
336 for (i
= 0; i
< impl
->stmts
->let
.count
; ++i
) {
337 let_stmt
*let
= impl
->stmts
->let
.list
[i
];
340 if (let
->val
&& let
->val
->func
&& let
->val
->func
->alloc
) {
341 if (!validate_decl_type(V
, let
->val
->func
->alloc
->type
)) {
342 V
->error(PSI_WARNING
, "Cannot use '%s' as type for calloc in `let` statement",
343 let
->val
->func
->alloc
->type
->name
);
347 if (let
->val
&& let
->val
->var
) {
348 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
349 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
351 if (!strcmp(let
->val
->var
->name
, iarg
->var
->name
)) {
358 V
->error(PSI_WARNING
, "Unknown value '$%s' of `let` statement"
359 " for variable '%s' of implementation '%s'",
360 let
->val
->var
->name
, let
->var
->name
, impl
->func
->name
);
367 static inline int validate_impl_set_stmts(PSI_Validator
*V
, impl
*impl
) {
369 /* we can have any count of set stmts; processing out vars */
370 /* check that set stmts reference known variables */
371 for (i
= 0; i
< impl
->stmts
->set
.count
; ++i
) {
372 set_stmt
*set
= impl
->stmts
->set
.list
[i
];
375 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
376 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
378 if (!strcmp(set
->var
->name
, iarg
->var
->name
)) {
385 V
->error(PSI_WARNING
, "Unknown variable '$%s' of `set` statement"
386 " of implementation '%s'",
387 set
->var
->name
, impl
->func
->name
);
391 for (j
= 0; j
< set
->val
->vars
->count
; ++j
) {
392 decl_var
*set_var
= set
->val
->vars
->vars
[j
];
395 if (impl
->decl
->args
) for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
396 decl_arg
*set_arg
= impl
->decl
->args
->args
[k
];
398 if (!strcmp(set_var
->name
, set_arg
->var
->name
)) {
400 set_var
->arg
= set_arg
;
406 V
->error(PSI_WARNING
, "Unknown value '%s' of `set` statement"
407 " for variable '$%s' of implementation '%s'",
408 set_var
->name
, set
->arg
->var
->name
, impl
->func
->name
);
415 static inline int validate_impl_free_stmts(PSI_Validator
*V
, impl
*impl
) {
417 /* we can have any count of free stmts; freeing any out vars */
418 for (i
= 0; i
< impl
->stmts
->fre
.count
; ++i
) {
419 free_stmt
*fre
= impl
->stmts
->fre
.list
[i
];
421 for (j
= 0; j
< fre
->vars
->count
; ++j
) {
422 decl_var
*free_var
= fre
->vars
->vars
[j
];
425 if (!strcmp(free_var
->name
, impl
->decl
->func
->var
->name
)) {
428 if (impl
->decl
->args
) for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
429 decl_arg
*free_arg
= impl
->decl
->args
->args
[k
];
431 if (!strcmp(free_var
->name
, free_arg
->var
->name
)) {
433 free_var
->arg
= free_arg
;
439 V
->error(PSI_WARNING
, "Unknown variable '%s' of `free` statement"
440 " of implementation '%s'",
441 free_var
->name
, impl
->func
->name
);
448 static inline int validate_impl_stmts(PSI_Validator
*V
, impl
*impl
) {
450 V
->error(PSI_WARNING
, "Missing body for implementation %s!",
455 if (!validate_impl_ret_stmt(V
, impl
)) {
459 if (!validate_impl_let_stmts(V
, impl
)) {
462 if (!validate_impl_set_stmts(V
, impl
)) {
465 if (!validate_impl_free_stmts(V
, impl
)) {
472 static inline int validate_impl(PSI_Validator
*V
, impl
*impl
) {
473 if (!validate_impl_func(V
, impl
, impl
->func
)) {
476 if (!validate_impl_stmts(V
, impl
)) {
481 static inline int validate_impls(PSI_Validator
*V
) {
484 for (i
= 0; i
< V
->impls
->count
; ++i
) {
485 if (!validate_impl(V
, V
->impls
->list
[i
])) {
492 int PSI_ValidatorValidate(PSI_Validator
*V
)
494 if (!validate_lib(V
)) {
497 if (V
->defs
&& !validate_typedefs(V
)) {
500 if (V
->structs
&& !validate_structs(V
)) {
503 if (V
->decls
&& !validate_decls(V
)) {
506 if (!V
->impls
|| !validate_impls(V
)) {