From 5917ec1de81d919ac670af18166a41238aa1d3f6 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Sun, 11 Oct 2015 14:45:50 +0200 Subject: [PATCH] add more ffi types; add typedefs --- idl/lexer.h | 20 ++++----- idl/lexer.re | 59 +++++++++++++++++--------- idl/main.c | 8 ++-- idl/parser.y | 95 +++++++++++++++++++++++++++++++++++------- idl/types.h | 115 +++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 235 insertions(+), 62 deletions(-) diff --git a/idl/lexer.h b/idl/lexer.h index e3f7c5f..62ce14b 100644 --- a/idl/lexer.h +++ b/idl/lexer.h @@ -1,28 +1,26 @@ #define BSIZE 256 typedef int token_t; -typedef unsigned char text; +typedef char text; typedef struct PSI_Token { token_t type; unsigned line; + size_t size; text text[1]; } PSI_Token; -typedef struct impl impl; -typedef struct decl decl; +typedef struct impls impls; +typedef struct decls decls; +typedef struct decl_typedefs decl_typedefs; typedef struct PSI_Lexer { FILE *fp; char *fn; - struct { - size_t count; - decl **list; - } decl; - struct { - size_t count; - impl **list; - } impl; + char *lib; + decl_typedefs *defs; + decls *decls; + impls *impls; size_t line; text *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; } PSI_Lexer; diff --git a/idl/lexer.re b/idl/lexer.re index 3d1c660..d52436a 100644 --- a/idl/lexer.re +++ b/idl/lexer.re @@ -19,11 +19,18 @@ PSI_Token *PSI_TokenAlloc(PSI_Lexer *L, token_t t) { PSI_Token *T; - size_t token_len = L->cur - L->tok; + size_t token_len; + + if (L->cur <= L->tok) { + return NULL; + } + + token_len = L->cur - L->tok; T = malloc(sizeof(*T) + token_len); T->type = t; T->line = L->line; + T->size = token_len; T->text[token_len] = 0; memcpy(T->text, L->tok, token_len); @@ -73,21 +80,17 @@ void PSI_LexerDtor(PSI_Lexer *L) if (L->fn) { free(L->fn); } - if (L->decl.list) { - size_t i; - - for (i = 0; i < L->decl.count; ++i) { - free_decl(L->decl.list[i]); - } - free(L->decl.list); + if (L->lib) { + free(L->lib); } - if (L->impl.list) { - size_t i; - - for (i = 0; i < L->impl.count; ++i) { - free_impl(L->impl.list[i]); - } - free(L->impl.list); + if (L->defs) { + free_decl_typedefs(L->defs); + } + if (L->decls) { + free_decls(L->decls); + } + if (L->impls) { + free_impls(L->impls); } memset(L, 0, sizeof(*L)); } @@ -141,7 +144,8 @@ token_t PSI_LexerScan(PSI_Lexer *L) B = [^a-zA-Z0-9_]; W = [a-zA-Z0-9_]; NAME = W+; - NSNAME = NAME ("\\" NAME)+; + NSNAME = (NAME)? ("\\" NAME)+; + QUOTED_STRING = "\"" ([^\"])+ "\""; NULL = 'NULL'; MIXED = 'mixed'; VOID = 'void'; @@ -151,9 +155,17 @@ token_t PSI_LexerScan(PSI_Lexer *L) DOUBLE = 'double'; SINT8 = 'sint8'; UINT8 = 'uint8'; + SINT16 = 'sint16'; + UINT16 = 'uint16'; + SINT32 = 'sint32'; + UINT32 = 'uint32'; + SINT64 = 'sint64'; + UINT64 = 'uint64'; STRING = 'string'; ARRAY = 'array'; FUNCTION = 'function'; + TYPEDEF = 'typedef'; + LIB = 'lib'; LET = 'let'; SET = 'set'; RET = 'ret'; @@ -172,8 +184,8 @@ token_t PSI_LexerScan(PSI_Lexer *L) ";" {return PSI_T_EOS;} "," {return PSI_T_COMMA;} ":" {return PSI_T_COLON;} - "{" {return PSI_T_LCURLY;} - "}" {return PSI_T_RCURLY;} + "{" {return PSI_T_LBRACE;} + "}" {return PSI_T_RBRACE;} "." {return PSI_T_DOT;} "=" {return PSI_T_EQUALS;} "$" {return PSI_T_DOLLAR;} @@ -190,9 +202,17 @@ token_t PSI_LexerScan(PSI_Lexer *L) DOUBLE {return PSI_T_DOUBLE;} SINT8 {return PSI_T_SINT8;} UINT8 {return PSI_T_UINT8;} + SINT16 {return PSI_T_SINT16;} + UINT16 {return PSI_T_UINT16;} + SINT32 {return PSI_T_SINT32;} + UINT32 {return PSI_T_UINT32;} + SINT64 {return PSI_T_SINT64;} + UINT64 {return PSI_T_UINT64;} STRING {return PSI_T_STRING;} ARRAY {return PSI_T_ARRAY;} FUNCTION {return PSI_T_FUNCTION;} + TYPEDEF {return PSI_T_TYPEDEF;} + LIB {return PSI_T_LIB;} LET {return PSI_T_LET;} SET {return PSI_T_SET;} RET {return PSI_T_RET;} @@ -205,8 +225,9 @@ token_t PSI_LexerScan(PSI_Lexer *L) TO_FLOAT {return PSI_T_TO_FLOAT;} TO_BOOL {return PSI_T_TO_BOOL;} [0-9] {return PSI_T_DIGIT;} - NSNAME {return PSI_T_NSNAME;} NAME {return PSI_T_NAME;} + NSNAME {return PSI_T_NSNAME;} + QUOTED_STRING {return PSI_T_QUOTED_STRING;} */ } return -1; diff --git a/idl/main.c b/idl/main.c index 6732b7d..fe49647 100644 --- a/idl/main.c +++ b/idl/main.c @@ -4,7 +4,7 @@ #include "lexer.h" #include "parser.h" -static volatile int TRACE; +static int TRACE; static void loop(PSI_Lexer *L, void *P) { @@ -16,12 +16,14 @@ static void loop(PSI_Lexer *L, void *P) } while (-1 != (t = PSI_LexerScan(L))) { - T = PSI_TokenAlloc(L, t); + if (!(T = PSI_TokenAlloc(L, t))) { + break; + } if (TRACE) { printf("# Token: <%s>(%d)\n", T->text, t); } - + PSI_Parser(P, t, T, L); } PSI_Parser(P, 0, T, L); diff --git a/idl/parser.y b/idl/parser.y index 74433f9..9d71e63 100644 --- a/idl/parser.y +++ b/idl/parser.y @@ -2,9 +2,22 @@ #include #include #include +#include #include "lexer.h" #include "parser.h" #include "types.h" + +static void syntax_error(const char *fn, size_t ln, const char *msg, ...) { + fprintf(stderr, "WARNING: Syntax error on line %zu in '%s'%s", ln, fn, msg ? ": ": "\n"); + if (msg) { + va_list argv; + + va_start(argv, msg); + vfprintf(stderr, msg, argv); + va_end(argv); + } +} + } %name PSI_Parser @@ -12,25 +25,42 @@ %token_type {PSI_Token *} %token_destructor {free($$);} %extra_argument {PSI_Lexer *L} +/* TOKEN is defined inside syntax_error */ %syntax_error { - printf("ERROR: Syntax error on line %zu in '%s': '%s...'\n", L->line, L->fn, L->tok); - exit(1); + syntax_error(L->fn, L->line, "Unexpected token '%s'.\n", TOKEN->text); } - file ::= blocks. blocks ::= block. blocks ::= blocks block. -block ::= decl(decl_). { - L->decl.list = realloc(L->decl.list, ++L->decl.count * sizeof(*L->decl.list)); - L->decl.list[L->decl.count-1] = decl_; +block ::= COMMENT. + +block ::= LIB(T) QUOTED_STRING(libname) EOS. { + if (L->lib) { + syntax_error(L->fn, T->line, "Extra 'lib %s' statement has no effect.\n", libname->text); + } else { + L->lib = strndup(libname->text + 1, libname->size - 2); + } + free(libname); + free(T); } -block ::= impl(impl_). { - L->impl.list = realloc(L->impl.list, ++L->impl.count * sizeof(*L->impl.list)); - L->impl.list[L->impl.count-1] = impl_; + +block ::= decl(decl). { + L->decls = add_decl(L->decls, decl); +} +block ::= impl(impl). { + L->impls = add_impl(L->impls, impl); +} +block ::= decl_typedef(def). { + L->defs = add_decl_typedef(L->defs, def); +} + +%type decl_typedef {decl_typedef*} +decl_typedef(def) ::= TYPEDEF NAME(ALIAS) decl_type(type) EOS. { + def = init_decl_typedef(ALIAS->text, type); + free(ALIAS); } -block ::= COMMENT. %type decl {decl*} decl(decl) ::= decl_arg(func) LPAREN decl_args(args) RPAREN EOS. { @@ -92,9 +122,37 @@ decl_type(type_) ::= UINT8(T). { type_ = init_decl_type(T->type, T->text); free(T); } +decl_type(type_) ::= SINT16(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= UINT16(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= SINT32(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= UINT32(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= SINT64(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= UINT64(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= NAME(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} %type impl {impl*} -impl(impl) ::= impl_func(func) LCURLY impl_stmts(stmts) RCURLY. { +impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { impl = init_impl(func, stmts); } @@ -103,6 +161,10 @@ impl_func(func) ::= FUNCTION NSNAME(NAME) LPAREN impl_args(args) RPAREN COLON im func = init_impl_func(NAME->text, args, type); free(NAME); } +impl_func(func) ::= FUNCTION NSNAME(NAME) LPAREN RPAREN COLON impl_type(type). { + func = init_impl_func(NAME->text, NULL, type); + free(NAME); +} %type impl_def_val {impl_def_val*} impl_def_val(def) ::= NULL. { @@ -166,13 +228,14 @@ let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. { %type let_value {let_value*} let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. { - val = init_let_value(func, var); + val = init_let_value(func, var, 0); } -let_value(val) ::= let_reference_null_pointer. { - val = init_let_value(NULL, NULL); +let_value(val) ::= REFERENCE NULL. { + val = init_let_value(NULL, NULL, 1); +} +let_value(val) ::= NULL. { + val = init_let_value(NULL, NULL, 0); } - -let_reference_null_pointer ::= REFERENCE NULL. %type let_func {let_func*} let_func(func) ::= STRVAL(T). { diff --git a/idl/types.h b/idl/types.h index b57f1db..c5b962e 100644 --- a/idl/types.h +++ b/idl/types.h @@ -7,7 +7,7 @@ typedef struct decl_type { static inline decl_type *init_decl_type(token_t type, text *name) { decl_type *t = malloc(sizeof(*t)); t->type = type; - t->name = (text *) strdup((const char *) name); + t->name = strdup(name); return t; } @@ -16,6 +16,48 @@ static inline void free_decl_type(decl_type *type) { free(type); } +typedef struct decl_typedef { + char *alias; + decl_type *type; +} decl_typedef; + +static inline decl_typedef *init_decl_typedef(text *name, decl_type *type) { + decl_typedef *t = malloc(sizeof(*t)); + t->alias = strdup(name); + t->type = type; + return t; +} + +static inline void free_decl_typedef(decl_typedef *t) { + free(t->alias); + free_decl_type(t->type); + free(t); +} + +typedef struct decl_typedefs { + size_t count; + decl_typedef **list; +} decl_typedefs; + +static decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_typedef *def) { + if (!defs) { + defs = calloc(1, sizeof(*defs)); + } + defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list)); + defs->list[defs->count-1] = def; + return defs; +} + +static void free_decl_typedefs(decl_typedefs *defs) { + size_t i; + + for (i = 0; i < defs->count; ++i) { + free_decl_typedef(defs->list[i]); + } + free(defs->list); + free(defs); +} + typedef struct decl_var { text *name; unsigned pointer_level; @@ -127,6 +169,30 @@ static inline void free_decl(decl *d) { free(d); } +typedef struct decls { + size_t count; + decl **list; +} decls; + +static inline decls *add_decl(decls *decls, decl *decl) { + if (!decls) { + decls = calloc(1, sizeof(*decls)); + } + decls->list = realloc(decls->list, ++decls->count * sizeof(*decls->list)); + decls->list[decls->count-1] = decl; + return decls; +} + +static inline void free_decls(decls *decls) { + size_t i; + + for (i = 0; i < decls->count; ++i) { + free_decl(decls->list[i]); + } + free(decls->list); + free(decls); +} + typedef struct impl_type { text *name; token_t type; @@ -212,9 +278,14 @@ typedef struct impl_args { static inline impl_args *init_impl_args(impl_arg *arg) { impl_args *args = malloc(sizeof(*args)); - args->count = 1; args->args = malloc(sizeof(*args->args)); - args->args[0] = arg; + if (arg) { + args->count = 1; + args->args[0] = arg; + } else { + args->count = 0; + args->args = NULL; + } return args; } @@ -242,8 +313,8 @@ typedef struct impl_func { static inline impl_func *init_impl_func(text *name, impl_args *args, impl_type *type) { impl_func *func = malloc(sizeof(*func)); - func->name = (text *) strdup((const char *) name); - func->args = args; + func->name = strdup(name); + func->args = args ? args : init_impl_args(NULL); func->return_type = type; return func; } @@ -278,17 +349,11 @@ typedef struct let_value { unsigned null_pointer_ref:1; } let_value; -static inline let_value *init_let_value(let_func *func, impl_var *var) { +static inline let_value *init_let_value(let_func *func, impl_var *var, int null_pointer_ref) { let_value *val = malloc(sizeof(*val)); - - if (!func || !var) { - val->null_pointer_ref = 1; - } else { - val->null_pointer_ref = 0; - } + val->null_pointer_ref = null_pointer_ref; val->func = func; val->var = var; - return val; } @@ -469,3 +534,27 @@ static inline void free_impl(impl *impl) { free_impl_stmts(impl->stmts); free(impl); } + +typedef struct impls { + size_t count; + impl **list; +} impls; + +static impls *add_impl(impls *impls, impl *impl) { + if (!impls) { + impls = calloc(1, sizeof(*impls)); + } + impls->list = realloc(impls->list, ++impls->count * sizeof(*impls->list)); + impls->list[impls->count-1] = impl; + return impls; +} + +static void free_impls(impls *impls) { + size_t i; + + for (i = 0; i < impls->count; ++i) { + free_impl(impls->list[i]); + } + free(impls->list); + free(impls); +} -- 2.30.2