*.dSYM
/idl/lexer.c
-/idl/parser
+/idl/main
/idl/parser.h
/idl/parser.c
/idl/parser.out
* move numbers to the lexer
* avoid allocs inside structures by reallocating the whole structure
+* let the various list types be hashtables where appropriate
-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
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
#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;
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);
#include <string.h>
#include "lexer.h"
#include "parser.h"
+#include "validator.h"
static int TRACE;
int main(int argc, char *argv[])
{
PSI_Lexer L;
+ PSI_Validator V;
void *P = PSI_ParserAlloc(malloc);
TRACE = !!getenv("TRACE");
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;
}
}
%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);
+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);
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;
}
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;
}
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);
}
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;
}
}
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;
}
}
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);
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;
}
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;
}
--- /dev/null
+#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;
+}
--- /dev/null
+
+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);