11 PSI_Validator
*PSI_ValidatorInit(PSI_Validator
*V
, PSI_Parser
*P
)
14 V
= malloc(sizeof(*V
));
16 memset(V
, 0, sizeof(*V
));
18 PSI_DataExchange((PSI_Data
*) V
, (PSI_Data
*) P
);
23 void PSI_ValidatorDtor(PSI_Validator
*V
)
25 PSI_DataDtor((PSI_Data
*) V
);
26 memset(V
, 0, sizeof(*V
));
29 void PSI_ValidatorFree(PSI_Validator
**V
)
32 PSI_ValidatorDtor(*V
);
38 static int validate_lib(PSI_Validator
*V
) {
40 const char *ptr
= V
->lib
;
44 /* FIXME: assume stdlib */
46 } else if (!strchr(ptr
, '/')) {
48 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.dylib", ptr
);
50 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.so", ptr
);
52 if (MAXPATHLEN
== len
) {
53 V
->error(PSI_WARNING
, "Library name too long: '%s'", ptr
);
58 if (!(V
->dlopened
= dlopen(ptr
, RTLD_LAZY
|RTLD_LOCAL
))) {
59 V
->error(PSI_WARNING
, "Could not open library '%s': %s.", V
->lib
, dlerror());
64 static inline int locate_decl_type_alias(decl_typedefs
*defs
, decl_type
*type
) {
70 for (i
= 0; i
< defs
->count
; ++i
) {
71 if (!strcmp(defs
->list
[i
]->alias
, type
->name
)) {
72 type
->real
= defs
->list
[i
]->type
;
78 static inline int validate_decl_type(PSI_Validator
*V
, decl_arg
*arg
, decl_type
*type
) {
79 if (type
->type
== PSI_T_NAME
) {
80 if (!V
->defs
|| !locate_decl_type_alias(V
->defs
, type
)) {
81 V
->error(PSI_WARNING
, "Cannot use '%s' as type for '%s';"
82 " Use 'typedef <type> <basic_type>;' statement",
83 type
->name
, arg
->var
->name
);
89 static inline int validate_typedef(PSI_Validator
*V
, decl_typedef
*def
) {
90 /* FIXME: check def->alias */
91 if (def
->type
->type
== PSI_T_NAME
) {
92 V
->error(PSI_WARNING
, "Type '%s' cannot be aliased to '%s'",
93 def
->type
->name
, def
->alias
);
98 static inline int validate_typedefs(PSI_Validator
*V
) {
101 for (i
= 0; i
< V
->defs
->count
; ++i
) {
102 if (!validate_typedef(V
, V
->defs
->list
[i
])) {
109 static inline int validate_decl_func(PSI_Validator
*V
, decl
*decl
, decl_arg
*func
)
111 if (!strcmp(func
->var
->name
, "dlsym")) {
112 V
->error(PSI_WARNING
, "Cannot dlsym dlsym (sic!)");
116 if (!validate_decl_type(V
, func
, func
->type
)) {
120 decl
->dlptr
= dlsym(V
->dlopened
, func
->var
->name
);
122 V
->error(PSI_WARNING
, "Failed to located symbol '%s': %s",
123 func
->var
->name
, dlerror());
127 static const char * const abi_ccs
[] = {
129 "extern", /* > - all the same */
134 static inline int validate_decl_abi(PSI_Validator
*V
, decl_abi
*abi
) {
137 for (i
= 0; i
< sizeof(abi_ccs
)/sizeof(char*); ++ i
) {
138 if (strcasecmp(abi
->convention
, abi_ccs
[i
])) {
142 V
->error(PSI_WARNING
, "Invalid calling convention: '%s'", abi
->convention
);
145 static inline int validate_decl_arg(PSI_Validator
*V
, decl
*decl
, decl_arg
*arg
) {
146 if (!validate_decl_type(V
, arg
, arg
->type
)) {
151 static inline int validate_decl_args(PSI_Validator
*V
, decl
*decl
, decl_args
*args
) {
154 for (i
= 0; i
< args
->count
; ++i
) {
155 if (!validate_decl_arg(V
, decl
, args
->args
[i
])) {
161 static inline int validate_decl(PSI_Validator
*V
, decl
*decl
) {
162 if (!validate_decl_abi(V
, decl
->abi
)) {
165 if (!validate_decl_func(V
, decl
, decl
->func
)) {
168 if (decl
->args
&& !validate_decl_args(V
, decl
, decl
->args
)) {
173 static inline int validate_decls(PSI_Validator
*V
) {
176 for (i
= 0; i
< V
->decls
->count
; ++i
) {
177 if (!validate_decl(V
, V
->decls
->list
[i
])) {
184 static inline int validate_impl_type(PSI_Validator
*V
, impl
*impl
, impl_type
*type
) {
188 static inline int validate_impl_arg(PSI_Validator
*V
, impl
*impl
, impl_arg
*arg
) {
191 static inline int validate_impl_args(PSI_Validator
*V
, impl
*impl
, impl_args
*args
) {
194 for (i
= 0; i
< args
->count
; ++i
) {
195 if (!validate_impl_arg(V
, impl
, args
->args
[i
])) {
201 static inline int validate_impl_func(PSI_Validator
*V
, impl
*impl
, impl_func
*func
) {
202 /* FIXME: does name need any validation? */
203 if (!validate_impl_type(V
, impl
, func
->return_type
)) {
206 if (func
->args
&& !validate_impl_args(V
, impl
, func
->args
)) {
211 static inline decl
*locate_impl_decl(decls
*decls
, return_stmt
*ret
) {
214 for (i
= 0; i
< decls
->count
; ++i
) {
215 if (!strcmp(decls
->list
[i
]->func
->var
->name
, ret
->decl
->name
)) {
216 return decls
->list
[i
];
222 static inline int validate_impl_stmts(PSI_Validator
*V
, impl
*impl
, impl_stmts
*stmts
) {
224 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
225 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
226 * - we can have any count of set stmts; processing out vars
227 * - we can have any count of free stmts; freeing any out vars
234 V
->error(PSI_WARNING
, "Missing body for implementation %s!",
238 if (stmts
->ret
.count
!= 1) {
239 if (stmts
->ret
.count
> 1) {
240 V
->error(PSI_WARNING
, "Too many `ret` statements for implmentation %s;"
241 "found %zu, exactly one is needed",
242 impl
->func
->name
, stmts
->ret
.count
);
244 V
->error(PSI_WARNING
, "Missing `ret` statement for implementation %s",
250 ret
= stmts
->ret
.list
[0];
251 decl
= locate_impl_decl(V
->decls
, ret
);
253 V
->error(PSI_WARNING
, "Missing declaration for implementation %s",
258 /* check that we have a let stmt for every decl arg */
259 for (i
= 0; i
< decl
->args
->count
; ++i
) {
260 decl_arg
*darg
= decl
->args
->args
[i
];
263 for (j
= 0; j
< stmts
->let
.count
; ++j
) {
264 let_stmt
*let
= stmts
->let
.list
[j
];
266 if (!strcmp(let
->var
->name
, darg
->var
->name
)) {
273 V
->error(PSI_WARNING
, "Missing `let` statement for arg '%s %.*s%s'"
274 "of declaration '%s' for implementation '%s'",
275 darg
->type
->name
, (int) darg
->var
->pointer_level
, "*****",
276 darg
->var
->name
, decl
->func
->var
->name
, impl
->func
->name
);
280 /* check that the let_value references a known variable or NULL */
281 for (i
= 0; i
< stmts
->let
.count
; ++i
) {
282 let_stmt
*let
= stmts
->let
.list
[i
];
286 for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
287 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
289 if (!strcmp(let
->val
->var
->name
, iarg
->var
->name
)) {
296 V
->error(PSI_WARNING
, "Unknown value '$%s' of `let` statement"
297 " for variable '%s' of implementation '%s'",
298 let
->val
->var
->name
, let
->var
->name
, impl
->func
->name
);
303 /* check that set stmts reference known variables */
304 for (i
= 0; i
< stmts
->set
.count
; ++i
) {
305 set_stmt
*set
= stmts
->set
.list
[i
];
308 for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
309 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
311 if (!strcmp(set
->var
->name
, iarg
->var
->name
)) {
318 V
->error(PSI_WARNING
, "Unknown variable '$%s' of `set` statement"
319 " of implementation '%s'",
320 set
->var
->name
, impl
->func
->name
);
324 for (j
= 0; j
< set
->val
->vars
->count
; ++j
) {
325 decl_var
*set_var
= set
->val
->vars
->vars
[j
];
328 for (k
= 0; k
< decl
->args
->count
; ++k
) {
329 decl_arg
*set_arg
= decl
->args
->args
[k
];
331 if (!strcmp(set_var
->name
, set_arg
->var
->name
)) {
333 set_var
->arg
= set_arg
;
339 V
->error(PSI_WARNING
, "Unknown value '%s' of `set` statement"
340 " for variable '$%s' of implementation '%s'",
341 set_var
->name
, set
->arg
->var
->name
, impl
->func
->name
);
346 /* check free stmts */
347 for (i
= 0; i
< stmts
->fre
.count
; ++i
) {
348 free_stmt
*fre
= stmts
->fre
.list
[i
];
350 for (j
= 0; j
< fre
->vars
->count
; ++j
) {
351 decl_var
*free_var
= fre
->vars
->vars
[j
];
354 if (!strcmp(free_var
->name
, decl
->func
->var
->name
)) {
357 for (k
= 0; k
< decl
->args
->count
; ++k
) {
358 decl_arg
*free_arg
= decl
->args
->args
[k
];
360 if (!strcmp(free_var
->name
, free_arg
->var
->name
)) {
362 free_var
->arg
= free_arg
;
368 V
->error(PSI_WARNING
, "Unknown variable '%s' of `free` statement"
369 " of implementation '%s'",
370 free_var
->name
, impl
->func
->name
);
381 static inline int validate_impl(PSI_Validator
*V
, impl
*impl
) {
382 if (!validate_impl_func(V
, impl
, impl
->func
)) {
385 if (!validate_impl_stmts(V
, impl
, impl
->stmts
)) {
390 static inline int validate_impls(PSI_Validator
*V
) {
393 for (i
= 0; i
< V
->impls
->count
; ++i
) {
394 if (!validate_impl(V
, V
->impls
->list
[i
])) {
401 int PSI_ValidatorValidate(PSI_Validator
*V
)
403 if (!validate_lib(V
)) {
406 if (V
->defs
&& !validate_typedefs(V
)) {
409 if (V
->decls
&& !validate_decls(V
)) {
412 if (V
->impls
&& !validate_impls(V
)) {