start validator
authorMichael Wallner <mike@php.net>
Mon, 12 Oct 2015 10:46:12 +0000 (12:46 +0200)
committerMichael Wallner <mike@php.net>
Mon, 12 Oct 2015 10:46:12 +0000 (12:46 +0200)
.gitignore
TODO
idl/Makefile
idl/lexer.h
idl/main.c
idl/parser.y
idl/types.h
idl/validator.c [new file with mode: 0644]
idl/validator.h [new file with mode: 0644]

index 3ce5b15..6a24edf 100644 (file)
@@ -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 (file)
--- 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
index f7d99f7..84860c9 100644 (file)
@@ -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
index 62ce14b..be1ee57 100644 (file)
@@ -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);
index fe49647..f802958 100644 (file)
@@ -3,6 +3,7 @@
 #include <string.h>
 #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;
 }
index 9d71e63..0515332 100644 (file)
@@ -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);
index c5b962e..7225b5d 100644 (file)
@@ -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 (file)
index 0000000..d2b7cfe
--- /dev/null
@@ -0,0 +1,249 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/param.h>
+#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 \"<libname>\";' 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 <type> <basic_type>;' 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 (file)
index 0000000..c7e8264
--- /dev/null
@@ -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);