From: Michael Wallner Date: Mon, 12 Oct 2015 10:46:12 +0000 (+0200) Subject: start validator X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=059fffcaee65cf92b95bdbe91e5a156b89b2cf71;p=m6w6%2Fext-psi start validator --- diff --git a/.gitignore b/.gitignore index 3ce5b15..6a24edf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.dSYM /idl/lexer.c -/idl/parser +/idl/main /idl/parser.h /idl/parser.c /idl/parser.out diff --git a/TODO b/TODO index 286357b..09344d0 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ * move numbers to the lexer * avoid allocs inside structures by reallocating the whole structure +* let the various list types be hashtables where appropriate diff --git a/idl/Makefile b/idl/Makefile index f7d99f7..84860c9 100644 --- a/idl/Makefile +++ b/idl/Makefile @@ -1,6 +1,6 @@ -CFLAGS = -g +CFLAGS += -g -D$(shell uname | tr a-z A-Z) .PHONY: all -all: parser makeheaders +all: main makeheaders.c: curl -sSO http://www.hwaci.com/sw/mkhdr/makeheaders.c @@ -8,8 +8,8 @@ makeheaders.c: GENERATED_FILES += makeheaders makeheaders: makeheaders.c -GENERATED_FILES += parser -parser: main.c parser.c lexer.c +GENERATED_FILES += main +main: main.c parser.c lexer.c validator.c GENERATED_FILES += parser.h parser.h: parser.c makeheaders diff --git a/idl/lexer.h b/idl/lexer.h index 62ce14b..be1ee57 100644 --- a/idl/lexer.h +++ b/idl/lexer.h @@ -1,13 +1,12 @@ #define BSIZE 256 typedef int token_t; -typedef char text; typedef struct PSI_Token { token_t type; unsigned line; size_t size; - text text[1]; + char text[1]; } PSI_Token; typedef struct impls impls; @@ -15,14 +14,14 @@ typedef struct decls decls; typedef struct decl_typedefs decl_typedefs; typedef struct PSI_Lexer { - FILE *fp; - char *fn; - char *lib; decl_typedefs *defs; decls *decls; impls *impls; + char *lib; + char *fn; + FILE *fp; size_t line; - text *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; + char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; } PSI_Lexer; PSI_Lexer *PSI_LexerInit(PSI_Lexer *L, const char *filename); diff --git a/idl/main.c b/idl/main.c index fe49647..f802958 100644 --- a/idl/main.c +++ b/idl/main.c @@ -3,6 +3,7 @@ #include #include "lexer.h" #include "parser.h" +#include "validator.h" static int TRACE; @@ -32,6 +33,7 @@ static void loop(PSI_Lexer *L, void *P) int main(int argc, char *argv[]) { PSI_Lexer L; + PSI_Validator V; void *P = PSI_ParserAlloc(malloc); TRACE = !!getenv("TRACE"); @@ -44,7 +46,18 @@ int main(int argc, char *argv[]) loop(&L, P); PSI_ParserFree(P, free); + + if (!PSI_ValidatorInit(&V, &L)) { + perror("Failed to init validator"); + return 2; + } + PSI_LexerDtor(&L); + if (PSI_ValidatorValidate(&V)) { + printf("Whoa! VALID.\n"); + } + PSI_ValidatorDtor(&V); + return 0; } diff --git a/idl/parser.y b/idl/parser.y index 9d71e63..0515332 100644 --- a/idl/parser.y +++ b/idl/parser.y @@ -63,9 +63,15 @@ decl_typedef(def) ::= TYPEDEF NAME(ALIAS) decl_type(type) EOS. { } %type decl {decl*} -decl(decl) ::= decl_arg(func) LPAREN decl_args(args) RPAREN EOS. { - decl = init_decl(func, args); +decl(decl) ::= decl_abi(abi) decl_arg(func) LPAREN decl_args(args) RPAREN EOS. { + decl = init_decl(abi, func, args); } + +%type decl_abi {decl_abi*} +decl_abi(abi) ::= NAME(T). { + abi = init_decl_abi(T->text); +} + %type decl_var {decl_var*} decl_var(var) ::= NAME(T). { var = init_decl_var(T->text, 0); diff --git a/idl/types.h b/idl/types.h index c5b962e..7225b5d 100644 --- a/idl/types.h +++ b/idl/types.h @@ -1,10 +1,25 @@ +typedef struct PSI_Data { + decl_typedefs *defs; + decls *decls; + impls *impls; + char *lib; + char *fn; +} PSI_Data; + +static inline void PSI_DataExchange(PSI_Data *dest, PSI_Data *src) { + memcpy(dest, src, sizeof(*dest)); + memset(src, 0, sizeof(*src)); +} + +struct decl_typedef; typedef struct decl_type { - text *name; + char *name; token_t type; + struct decl_type *real; } decl_type; -static inline decl_type *init_decl_type(token_t type, text *name) { +static inline decl_type *init_decl_type(token_t type, char *name) { decl_type *t = malloc(sizeof(*t)); t->type = type; t->name = strdup(name); @@ -21,7 +36,7 @@ typedef struct decl_typedef { decl_type *type; } decl_typedef; -static inline decl_typedef *init_decl_typedef(text *name, decl_type *type) { +static inline decl_typedef *init_decl_typedef(char *name, decl_type *type) { decl_typedef *t = malloc(sizeof(*t)); t->alias = strdup(name); t->type = type; @@ -59,13 +74,13 @@ static void free_decl_typedefs(decl_typedefs *defs) { } typedef struct decl_var { - text *name; + char *name; unsigned pointer_level; } decl_var; -static inline decl_var *init_decl_var(text *name, unsigned pl) { +static inline decl_var *init_decl_var(char *name, unsigned pl) { decl_var *v = malloc(sizeof(*v)); - v->name = (text *) strdup((const char *) name); + v->name = (char *) strdup((const char *) name); v->pointer_level = pl; return v; } @@ -151,19 +166,38 @@ static inline void free_decl_args(decl_args *args) { free(args); } +typedef struct decl_abi { + char *convention; +} decl_abi; + +static inline decl_abi *init_decl_abi(char *convention) { + decl_abi *abi = malloc(sizeof(*abi)); + abi->convention = strdup(convention); + return abi; +} + +static inline void free_decl_abi(decl_abi *abi) { + free(abi->convention); + free(abi); +} + typedef struct decl { + decl_abi *abi; decl_arg *func; decl_args *args; + void *dlptr; } decl; -static inline decl* init_decl(decl_arg *func, decl_args *args) { +static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) { decl *d = malloc(sizeof(*d)); + d->abi = abi; d->func = func; d->args = args; return d; } static inline void free_decl(decl *d) { + free_decl_abi(d->abi); free_decl_arg(d->func); free_decl_args(d->args); free(d); @@ -194,15 +228,15 @@ static inline void free_decls(decls *decls) { } typedef struct impl_type { - text *name; + char *name; token_t type; } impl_type; -static inline impl_type *init_impl_type(token_t type, text *name) { +static inline impl_type *init_impl_type(token_t type, char *name) { impl_type *t = malloc(sizeof(*t)); t->type = type; - t->name = (text *) strdup((const char *) name); + t->name = (char *) strdup((const char *) name); return t; } @@ -212,13 +246,13 @@ static inline void free_impl_type(impl_type *type) { } typedef struct impl_var { - text *name; + char *name; unsigned reference:1; } impl_var; -static inline impl_var *init_impl_var(text *name, int is_reference) { +static inline impl_var *init_impl_var(char *name, int is_reference) { impl_var *var = malloc(sizeof(*var)); - var->name = (text *) strdup((const char *) name); + var->name = (char *) strdup((const char *) name); var->reference = is_reference; return var; } @@ -306,12 +340,12 @@ static inline void free_impl_args(impl_args *args) { } typedef struct impl_func { - text *name; + char *name; impl_args *args; impl_type *return_type; } impl_func; -static inline impl_func *init_impl_func(text *name, impl_args *args, impl_type *type) { +static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type *type) { impl_func *func = malloc(sizeof(*func)); func->name = strdup(name); func->args = args ? args : init_impl_args(NULL); @@ -328,13 +362,13 @@ static inline void free_impl_func(impl_func *f) { typedef struct let_func { token_t type; - text *name; + char *name; } let_func; -static inline let_func *init_let_func(token_t type, text *name) { +static inline let_func *init_let_func(token_t type, char *name) { let_func *func = malloc(sizeof(*func)); func->type = type; - func->name = (text *) strdup((const char *) name); + func->name = (char *) strdup((const char *) name); return func; } @@ -387,13 +421,13 @@ static inline void free_let_stmt(let_stmt *stmt) { typedef struct set_func { token_t type; - text *name; + char *name; } set_func; -static inline set_func *init_set_func(token_t type, text *name) { +static inline set_func *init_set_func(token_t type, char *name) { set_func *func = malloc(sizeof(*func)); func->type = type; - func->name = (text *) strdup((const char *) name); + func->name = (char *) strdup((const char *) name); return func; } diff --git a/idl/validator.c b/idl/validator.c new file mode 100644 index 0000000..d2b7cfe --- /dev/null +++ b/idl/validator.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include "lexer.h" +#include "parser.h" +#include "types.h" +#include "validator.h" + +PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Lexer *L) +{ + if (!V) { + V = malloc(sizeof(*V)); + } + memset(V, 0, sizeof(*V)); + + PSI_DataExchange((PSI_Data *) V, (PSI_Data *) L); + + return V; +} + +void PSI_ValidatorDtor(PSI_Validator *V) +{ + if (V->defs) { + free_decl_typedefs(V->defs); + } + if (V->decls) { + free_decls(V->decls); + } + if (V->impls) { + free_impls(V->impls); + } + if (V->fn) { + free(V->fn); + } + memset(V, 0, sizeof(*V)); +} + +void PSI_ValidatorFree(PSI_Validator **V) +{ + if (*V) { + PSI_ValidatorDtor(*V); + free(*V); + *V = NULL; + } +} + +static inline int validate_lib(PSI_Validator *V) { + char lib[MAXPATHLEN]; + const char *ptr = V->lib; + size_t len; + + if (!ptr) { + /* FIXME: assume stdlib */ + return 1; + fprintf(stderr, "No import library defined;" + " use 'lib \"\";' statement.\n"); + } else if (!strchr(ptr, '/')) { +#ifdef DARWIN + len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr); +#else + len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr); +#endif + if (MAXPATHLEN == len) { + fprintf(stderr, "Library name too long: '%s'\n", ptr); + } + lib[len] = 0; + ptr = lib; + } + if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) { + perror(ptr); + return 0; + } + return 1; +} +static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { + size_t i; + + if (type->real) { + return 1; + } + for (i = 0; i < defs->count; ++i) { + if (!strcmp(defs->list[i]->alias, type->name)) { + type->real = defs->list[i]->type; + return 1; + } + } + return 0; +} +static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) { + if (type->type == PSI_T_NAME) { + size_t i; + + if (!V->defs || !locate_decl_type_alias(V->defs, type)) { + fprintf(stderr, "Cannot use '%s' as type for '%s';" + " Use 'typedef ;' statement.\n", + type->name, arg->var->name); + } + } + return 1; +} +static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) { + /* FIXME: check def->alias */ + if (def->type->type == PSI_T_NAME) { + fprintf(stderr, "Type '%s' cannot be aliased to '%s'\n", + def->type->name, def->alias); + return 0; + } + return 1; +} +static inline int validate_typedefs(PSI_Validator *V) { + size_t i; + + for (i = 0; i < V->defs->count; ++i) { + if (!validate_typedef(V, V->defs->list[i])) { + return 0; + } + } + + return 1; +} +static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) +{ + void *dlptr; + + if (!strcmp(func->var->name, "dlsym")) { + fprintf(stderr, "Cannot dlsym dlsym (sic!)\n"); + return 0; + } + + if (!validate_decl_type(V, func, func->type)) { + return 0; + } + + decl->dlptr = dlsym(V->dlopened ?: RTLD_DEFAULT, func->var->name); + if (!decl->dlptr) { + fprintf(stderr, "Failed to located symbol '%s': %s\n", + func->var->name, dlerror()); + } + return 1; +} +static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { + if (strcasecmp(abi->convention, "default")) { + fprintf(stderr, "Invalid calling convention: '%s'\n", abi->convention); + return 0; + } + /* FIXME */ + return 1; +} +static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) { + if (!validate_decl_type(V, arg, arg->type)) { + return 0; + } + return 1; +} +static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) { + size_t i; + + for (i = 0; i < args->count; ++i) { + if (!validate_decl_arg(V, decl, args->args[i])) { + return 0; + } + } + return 1; +} +static inline int validate_decl(PSI_Validator *V, decl *decl) { + if (!validate_decl_abi(V, decl->abi)) { + return 0; + } + if (!validate_decl_func(V, decl, decl->func)) { + return 0; + } + if (decl->args && !validate_decl_args(V, decl, decl->args)) { + return 0; + } + return 1; +} +static inline int validate_decls(PSI_Validator *V) { + size_t i; + + for (i = 0; i < V->decls->count; ++i) { + if (!validate_decl(V, V->decls->list[i])) { + return 0; + } + } + return 1; +} + +static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) { + /* FIXME */ + return 1; +} +static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) { + return 1; +} +static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) { + size_t i; + + for (i = 0; i < args->count; ++i) { + if (!validate_impl_arg(V, impl, args->args[i])) { + return 0; + } + } + return 1; +} +static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) { + /* FIXME: does name need any validation? */ + if (!validate_impl_type(V, impl, func->return_type)) { + return 0; + } + if (func->args && !validate_impl_args(V, impl, func->args)) { + return 0; + } + return 1; +} +static inline int validate_impl(PSI_Validator *V, impl *impl) { + if (!validate_impl_func(V, impl, impl->func)) { + return 0; + } + if (!validate_impl_stmts(V, impl, impl->stmts)) { + return 0; + } + return 1; +} +static inline int validate_impls(PSI_Validator *V) { + size_t i; + + for (i = 0; i < V->impls->count; ++i) { + if (!validate_impl(V, V->impls->list[i])) { + return 0; + } + } + return 1; +} + +int PSI_ValidatorValidate(PSI_Validator *V) +{ + if (V->defs && !validate_typedefs(V)) { + return 0; + } + if (V->decls && !validate_decls(V)) { + return 0; + } + if (V->impls && !validate_impls(V)) { + return 0; + } + return 1; +} diff --git a/idl/validator.h b/idl/validator.h new file mode 100644 index 0000000..c7e8264 --- /dev/null +++ b/idl/validator.h @@ -0,0 +1,14 @@ + +typedef struct PSI_Validator { + decl_typedefs *defs; + decls *decls; + impls *impls; + char *lib; + char *fn; + void *dlopened; +} PSI_Validator; + +PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Lexer *L); +int PSI_ValidatorValidate(PSI_Validator *V); +void PSI_ValidatorDtor(PSI_Validator *V); +void PSI_ValidatorFree(PSI_Validator **V);