flush
authorMichael Wallner <mike@php.net>
Wed, 14 Oct 2015 18:47:17 +0000 (20:47 +0200)
committerMichael Wallner <mike@php.net>
Wed, 14 Oct 2015 18:51:53 +0000 (20:51 +0200)
31 files changed:
.gitignore
AUTHORS [new file with mode: 0644]
BUGS [new file with mode: 0644]
CONTRIBUTING.md [new file with mode: 0644]
CREDITS [new file with mode: 0644]
EXPERIMENTAL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile.frag [new file with mode: 0644]
README.md [new file with mode: 0644]
THANKS [new file with mode: 0644]
TODO
config.m4 [new file with mode: 0644]
idl/compiler.c [deleted file]
idl/compiler.h [deleted file]
idl/parser.h [deleted file]
idl/parser.re [deleted file]
idl/parser_proc.h [deleted file]
idl/parser_proc.y [deleted file]
idl/validator.c [deleted file]
idl/validator.h [deleted file]
package.xml [new file with mode: 0644]
php_psi.h [new file with mode: 0644]
src/compiler.c [new file with mode: 0644]
src/compiler.h [new file with mode: 0644]
src/module.c [new file with mode: 0644]
src/parser.h [new file with mode: 0644]
src/parser.re [new file with mode: 0644]
src/parser_proc.h [new file with mode: 0644]
src/parser_proc.y [new file with mode: 0644]
src/validator.c [new file with mode: 0644]
src/validator.h [new file with mode: 0644]

index 8ec900333feafadc31cb0a3404ea488fd9007577..70680cf0df90f2d9d888415f779c31339cb3fe4c 100644 (file)
@@ -1,8 +1,43 @@
 *.dSYM
 /idl/main
-/idl/parser.c
-/idl/lemon.c
-/idl/lempar.c
-/idl/lemon
-/idl/parser_proc.out
-/idl/parser_proc.c
+/lemon.c
+/lempar.c
+/lemon
+/src/parser.c
+/src/parser_proc.out
+/src/parser_proc.c
+.deps
+*.lo
+*.la
+.libs
+acinclude.m4
+aclocal.m4
+autom4te.cache
+build
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+include
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+missing
+mkinstalldirs
+modules
+run-tests.php
+tests/*/*.diff
+tests/*/*.out
+tests/*/*.php
+tests/*/*.exp
+tests/*/*.log
+tests/*/*.sh
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..67bbd91
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Michael Wallner <mike@php.net>
diff --git a/BUGS b/BUGS
new file mode 100644 (file)
index 0000000..ebbf227
--- /dev/null
+++ b/BUGS
@@ -0,0 +1 @@
+Yay, no known and unresolved issues yet!
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..968bd44
--- /dev/null
@@ -0,0 +1,39 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project, and in the interest of
+fostering an open and welcoming community, we pledge to respect all people who
+contribute through reporting issues, posting feature requests, updating
+documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free
+experience for everyone, regardless of level of experience, gender, gender
+identity and expression, sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information, such as physical or electronic
+  addresses, without explicit permission
+* Other unethical or unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct. By adopting this Code of Conduct, project
+maintainers commit themselves to fairly and consistently applying these
+principles to every aspect of managing this project. Project maintainers who do
+not follow or enforce the Code of Conduct may be permanently removed from the
+project team.
+
+This code of conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by opening an issue or contacting one or more of the project maintainers.
+
+This Code of Conduct is adapted from the
+[Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
+available at http://contributor-covenant.org/version/1/2/0/.
diff --git a/CREDITS b/CREDITS
new file mode 100644 (file)
index 0000000..7c8d2da
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,2 @@
+psi
+Michael Wallner
diff --git a/EXPERIMENTAL b/EXPERIMENTAL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..f52c89a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2015, Michael Wallner <mike@php.net>.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile.frag b/Makefile.frag
new file mode 100644 (file)
index 0000000..fbf6c9c
--- /dev/null
@@ -0,0 +1,30 @@
+# provide headers in builddir, so they do not end up in /usr/include/ext/psi/src
+
+PHP_PSI_HEADERS := $(addprefix $(PHP_PSI_BUILDDIR)/,$(PHP_PSI_HEADERS))
+
+$(PHP_PSI_BUILDDIR)/%.h: $(PHP_PSI_SRCDIR)/src/%.h
+       @cat >$@ <$<
+
+all: psi-build-headers
+clean: psi-clean-headers
+
+.PHONY: psi-build-headers
+psi-build-headers: $(PHP_PSI_HEADERS)
+
+.PHONY: psi-clean-headers
+psi-clean-headers:
+       -rm -f $(PHP_PSI_HEADERS)
+
+lempar.c:
+       curl -sSo $@ "http://www.sqlite.org/src/raw/tool/lempar.c?name=3617143ddb9b176c3605defe6a9c798793280120"
+
+lemon.c:
+       curl -sSo $@ "http://www.sqlite.org/src/raw/tool/lemon.c?name=039f813b520b9395740c52f9cbf36c90b5d8df03"
+
+./lemon: lemon.c | lempar.c
+
+$(PHP_PSI_BUILDDIR)/src/parser_proc.c: $(PHP_PSI_SRCDIR)/src/parser_proc.y $(LEMON)
+       $(LEMON) -c $<
+
+$(PHP_PSI_BUILDDIR)/src/parser.c: $(PHP_PSI_SRCDIR)/src/parser.re
+       $(RE2C) -o $@ $<
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..46956de
--- /dev/null
+++ b/README.md
@@ -0,0 +1,48 @@
+# psi
+
+[![Build Status](https://travis-ci.org/m6w6/psi.svg?branch=master)](https://travis-ci.org/m6w6/psi)
+
+...
+
+## Documentation
+
+See the [online markdown reference](https://mdref.m6w6.name/psi).
+
+Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
+
+## Installing
+
+### PECL
+
+       pecl install psi
+
+### PHARext
+
+Watch out for [PECL replicates](https://replicator.pharext.org?psi)
+and pharext packages attached to [releases](./releases).
+
+### Checkout
+
+       git clone github.com:m6w6/psi
+       cd psi
+       /path/to/phpize
+       ./configure --with-php-config=/path/to/php-config
+       make
+       sudo make install
+
+## ChangeLog
+
+A comprehensive list of changes can be obtained from the
+[PECL website](https://pecl.php.net/package-changelog.php?package=psi).
+
+## License
+
+psi is licensed under the 2-Clause-BSD license, which can be found in
+the accompanying [LICENSE](./LICENSE) file.
+
+## Contributing
+
+All forms of contribution are welcome! Please see the bundled
+[CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
+
+The list of past and current contributors is maintained in [THANKS](./THANKS).
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..d0eae43
--- /dev/null
+++ b/THANKS
@@ -0,0 +1 @@
+Thanks go to the following people, who have contributed to this project:
diff --git a/TODO b/TODO
index 09344d0312240a7e09f116927af5f329be3c7be1..22c7d4067f66c8bbc2657661ac4432948144a3a2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
 * move numbers to the lexer
 * avoid allocs inside structures by reallocating the whole structure
 * let the various list types be hashtables where appropriate
+* check out jit-dynamic
diff --git a/config.m4 b/config.m4
new file mode 100644 (file)
index 0000000..999f61c
--- /dev/null
+++ b/config.m4
@@ -0,0 +1,43 @@
+PHP_ARG_ENABLE(psi, whether to enable psi support,
+[  --with-psi[[=path to libjit]]
+                          Enable PHP System Interface support])
+
+if test "$PHP_PSI" != "no"; then
+       AC_ARG_VAR(LEMON, The lemon parser generator of the SQLite project)
+       AC_PATH_PROG(LEMON, lemon, ./lemon)
+       PHP_SUBST(LEMON)
+
+       AC_CACHE_CHECK(for libjit install root, PSI_cv_LIBJIT_DIR, [
+       for PSI_cv_LIBJIT_DIR in {/usr{,/local},/opt}{,libjit}
+       do
+               if test -e $PSI_cv_LIBJIT_DIR/include/jit/jit.h
+               then
+                       break
+               fi
+               PSI_cv_LIBJIT_DIR=
+       done])
+       if test -z "$PSI_cv_LIBJIT_DIR"
+       then
+               AC_MSG_ERROR([Could not find libjit, please provide the base install path])
+       fi
+
+       PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi)
+       PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi)
+
+       PHP_ADD_INCLUDE($PHP_PSI_SRCDIR/src)
+       PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src)
+
+       PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && echo *.h)`
+       PHP_PSI_SOURCES=`(cd $PHP_PSI_SRCDIR && echo src/*.c)`
+
+       PHP_NEW_EXTENSION(psi, $PHP_PSI_SOURCES, $ext_shared)
+       PHP_INSTALL_HEADERS(ext/psi, php_psi.h $PHP_PSI_HEADERS)
+
+       PHP_SUBST(PHP_PSI_HEADERS)
+       PHP_SUBST(PHP_PSI_SOURCES)
+
+       PHP_SUBST(PHP_PSI_SRCDIR)
+       PHP_SUBST(PHP_PSI_BUILDDIR)
+
+       PHP_ADD_MAKEFILE_FRAGMENT
+fi
diff --git a/idl/compiler.c b/idl/compiler.c
deleted file mode 100644 (file)
index 02f3867..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdlib.h>
-
-#include "compiler.h"
-
-PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V)
-{
-       if (!C) {
-               C = malloc(sizeof(*C));
-       }
-       memset(C, 0, sizeof(*C));
-
-       PSI_DataExchange((PSI_Data *) C, (PSI_Data *) V);
-       return C;
-}
diff --git a/idl/compiler.h b/idl/compiler.h
deleted file mode 100644 (file)
index c5e447f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _PSI_COMPILER_H
-#define _PSI_COMPILER_H
-
-#include "validator.h"
-
-typedef struct PSI_Compiler {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
-} PSI_Compiler;
-
-PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V);
-
-#endif
diff --git a/idl/parser.h b/idl/parser.h
deleted file mode 100644 (file)
index dcb464b..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-#ifndef _PSI_PARSER_H
-#define _PSI_PARSER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "parser_proc.h"
-
-#define BSIZE 256
-
-typedef int token_t;
-
-typedef struct PSI_Token {
-       token_t type;
-       unsigned line;
-       size_t size;
-       char text[1];
-} PSI_Token;
-
-typedef struct decl_type {
-       char *name;
-       token_t type;
-       struct decl_type *real;
-} decl_type;
-
-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);
-       return t;
-}
-
-static inline void free_decl_type(decl_type *type) {
-       free(type->name);
-       free(type);
-}
-
-typedef struct decl_typedef {
-       char *alias;
-       decl_type *type;
-} decl_typedef;
-
-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;
-       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 {
-       char *name;
-       unsigned pointer_level;
-} decl_var;
-
-static inline decl_var *init_decl_var(char *name, unsigned pl) {
-       decl_var *v = malloc(sizeof(*v));
-       v->name = (char *) strdup((const char *) name);
-       v->pointer_level = pl;
-       return v;
-}
-
-static inline void free_decl_var(decl_var *var) {
-       free(var->name);
-       free(var);
-}
-
-typedef struct decl_arg {
-       decl_type *type;
-       decl_var *var;
-} decl_arg;
-
-static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
-       decl_arg *arg = malloc(sizeof(*arg));
-       arg->type = type;
-       arg->var = var;
-       return arg;
-}
-
-static inline void free_decl_arg(decl_arg *arg) {
-       free_decl_type(arg->type);
-       free_decl_var(arg->var);
-       free(arg);
-}
-
-typedef struct decl_vars {
-       decl_var **vars;
-       size_t count;
-} decl_vars;
-
-static inline decl_vars *init_decl_vars(decl_var *var) {
-       decl_vars *vars = malloc(sizeof(*vars));
-       vars->count = 1;
-       vars->vars = malloc(sizeof(*vars->vars));
-       vars->vars[0] = var;
-       return vars;
-}
-
-static inline decl_vars *add_decl_var(decl_vars *vars, decl_var *var) {
-       vars->vars = realloc(vars->vars, ++vars->count * sizeof(*vars->vars));
-       vars->vars[vars->count-1] = var;
-       return vars;
-}
-
-static inline void free_decl_vars(decl_vars *vars) {
-       size_t i;
-
-       for (i = 0; i < vars->count; ++i) {
-               free_decl_var(vars->vars[i]);
-       }
-       free(vars->vars);
-       free(vars);
-}
-
-typedef struct decl_args {
-       decl_arg **args;
-       size_t count;
-} decl_args;
-
-static inline decl_args *init_decl_args(decl_arg *arg) {
-       decl_args *args = malloc(sizeof(*args));
-       args->count = 1;
-       args->args = malloc(sizeof(*args->args));
-       args->args[0] = arg;
-       return args;
-}
-
-static inline decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
-       args->args = realloc(args->args, ++args->count * sizeof(*args->args));
-       args->args[args->count-1] = arg;
-       return args;
-}
-
-static inline void free_decl_args(decl_args *args) {
-       size_t i;
-
-       for (i = 0; i < args->count; ++i) {
-               free_decl_arg(args->args[i]);
-       }
-       free(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_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 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 {
-       char *name;
-       token_t type;
-} impl_type;
-
-static inline impl_type *init_impl_type(token_t type, char *name) {
-       impl_type *t = malloc(sizeof(*t));
-
-       t->type = type;
-       t->name = (char *) strdup((const char *) name);
-       return t;
-}
-
-static inline void free_impl_type(impl_type *type) {
-       free(type->name);
-       free(type);
-}
-
-typedef struct impl_var {
-       char *name;
-       unsigned reference:1;
-} impl_var;
-
-static inline impl_var *init_impl_var(char *name, int is_reference) {
-       impl_var *var = malloc(sizeof(*var));
-       var->name = (char *) strdup((const char *) name);
-       var->reference = is_reference;
-       return var;
-}
-
-static inline void free_impl_var(impl_var *var) {
-       free(var->name);
-       free(var);
-}
-
-typedef struct impl_def_val {
-       token_t type;
-       union {
-               int64_t digits;
-               double decimals;
-       } v;
-       unsigned is_null:1;
-} impl_def_val;
-
-static inline impl_def_val *init_impl_def_val() {
-       impl_def_val *def = malloc(sizeof(*def));
-       def->type = 0;
-       def->is_null = 1;
-       return def;
-}
-
-static inline void free_impl_def_val(impl_def_val *def) {
-       free(def);
-}
-
-typedef struct impl_arg {
-       impl_type *type;
-       impl_var *var;
-       impl_def_val *def;
-} impl_arg;
-
-static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
-       impl_arg *arg = malloc(sizeof(*arg));
-       arg->type = type;
-       arg->var = var;
-       arg->def = def;
-       return arg;
-}
-
-static inline void free_impl_arg(impl_arg *arg) {
-       free_impl_type(arg->type);
-       free_impl_var(arg->var);
-       if (arg->def) {
-               free_impl_def_val(arg->def);
-       }
-       free(arg);
-}
-
-typedef struct impl_args {
-       impl_arg **args;
-       size_t count;
-} impl_args;
-
-static inline impl_args *init_impl_args(impl_arg *arg) {
-       impl_args *args = malloc(sizeof(*args));
-       args->args = malloc(sizeof(*args->args));
-       if (arg) {
-               args->count = 1;
-               args->args[0] = arg;
-       } else {
-               args->count = 0;
-               args->args = NULL;
-       }
-       return args;
-}
-
-static inline impl_args *add_impl_arg(impl_args *args, impl_arg *arg) {
-       args->args = realloc(args->args, ++args->count * sizeof(*args->args));
-       args->args[args->count-1] = arg;
-       return args;
-}
-
-static inline void free_impl_args(impl_args *args) {
-       size_t i;
-
-       for (i = 0; i < args->count; ++i) {
-               free_impl_arg(args->args[i]);
-       }
-       free(args->args);
-       free(args);
-}
-
-typedef struct impl_func {
-       char *name;
-       impl_args *args;
-       impl_type *return_type;
-} impl_func;
-
-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);
-       func->return_type = type;
-       return func;
-}
-
-static inline void free_impl_func(impl_func *f) {
-       free_impl_type(f->return_type);
-       free_impl_args(f->args);
-       free(f->name);
-       free(f);
-}
-
-typedef struct let_func {
-       token_t type;
-       char *name;
-} let_func;
-
-static inline let_func *init_let_func(token_t type, char *name) {
-       let_func *func = malloc(sizeof(*func));
-       func->type = type;
-       func->name = (char *) strdup((const char *) name);
-       return func;
-}
-
-static inline void free_let_func(let_func *func) {
-       free(func->name);
-       free(func);
-}
-
-typedef struct let_value {
-       let_func *func;
-       impl_var *var;
-       unsigned null_pointer_ref:1;
-} let_value;
-
-static inline let_value *init_let_value(let_func *func, impl_var *var, int null_pointer_ref) {
-       let_value *val = malloc(sizeof(*val));
-       val->null_pointer_ref = null_pointer_ref;
-       val->func = func;
-       val->var = var;
-       return val;
-}
-
-static inline void free_let_value(let_value *val) {
-       if (val->func) {
-               free_let_func(val->func);
-       }
-       if (val->var) {
-               free_impl_var(val->var);
-       }
-       free(val);
-}
-
-typedef struct let_stmt {
-       decl_var *var;
-       let_value *val;
-} let_stmt;
-
-static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) {
-       let_stmt *let = malloc(sizeof(*let));
-       let->var = var;
-       let->val = val;
-       return let;
-}
-
-static inline void free_let_stmt(let_stmt *stmt) {
-       free_decl_var(stmt->var);
-       free_let_value(stmt->val);
-       free(stmt);
-}
-
-typedef struct set_func {
-       token_t type;
-       char *name;
-} set_func;
-
-static inline set_func *init_set_func(token_t type, char *name) {
-       set_func *func = malloc(sizeof(*func));
-       func->type = type;
-       func->name = (char *) strdup((const char *) name);
-       return func;
-}
-
-static inline void free_set_func(set_func *func) {
-       free(func->name);
-       free(func);
-}
-
-typedef struct set_value {
-       set_func *func;
-       decl_vars *vars;
-} set_value;
-
-static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
-       set_value *val = malloc(sizeof(*val));
-       val->func = func;
-       val->vars = vars;
-       return val;
-}
-
-static inline void free_set_value(set_value *val) {
-       free_set_func(val->func);
-       free_decl_vars(val->vars);
-       free(val);
-}
-
-typedef struct set_stmt {
-       impl_var *var;
-       set_value *val;
-} set_stmt;
-
-static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) {
-       set_stmt *set = malloc(sizeof(*set));
-       set->var = var;
-       set->val = val;
-       return set;
-}
-
-static inline void free_set_stmt(set_stmt *set) {
-       free_impl_var(set->var);
-       free_set_value(set->val);
-       free(set);
-}
-
-typedef struct ret_stmt {
-       set_func *func;
-       decl_var *decl;
-} ret_stmt;
-
-static inline ret_stmt *init_ret_stmt(set_func *func, decl_var *decl) {
-       ret_stmt *ret = malloc(sizeof(*ret));
-       ret->func = func;
-       ret->decl = decl;
-       return ret;
-}
-
-static inline void free_ret_stmt(ret_stmt *ret) {
-       free_set_func(ret->func);
-       free_decl_var(ret->decl);
-       free(ret);
-}
-
-typedef struct impl_stmt {
-       token_t type;
-       union {
-               let_stmt *let;
-               set_stmt *set;
-               ret_stmt *ret;
-               void *ptr;
-       } s;
-} impl_stmt;
-
-static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) {
-       impl_stmt *stmt = malloc(sizeof(*stmt));
-       stmt->type = type;
-       stmt->s.ptr = ptr;
-       return stmt;
-}
-
-static inline void free_impl_stmt(impl_stmt *stmt) {
-       switch (stmt->type) {
-       case PSI_T_LET:
-               free_let_stmt(stmt->s.let);
-               break;
-       case PSI_T_SET:
-               free_set_stmt(stmt->s.set);
-               break;
-       case PSI_T_RET:
-               free_ret_stmt(stmt->s.ret);
-               break;
-       }
-       free(stmt);
-}
-
-typedef struct impl_stmts {
-       impl_stmt **stmts;
-       size_t count;
-} impl_stmts;
-
-static inline impl_stmts *init_impl_stmts(impl_stmt *stmt) {
-       impl_stmts *stmts = malloc(sizeof(*stmts));
-       stmts->count = 1;
-       stmts->stmts = malloc(sizeof(*stmts->stmts));
-       stmts->stmts[0] = stmt;
-       return stmts;
-}
-
-static inline impl_stmts *add_impl_stmt(impl_stmts *stmts, impl_stmt *stmt) {
-       stmts->stmts = realloc(stmts->stmts, ++stmts->count * sizeof(*stmts->stmts));
-       stmts->stmts[stmts->count-1] = stmt;
-       return stmts;
-}
-
-static inline void free_impl_stmts(impl_stmts *stmts) {
-       size_t i;
-
-       for (i = 0; i < stmts->count; ++i) {
-               free_impl_stmt(stmts->stmts[i]);
-       }
-       free(stmts->stmts);
-       free(stmts);
-}
-
-typedef struct impl {
-       impl_func *func;
-       impl_stmts *stmts;
-} impl;
-
-static inline impl *init_impl(impl_func *func, impl_stmts *stmts) {
-       impl *i = malloc(sizeof(*i));
-       i->func = func;
-       i->stmts = stmts;
-       return i;
-}
-
-static inline void free_impl(impl *impl) {
-       free_impl_func(impl->func);
-       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);
-}
-
-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));
-}
-
-static inline void PSI_DataDtor(PSI_Data *data) {
-       if (data->defs) {
-               free_decl_typedefs(data->defs);
-       }
-       if (data->decls) {
-               free_decls(data->decls);
-       }
-       if (data->impls) {
-               free_impls(data->impls);
-       }
-       if (data->lib) {
-               free(data->lib);
-       }
-       if (data->fn) {
-               free(data->fn);
-       }
-}
-
-typedef struct PSI_Parser {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
-       FILE *fp;
-       void *proc;
-       size_t line;
-       token_t num;
-       char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
-} PSI_Parser;
-
-static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
-       PSI_Token *T;
-       size_t token_len;
-
-       if (P->cur <= P->tok) {
-               return NULL;
-       }
-
-       token_len = P->cur - P->tok;
-
-       T = malloc(sizeof(*T) + token_len);
-       T->type = P->num;
-       T->line = P->line;
-       T->size = token_len;
-       T->text[token_len] = 0;
-       memcpy(T->text, P->tok, token_len);
-
-       return T;
-}
-
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename);
-size_t PSI_ParserFill(PSI_Parser *P, size_t n);
-token_t PSI_ParserScan(PSI_Parser *P);
-void PSI_ParserParse(PSI_Parser *P, PSI_Token *T);
-void PSI_ParserDtor(PSI_Parser *P);
-void PSI_ParserFree(PSI_Parser **P);
-
-#endif
diff --git a/idl/parser.re b/idl/parser.re
deleted file mode 100644 (file)
index 5a06023..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-#include <stdio.h>
-#include <assert.h>
-
-#include "parser.h"
-#include "parser_proc.h"
-
-void *PSI_ParserProcAlloc(void*(unsigned long));
-void PSI_ParserProcFree(void*, void(*)(void*));
-void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
-
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename)
-{
-       FILE *fp;
-
-       if (!P) {
-               P = malloc(sizeof(*P));
-       }
-       memset(P, 0, sizeof(*P));
-
-       fp = fopen(filename, "r");
-
-       if (!fp) {
-               perror(filename);
-               return NULL;
-       }
-
-       if (!P) {
-               P = malloc(sizeof(*P));
-       }
-       memset(P, 0, sizeof(*P));
-
-       P->fp = fp;
-       P->fn = strdup(filename);
-       P->line = 1;
-
-       P->proc = PSI_ParserProcAlloc(malloc);
-
-       PSI_ParserFill(P, 0);
-
-       return P;
-}
-
-size_t PSI_ParserFill(PSI_Parser *P, size_t n)
-{
-       // printf("+ Fill: n=%zu\n", n);
-       if (!n) {
-               P->cur = P->tok = P->lim = P->mrk = P->buf;
-               P->eof = NULL;
-       }
-
-       if (!P->eof) {
-               size_t consumed = P->tok - P->buf;
-               size_t reserved = P->lim - P->tok;
-               size_t available = BSIZE - reserved;
-               size_t didread;
-
-               if (consumed) {
-                       memmove(P->buf, P->tok, reserved);
-                       P->tok -= consumed;
-                       P->cur -= consumed;
-                       P->lim -= consumed;
-                       P->mrk -= consumed;
-               }
-
-               didread = fread(P->lim, 1, available, P->fp);
-               P->lim += didread;
-               if (didread < available) {
-                       P->eof = P->lim;
-               }
-
-               // printf("+ Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
-                       // consumed, reserved, available, didread);
-       }
-       // printf("+ Fill: avail=%zu\n", P->lim - P->cur);
-       return P->lim - P->cur;
-}
-
-void PSI_ParserParse(PSI_Parser *P, PSI_Token *T)
-{
-       if (T) {
-               PSI_ParserProc(P->proc, T->type, T, P);
-       } else {
-               PSI_ParserProc(P->proc, 0, NULL, P);
-       }
-}
-
-void PSI_ParserDtor(PSI_Parser *P)
-{
-       PSI_ParserProcFree(P->proc, free);
-
-       if (P->fp) {
-               fclose(P->fp);
-       }
-
-       PSI_DataDtor((PSI_Data *) P);
-
-       memset(P, 0, sizeof(*P));
-}
-
-void PSI_ParserFree(PSI_Parser **P)
-{
-       if (*P) {
-               PSI_ParserDtor(*P);
-               free(*P);
-               *P = NULL;
-       }
-}
-
-/*!max:re2c*/
-#define BSIZE 256
-
-#if BSIZE < YYMAXFILL
-# error BSIZE must be greater than YYMAXFILL
-#endif
-
-#define RETURN(t) do { \
-       P->num = t; \
-       return t; \
-} while(1)
-
-token_t PSI_ParserScan(PSI_Parser *P)
-{
-       for (;;) {
-               P->tok = P->cur;
-               /*!re2c
-               re2c:indent:top = 2;
-               re2c:define:YYCTYPE = "unsigned char";
-               re2c:define:YYCURSOR = P->cur;
-               re2c:define:YYLIMIT = P->lim;
-               re2c:define:YYMARKER = P->mrk;
-               re2c:define:YYFILL = "{ if (!PSI_ParserFill(P,@@)) RETURN(-1); }";
-               re2c:yyfill:parameter = 0;
-
-               B = [^a-zA-Z0-9_];
-               W = [a-zA-Z0-9_];
-               NAME = W+;
-               NSNAME = (NAME)? ("\\" NAME)+;
-               QUOTED_STRING = "\"" ([^\"])+ "\"";
-               NULL = 'NULL';
-               MIXED = 'mixed';
-               VOID = 'void';
-               BOOL = 'bool';
-               INT = 'int';
-               FLOAT = 'float';
-               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';
-               STRVAL = 'strval';
-               INTVAL = 'intval';
-               FLOATVAL = 'floatval';
-               BOOLVAL = 'boolval';
-               TO_STRING = 'to_string';
-               TO_INT = 'to_int';
-               TO_FLOAT = 'to_float';
-               TO_BOOL = 'to_bool';
-
-               "#" .* "\n" { ++P->line; RETURN(PSI_T_COMMENT);}
-               "(" {RETURN(PSI_T_LPAREN);}
-               ")" {RETURN(PSI_T_RPAREN);}
-               ";" {RETURN(PSI_T_EOS);}
-               "," {RETURN(PSI_T_COMMA);}
-               ":" {RETURN(PSI_T_COLON);}
-               "{" {RETURN(PSI_T_LBRACE);}
-               "}" {RETURN(PSI_T_RBRACE);}
-               "." {RETURN(PSI_T_DOT);}
-               "=" {RETURN(PSI_T_EQUALS);}
-               "$" {RETURN(PSI_T_DOLLAR);}
-               "*" {RETURN(PSI_T_POINTER);}
-               "&" {RETURN(PSI_T_REFERENCE);}
-               [\r\n] { ++P->line; continue; }
-               [\t ]+ { continue; }
-               NULL {RETURN(PSI_T_NULL);}
-               MIXED {RETURN(PSI_T_MIXED);}
-               VOID {RETURN(PSI_T_VOID);}
-               BOOL {RETURN(PSI_T_BOOL);}
-               INT {RETURN(PSI_T_INT);}
-               FLOAT {RETURN(PSI_T_FLOAT);}
-               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);}
-               STRVAL {RETURN(PSI_T_STRVAL);}
-               INTVAL {RETURN(PSI_T_INTVAL);}
-               FLOATVAL {RETURN(PSI_T_FLOATVAL);}
-               BOOLVAL {RETURN(PSI_T_BOOLVAL);}
-               TO_STRING {RETURN(PSI_T_TO_STRING);}
-               TO_INT {RETURN(PSI_T_TO_INT);}
-               TO_FLOAT {RETURN(PSI_T_TO_FLOAT);}
-               TO_BOOL {RETURN(PSI_T_TO_BOOL);}
-               [0-9] {RETURN(PSI_T_DIGIT);}
-               NAME {RETURN(PSI_T_NAME);}
-               NSNAME {RETURN(PSI_T_NSNAME);}
-               QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
-               */
-       }
-       return -1;
-}
diff --git a/idl/parser_proc.h b/idl/parser_proc.h
deleted file mode 100644 (file)
index 3be3c66..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#define PSI_T_COMMENT                          1
-#define PSI_T_LIB                              2
-#define PSI_T_QUOTED_STRING                    3
-#define PSI_T_EOS                              4
-#define PSI_T_TYPEDEF                          5
-#define PSI_T_NAME                             6
-#define PSI_T_LPAREN                           7
-#define PSI_T_RPAREN                           8
-#define PSI_T_COMMA                            9
-#define PSI_T_VOID                            10
-#define PSI_T_INT                             11
-#define PSI_T_FLOAT                           12
-#define PSI_T_DOUBLE                          13
-#define PSI_T_SINT8                           14
-#define PSI_T_UINT8                           15
-#define PSI_T_SINT16                          16
-#define PSI_T_UINT16                          17
-#define PSI_T_SINT32                          18
-#define PSI_T_UINT32                          19
-#define PSI_T_SINT64                          20
-#define PSI_T_UINT64                          21
-#define PSI_T_LBRACE                          22
-#define PSI_T_RBRACE                          23
-#define PSI_T_FUNCTION                        24
-#define PSI_T_NSNAME                          25
-#define PSI_T_COLON                           26
-#define PSI_T_NULL                            27
-#define PSI_T_DOLLAR                          28
-#define PSI_T_REFERENCE                       29
-#define PSI_T_EQUALS                          30
-#define PSI_T_LET                             31
-#define PSI_T_STRVAL                          32
-#define PSI_T_INTVAL                          33
-#define PSI_T_FLOATVAL                        34
-#define PSI_T_BOOLVAL                         35
-#define PSI_T_SET                             36
-#define PSI_T_TO_STRING                       37
-#define PSI_T_TO_INT                          38
-#define PSI_T_TO_FLOAT                        39
-#define PSI_T_TO_BOOL                         40
-#define PSI_T_RET                             41
-#define PSI_T_MIXED                           42
-#define PSI_T_BOOL                            43
-#define PSI_T_STRING                          44
-#define PSI_T_ARRAY                           45
-#define PSI_T_DIGIT                           46
-#define PSI_T_DOT                             47
-#define PSI_T_PLUS                            48
-#define PSI_T_MINUS                           49
-#define PSI_T_POINTER                         50
diff --git a/idl/parser_proc.y b/idl/parser_proc.y
deleted file mode 100644 (file)
index 47de153..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-%include {
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "parser.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_ParserProc
-%token_prefix PSI_T_
-%token_type {PSI_Token *}
-%token_destructor {free($$);}
-%extra_argument {PSI_Parser *P}
-/* TOKEN is defined inside syntax_error */
-%syntax_error {
-       syntax_error(P->fn, P->line, "Unexpected token '%s'.\n", TOKEN->text);
-}
-file ::= blocks.
-
-blocks ::= block.
-blocks ::= blocks block.
-
-block ::= COMMENT.
-
-block ::= LIB(T) QUOTED_STRING(libname) EOS. {
-       if (P->lib) {
-               syntax_error(P->fn, T->line, "Extra 'lib %s' statement has no effect.\n", libname->text);
-       } else {
-               P->lib = strndup(libname->text + 1, libname->size - 2);
-       }
-       free(libname);
-       free(T);
-}
-
-block ::= decl(decl). {
-       P->decls = add_decl(P->decls, decl);
-}
-block ::= impl(impl). {
-       P->impls = add_impl(P->impls, impl);
-}
-block ::= decl_typedef(def). {
-       P->defs = add_decl_typedef(P->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);
-}
-
-%type decl {decl*}
-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);
-       free(T);
-}
-decl_var(var) ::= pointers(p) NAME(T). {
-       var = init_decl_var(T->text, p);
-       free(T);
-}
-
-%type decl_vars {decl_vars*}
-decl_vars(vars) ::= decl_var(var). {
-       vars = init_decl_vars(var);
-}
-decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). {
-       vars = add_decl_var(vars_, var);
-}
-
-%type decl_arg {decl_arg*}
-decl_arg(arg) ::= decl_type(type) decl_var(var). {
-       arg = init_decl_arg(type, var);
-}
-
-%type decl_args {decl_args*}
-decl_args(args) ::= decl_arg(arg). {
-       args = init_decl_args(arg);
-}
-decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). {
-       args = add_decl_arg(args_, arg);
-}
-
-%type decl_type {decl_type*}
-decl_type(type_) ::= VOID(T). {
-       type_ = init_decl_type(T->type, T->text);
-       free(T);
-}
-decl_type(type_) ::= INT(T). {
-       type_ = init_decl_type(T->type, T->text);
-       free(T);
-}
-decl_type(type_) ::= FLOAT(T). {
-       type_ = init_decl_type(T->type, T->text);
-       free(T);
-}
-decl_type(type_) ::= DOUBLE(T). {
-       type_ = init_decl_type(T->type, T->text);
-       free(T);
-}
-decl_type(type_) ::= SINT8(T). {
-       type_ = init_decl_type(T->type, T->text);
-       free(T);
-}
-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) LBRACE impl_stmts(stmts) RBRACE. {
-       impl = init_impl(func, stmts);
-}
-
-%type impl_func {impl_func*}
-impl_func(func) ::= FUNCTION NSNAME(NAME) LPAREN impl_args(args) RPAREN COLON impl_type(type). {
-       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. {
-       /* FIXME */
-       def = init_impl_def_val();
-}
-impl_def_val(def) ::= number. {
-       /* FIXME */
-       def = init_impl_def_val();
-}
-
-%type impl_var {impl_var*}
-impl_var(var) ::= DOLLAR NAME(T). {
-       var = init_impl_var(T->text, 0);
-       free(T);
-}
-impl_var(var) ::= REFERENCE DOLLAR NAME(T). {
-       var = init_impl_var(T->text, 1);
-       free(T);
-}
-
-%type impl_arg {impl_arg*}
-impl_arg(arg) ::= impl_type(type) impl_var(var). {
-       arg = init_impl_arg(type, var, NULL);
-}
-impl_arg(arg) ::= impl_type(type) impl_var(var) EQUALS impl_def_val(def). {
-       arg = init_impl_arg(type, var, def);
-}
-
-%type impl_args {impl_args*}
-impl_args(args) ::= impl_arg(arg). {
-       args = init_impl_args(arg);
-}
-impl_args(args) ::= impl_args(args_) COMMA impl_arg(arg). {
-       args = add_impl_arg(args_, arg);
-}
-
-%type impl_stmts {impl_stmts*}
-impl_stmts(stmts) ::= impl_stmt(stmt). {
-       stmts = init_impl_stmts(stmt);
-}
-impl_stmts(stmts) ::= impl_stmts(stmts_) impl_stmt(stmt). {
-       stmts = add_impl_stmt(stmts_, stmt);
-}
-
-%type impl_stmt {impl_stmt*}
-impl_stmt(stmt) ::= let_stmt(let). {
-       stmt = init_impl_stmt(PSI_T_LET, let);
-}
-impl_stmt(stmt) ::= set_stmt(set). {
-       stmt = init_impl_stmt(PSI_T_SET, set);
-}
-impl_stmt(stmt) ::= ret_stmt(ret). {
-       stmt = init_impl_stmt(PSI_T_RET, ret);
-}
-
-%type let_stmt {let_stmt*}
-let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. {
-       let = init_let_stmt(var, val);
-}
-
-%type let_value {let_value*}
-let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. {
-       val = init_let_value(func, var, 0);
-}
-let_value(val) ::= REFERENCE NULL. {
-       val = init_let_value(NULL, NULL, 1);
-}
-let_value(val) ::= NULL. {
-       val = init_let_value(NULL, NULL, 0);
-}
-
-%type let_func {let_func*}
-let_func(func) ::= STRVAL(T). {
-       func = init_let_func(T->type, T->text);
-       free(T);
-}
-let_func(func) ::= INTVAL(T). {
-       func = init_let_func(T->type, T->text);
-       free(T);
-}
-let_func(func) ::= FLOATVAL(T). {
-       func = init_let_func(T->type, T->text);
-       free(T);
-}
-let_func(func) ::= BOOLVAL(T). {
-       func = init_let_func(T->type, T->text);
-       free(T);
-}
-
-%type set_stmt {set_stmt*}
-set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. {
-       set = init_set_stmt(var, val);
-}
-
-%type set_value {set_value*}
-set_value(val) ::= set_func(func) LPAREN decl_vars(vars) RPAREN. {
-       val = init_set_value(func, vars);
-}
-
-%type set_func {set_func*}
-set_func(func) ::= TO_STRING(T). {
-       func = init_set_func(T->type, T->text);
-       free(T);
-}
-set_func(func) ::= TO_INT(T). {
-       func = init_set_func(T->type, T->text);
-       free(T);
-}
-set_func(func) ::= TO_FLOAT(T). {
-       func = init_set_func(T->type, T->text);
-       free(T);
-}
-set_func(func) ::= TO_BOOL(T). {
-       func = init_set_func(T->type, T->text);
-       free(T);
-}
-
-%type ret_stmt {ret_stmt*}
-ret_stmt(ret) ::= RET set_func(func) LPAREN decl_var(var) RPAREN EOS. {
-       ret = init_ret_stmt(func, var);
-}
-
-%type impl_type {impl_type*}
-impl_type(type_) ::= VOID(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= MIXED(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= BOOL(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= INT(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= FLOAT(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= STRING(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-impl_type(type_) ::= ARRAY(T). {
-       type_ = init_impl_type(T->type, T->text);
-       free(T);
-}
-
-digits ::= DIGIT.
-digits ::= digits DIGIT.
-decimals ::= digits DOT digits.
-decimals ::= DOT digits.
-decimals ::= digits DOT.
-number ::= digits.
-number ::= PLUS digits.
-number ::= MINUS digits.
-number ::= decimals.
-number ::= MINUS decimals.
-number ::= PLUS decimals.
-
-%type pointers {unsigned}
-pointers(p) ::= POINTER. {++p;}
-pointers(p) ::= pointers(P) POINTER. {p = ++P;}
diff --git a/idl/validator.c b/idl/validator.c
deleted file mode 100644 (file)
index 87951eb..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <sys/param.h>
-
-#include "validator.h"
-
-PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
-{
-       if (!V) {
-               V = malloc(sizeof(*V));
-       }
-       memset(V, 0, sizeof(*V));
-
-       PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
-
-       return V;
-}
-
-void PSI_ValidatorDtor(PSI_Validator *V)
-{
-       PSI_DataDtor((PSI_Data *) V);
-       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_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
-       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
deleted file mode 100644 (file)
index f96111c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _PSI_VALIDATOR_H
-#define _PSI_VALIDATOR_H
-
-#include "parser.h"
-
-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_Parser *P);
-int PSI_ValidatorValidate(PSI_Validator *V);
-void PSI_ValidatorFree(PSI_Validator **V);
-void PSI_ValidatorDtor(PSI_Validator *V);
-
-#endif
diff --git a/package.xml b/package.xml
new file mode 100644 (file)
index 0000000..06f2bde
--- /dev/null
@@ -0,0 +1,3 @@
+
+Parse error: parse error in /Users/Mike/Sources/repo-template.git/presets/package.xml on line 2
+
diff --git a/php_psi.h b/php_psi.h
new file mode 100644 (file)
index 0000000..0828ebe
--- /dev/null
+++ b/php_psi.h
@@ -0,0 +1,43 @@
+
+#ifndef PHP_PSI_H
+#define PHP_PSI_H
+
+extern zend_module_entry psi_module_entry;
+#define phpext_psi_ptr &psi_module_entry
+
+#define PHP_PSI_VERSION "0.1.0"
+
+#ifdef PHP_WIN32
+#      define PHP_PSI_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#      define PHP_PSI_API __attribute__ ((visibility("default")))
+#else
+#      define PHP_PSI_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+ZEND_BEGIN_MODULE_GLOBALS(psi)
+       char *directory;
+       void *context;
+ZEND_END_MODULE_GLOBALS(psi);
+
+#define PSI_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(psi, v)
+
+#if defined(ZTS) && defined(COMPILE_DL_PSI)
+ZEND_TSRMLS_CACHE_EXTERN();
+#endif
+
+#endif /* PHP_PSI_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/src/compiler.c b/src/compiler.c
new file mode 100644 (file)
index 0000000..e075a39
--- /dev/null
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+
+#include <jit/jit.h>
+
+#include <php.h>
+#include <Zend/Zend_API.h>
+
+#include "compiler.h"
+
+PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V)
+{
+       if (!C) {
+               C = malloc(sizeof(*C));
+       }
+       memset(C, 0, sizeof(*C));
+
+       PSI_DataExchange((PSI_Data *) C, (PSI_Data *) V);
+       return C;
+}
+
+typedef struct PSI_ClosureData {
+       impl *impl;
+} PSI_ClosureData;
+
+static inline size_t impl_num_min_args(impl *impl) {
+       size_t i, n = impl->func->args->count;
+
+       for (i = 0; i < impl->func->args->count; ++i) {
+               if (impl->func->args->args[i]->def) {
+                       --n;
+               }
+       }
+       return n;
+}
+void PSI_Closure(jit_type_t signature, void *result, void **args, void *user_data)
+{
+       zend_execute_data *execute_data = args[0];
+       zval *return_value = args[1];
+       PSI_ClosureData *data = user_data;
+       impl_arg *iarg;
+
+       if (!data->impl->func->args->count) {
+               if (SUCCESS != zend_parse_parameters_none()) {
+                       return;
+               }
+       } else
+       ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data->impl), data->impl->func->args->count)
+       nextarg:
+               iarg = data->impl->func->args->args[_i];
+               if (iarg->def) {
+                       Z_PARAM_OPTIONAL;
+               }
+               if (PSI_T_BOOL == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
+                       }
+                       Z_PARAM_BOOL(iarg->val.bval);
+               } else if (PSI_T_INT == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.lval = atol(iarg->def->text);
+                       }
+                       Z_PARAM_LONG(iarg->val.lval);
+               } else if (PSI_T_FLOAT == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.dval = strtod(iarg->def->text, NULL);
+                       }
+                       Z_PARAM_DOUBLE(iarg->val.dval);
+               } else if (PSI_T_STRING == iarg->type->type) {
+                       if (iarg->def) {
+                               /* FIXME */
+                               iarg->val.str.len = strlen(iarg->def->text) - 2;
+                               iarg->val.str.val = &iarg->def->text[1];
+                       }
+                       Z_PARAM_STRING(iarg->val.str.val, iarg->val.str.len);
+               } else {
+                       error_code = ZPP_ERROR_FAILURE;
+                       break;
+               }
+               goto nextarg;
+       ZEND_PARSE_PARAMETERS_END();
+}
diff --git a/src/compiler.h b/src/compiler.h
new file mode 100644 (file)
index 0000000..c5e447f
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _PSI_COMPILER_H
+#define _PSI_COMPILER_H
+
+#include "validator.h"
+
+typedef struct PSI_Compiler {
+       decl_typedefs *defs;
+       decls *decls;
+       impls *impls;
+       char *lib;
+       char *fn;
+} PSI_Compiler;
+
+PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V);
+
+#endif
diff --git a/src/module.c b/src/module.c
new file mode 100644 (file)
index 0000000..c45ddb0
--- /dev/null
@@ -0,0 +1,107 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jit/jit.h>
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_psi.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(psi);
+
+PHP_INI_BEGIN()
+    STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals)
+PHP_INI_END();
+
+PHP_MINIT_FUNCTION(psi)
+{
+       jit_context_t ctx;
+
+       REGISTER_INI_ENTRIES();
+
+       jit_init();
+
+       if (!(ctx = jit_context_create())) {
+               zend_error(E_WARNING, "Could not initialize libjit!");
+               return FAILURE;
+       }
+
+       PSI_G(context) = ctx;
+
+       return SUCCESS;
+}
+PHP_MSHUTDOWN_FUNCTION(psi)
+{
+       jit_context_t *ctx = PSI_G(context);
+
+       jit_context_destroy(ctx);
+       
+       UNREGISTER_INI_ENTRIES();
+
+       return SUCCESS;
+}
+
+/* Remove if there's nothing to do at request start */
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(psi)
+{
+#if defined(COMPILE_DL_PSI) && defined(ZTS)
+       ZEND_TSRMLS_CACHE_UPDATE();
+#endif
+       return SUCCESS;
+}
+/* }}} */
+
+/* Remove if there's nothing to do at request end */
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+PHP_RSHUTDOWN_FUNCTION(psi)
+{
+       return SUCCESS;
+}
+/* }}} */
+
+PHP_MINFO_FUNCTION(psi)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, "psi support", "enabled");
+       php_info_print_table_end();
+
+       DISPLAY_INI_ENTRIES();
+}
+const zend_function_entry psi_functions[] = {
+       PHP_FE_END
+};
+
+zend_module_entry psi_module_entry = {
+       STANDARD_MODULE_HEADER,
+       "psi",
+       psi_functions,
+       PHP_MINIT(psi),
+       PHP_MSHUTDOWN(psi),
+       PHP_RINIT(psi),         /* Replace with NULL if there's nothing to do at request start */
+       PHP_RSHUTDOWN(psi),     /* Replace with NULL if there's nothing to do at request end */
+       PHP_MINFO(psi),
+       PHP_PSI_VERSION,
+       STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_PSI
+#ifdef ZTS
+ZEND_TSRMLS_CACHE_DEFINE();
+#endif
+ZEND_GET_MODULE(psi)
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/src/parser.h b/src/parser.h
new file mode 100644 (file)
index 0000000..d4909dd
--- /dev/null
@@ -0,0 +1,717 @@
+#ifndef _PSI_PARSER_H
+#define _PSI_PARSER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <Zend/zend_types.h>
+
+#include "parser_proc.h"
+
+#define BSIZE 256
+
+typedef int token_t;
+
+typedef struct PSI_Token {
+       token_t type;
+       unsigned line;
+       size_t size;
+       char text[1];
+} PSI_Token;
+
+typedef struct decl_type {
+       char *name;
+       token_t type;
+       struct decl_type *real;
+} decl_type;
+
+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);
+       return t;
+}
+
+static inline void free_decl_type(decl_type *type) {
+       free(type->name);
+       free(type);
+}
+
+typedef struct decl_typedef {
+       char *alias;
+       decl_type *type;
+} decl_typedef;
+
+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;
+       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 {
+       char *name;
+       unsigned pointer_level;
+} decl_var;
+
+static inline decl_var *init_decl_var(char *name, unsigned pl) {
+       decl_var *v = malloc(sizeof(*v));
+       v->name = (char *) strdup((const char *) name);
+       v->pointer_level = pl;
+       return v;
+}
+
+static inline void free_decl_var(decl_var *var) {
+       free(var->name);
+       free(var);
+}
+
+typedef struct decl_arg {
+       decl_type *type;
+       decl_var *var;
+} decl_arg;
+
+static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
+       decl_arg *arg = malloc(sizeof(*arg));
+       arg->type = type;
+       arg->var = var;
+       return arg;
+}
+
+static inline void free_decl_arg(decl_arg *arg) {
+       free_decl_type(arg->type);
+       free_decl_var(arg->var);
+       free(arg);
+}
+
+typedef struct decl_vars {
+       decl_var **vars;
+       size_t count;
+} decl_vars;
+
+static inline decl_vars *init_decl_vars(decl_var *var) {
+       decl_vars *vars = malloc(sizeof(*vars));
+       vars->count = 1;
+       vars->vars = malloc(sizeof(*vars->vars));
+       vars->vars[0] = var;
+       return vars;
+}
+
+static inline decl_vars *add_decl_var(decl_vars *vars, decl_var *var) {
+       vars->vars = realloc(vars->vars, ++vars->count * sizeof(*vars->vars));
+       vars->vars[vars->count-1] = var;
+       return vars;
+}
+
+static inline void free_decl_vars(decl_vars *vars) {
+       size_t i;
+
+       for (i = 0; i < vars->count; ++i) {
+               free_decl_var(vars->vars[i]);
+       }
+       free(vars->vars);
+       free(vars);
+}
+
+typedef struct decl_args {
+       decl_arg **args;
+       size_t count;
+} decl_args;
+
+static inline decl_args *init_decl_args(decl_arg *arg) {
+       decl_args *args = malloc(sizeof(*args));
+       args->count = 1;
+       args->args = malloc(sizeof(*args->args));
+       args->args[0] = arg;
+       return args;
+}
+
+static inline decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
+       args->args = realloc(args->args, ++args->count * sizeof(*args->args));
+       args->args[args->count-1] = arg;
+       return args;
+}
+
+static inline void free_decl_args(decl_args *args) {
+       size_t i;
+
+       for (i = 0; i < args->count; ++i) {
+               free_decl_arg(args->args[i]);
+       }
+       free(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_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 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 {
+       char *name;
+       token_t type;
+} impl_type;
+
+static inline impl_type *init_impl_type(token_t type, char *name) {
+       impl_type *t = malloc(sizeof(*t));
+
+       t->type = type;
+       t->name = (char *) strdup((const char *) name);
+       return t;
+}
+
+static inline void free_impl_type(impl_type *type) {
+       free(type->name);
+       free(type);
+}
+
+typedef struct impl_var {
+       char *name;
+       unsigned reference:1;
+} impl_var;
+
+static inline impl_var *init_impl_var(char *name, int is_reference) {
+       impl_var *var = malloc(sizeof(*var));
+       var->name = (char *) strdup((const char *) name);
+       var->reference = is_reference;
+       return var;
+}
+
+static inline void free_impl_var(impl_var *var) {
+       free(var->name);
+       free(var);
+}
+
+typedef struct impl_def_val {
+       token_t type;
+       char *text;
+} impl_def_val;
+
+static inline impl_def_val *init_impl_def_val(PSI_Token *T) {
+       impl_def_val *def = malloc(sizeof(*def));
+       def->type = T->type;
+       def->text = strdup(T->text);
+       return def;
+}
+
+static inline void free_impl_def_val(impl_def_val *def) {
+       free(def->text);
+       free(def);
+}
+
+typedef struct impl_arg {
+       impl_type *type;
+       impl_var *var;
+       impl_def_val *def;
+       union {
+               unsigned char bval;
+               zend_long lval;
+               double dval;
+               struct {
+                       char *val;
+                       size_t len;
+               } str;
+       } val;
+} impl_arg;
+
+static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
+       impl_arg *arg = malloc(sizeof(*arg));
+       arg->type = type;
+       arg->var = var;
+       arg->def = def;
+       return arg;
+}
+
+static inline void free_impl_arg(impl_arg *arg) {
+       free_impl_type(arg->type);
+       free_impl_var(arg->var);
+       if (arg->def) {
+               free_impl_def_val(arg->def);
+       }
+       free(arg);
+}
+
+typedef struct impl_args {
+       impl_arg **args;
+       size_t count;
+} impl_args;
+
+static inline impl_args *init_impl_args(impl_arg *arg) {
+       impl_args *args = malloc(sizeof(*args));
+       args->args = malloc(sizeof(*args->args));
+       if (arg) {
+               args->count = 1;
+               args->args[0] = arg;
+       } else {
+               args->count = 0;
+               args->args = NULL;
+       }
+       return args;
+}
+
+static inline impl_args *add_impl_arg(impl_args *args, impl_arg *arg) {
+       args->args = realloc(args->args, ++args->count * sizeof(*args->args));
+       args->args[args->count-1] = arg;
+       return args;
+}
+
+static inline void free_impl_args(impl_args *args) {
+       size_t i;
+
+       for (i = 0; i < args->count; ++i) {
+               free_impl_arg(args->args[i]);
+       }
+       free(args->args);
+       free(args);
+}
+
+typedef struct impl_func {
+       char *name;
+       impl_args *args;
+       impl_type *return_type;
+} impl_func;
+
+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);
+       func->return_type = type;
+       return func;
+}
+
+static inline void free_impl_func(impl_func *f) {
+       free_impl_type(f->return_type);
+       free_impl_args(f->args);
+       free(f->name);
+       free(f);
+}
+
+typedef struct let_func {
+       token_t type;
+       char *name;
+} let_func;
+
+static inline let_func *init_let_func(token_t type, char *name) {
+       let_func *func = malloc(sizeof(*func));
+       func->type = type;
+       func->name = (char *) strdup((const char *) name);
+       return func;
+}
+
+static inline void free_let_func(let_func *func) {
+       free(func->name);
+       free(func);
+}
+
+typedef struct let_value {
+       let_func *func;
+       impl_var *var;
+       unsigned null_pointer_ref:1;
+} let_value;
+
+static inline let_value *init_let_value(let_func *func, impl_var *var, int null_pointer_ref) {
+       let_value *val = malloc(sizeof(*val));
+       val->null_pointer_ref = null_pointer_ref;
+       val->func = func;
+       val->var = var;
+       return val;
+}
+
+static inline void free_let_value(let_value *val) {
+       if (val->func) {
+               free_let_func(val->func);
+       }
+       if (val->var) {
+               free_impl_var(val->var);
+       }
+       free(val);
+}
+
+typedef struct let_stmt {
+       decl_var *var;
+       let_value *val;
+} let_stmt;
+
+static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) {
+       let_stmt *let = malloc(sizeof(*let));
+       let->var = var;
+       let->val = val;
+       return let;
+}
+
+static inline void free_let_stmt(let_stmt *stmt) {
+       free_decl_var(stmt->var);
+       free_let_value(stmt->val);
+       free(stmt);
+}
+
+typedef struct set_func {
+       token_t type;
+       char *name;
+} set_func;
+
+static inline set_func *init_set_func(token_t type, char *name) {
+       set_func *func = malloc(sizeof(*func));
+       func->type = type;
+       func->name = (char *) strdup((const char *) name);
+       return func;
+}
+
+static inline void free_set_func(set_func *func) {
+       free(func->name);
+       free(func);
+}
+
+typedef struct set_value {
+       set_func *func;
+       decl_vars *vars;
+} set_value;
+
+static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
+       set_value *val = malloc(sizeof(*val));
+       val->func = func;
+       val->vars = vars;
+       return val;
+}
+
+static inline void free_set_value(set_value *val) {
+       free_set_func(val->func);
+       free_decl_vars(val->vars);
+       free(val);
+}
+
+typedef struct set_stmt {
+       impl_var *var;
+       set_value *val;
+} set_stmt;
+
+static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) {
+       set_stmt *set = malloc(sizeof(*set));
+       set->var = var;
+       set->val = val;
+       return set;
+}
+
+static inline void free_set_stmt(set_stmt *set) {
+       free_impl_var(set->var);
+       free_set_value(set->val);
+       free(set);
+}
+
+typedef struct ret_stmt {
+       set_func *func;
+       decl_var *decl;
+} ret_stmt;
+
+static inline ret_stmt *init_ret_stmt(set_func *func, decl_var *decl) {
+       ret_stmt *ret = malloc(sizeof(*ret));
+       ret->func = func;
+       ret->decl = decl;
+       return ret;
+}
+
+static inline void free_ret_stmt(ret_stmt *ret) {
+       free_set_func(ret->func);
+       free_decl_var(ret->decl);
+       free(ret);
+}
+
+typedef struct impl_stmt {
+       token_t type;
+       union {
+               let_stmt *let;
+               set_stmt *set;
+               ret_stmt *ret;
+               void *ptr;
+       } s;
+} impl_stmt;
+
+static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) {
+       impl_stmt *stmt = malloc(sizeof(*stmt));
+       stmt->type = type;
+       stmt->s.ptr = ptr;
+       return stmt;
+}
+
+static inline void free_impl_stmt(impl_stmt *stmt) {
+       switch (stmt->type) {
+       case PSI_T_LET:
+               free_let_stmt(stmt->s.let);
+               break;
+       case PSI_T_SET:
+               free_set_stmt(stmt->s.set);
+               break;
+       case PSI_T_RET:
+               free_ret_stmt(stmt->s.ret);
+               break;
+       }
+       free(stmt);
+}
+
+typedef struct impl_stmts {
+       struct {
+               ret_stmt **list;
+               size_t count;
+       } ret;
+       struct {
+               let_stmt **list;
+               size_t count;
+       } let;
+       struct {
+               set_stmt **list;
+               size_t count;
+       } set;
+} impl_stmts;
+
+static inline void *add_impl_stmt_ex(void *list, size_t count, void *stmt) {
+       list = realloc(list, count * sizeof(list));
+       ((void **)list)[count-1] = stmt;
+       return list;
+}
+
+static inline impl_stmts *add_impl_stmt(impl_stmts *stmts, impl_stmt *stmt) {
+       switch (stmt->type) {
+       case PSI_T_RET:
+               stmts->ret.list = add_impl_stmt_ex(stmts->ret.list, ++stmts->ret.count, stmt->s.ret);
+               break;
+       case PSI_T_LET:
+               stmts->let.list = add_impl_stmt_ex(stmts->let.list, ++stmts->let.count, stmt->s.let);
+               break;
+       case PSI_T_SET:
+               stmts->set.list = add_impl_stmt_ex(stmts->set.list, ++stmts->set.count, stmt->s.set);
+               break;
+       }
+       return stmts;
+}
+
+static inline impl_stmts *init_impl_stmts(impl_stmt *stmt) {
+       impl_stmts *stmts = calloc(1, sizeof(*stmts));
+       return add_impl_stmt(stmts, stmt);
+}
+
+static inline void free_impl_stmts(impl_stmts *stmts) {
+       size_t i;
+
+       for (i = 0; i < stmts->let.count; ++i) {
+               free_let_stmt(stmts->let.list[i]);
+       }
+       free(stmts->let.list);
+       for (i = 0; i < stmts->ret.count; ++i) {
+               free_ret_stmt(stmts->ret.list[i]);
+       }
+       free(stmts->ret.list);
+       for (i = 0; i < stmts->set.count; ++i) {
+               free_set_stmt(stmts->set.list[i]);
+       }
+       free(stmts->set.list);
+       free(stmts);
+}
+
+typedef struct impl {
+       impl_func *func;
+       impl_stmts *stmts;
+       decl *decl;
+} impl;
+
+static inline impl *init_impl(impl_func *func, impl_stmts *stmts) {
+       impl *i = malloc(sizeof(*i));
+       i->func = func;
+       i->stmts = stmts;
+       return i;
+}
+
+static inline void free_impl(impl *impl) {
+       free_impl_func(impl->func);
+       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);
+}
+
+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));
+}
+
+static inline void PSI_DataDtor(PSI_Data *data) {
+       if (data->defs) {
+               free_decl_typedefs(data->defs);
+       }
+       if (data->decls) {
+               free_decls(data->decls);
+       }
+       if (data->impls) {
+               free_impls(data->impls);
+       }
+       if (data->lib) {
+               free(data->lib);
+       }
+       if (data->fn) {
+               free(data->fn);
+       }
+}
+
+typedef struct PSI_Parser {
+       decl_typedefs *defs;
+       decls *decls;
+       impls *impls;
+       char *lib;
+       char *fn;
+       FILE *fp;
+       unsigned flags;
+       unsigned errors;
+       void *proc;
+       size_t line;
+       token_t num;
+       char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
+} PSI_Parser;
+
+static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
+       PSI_Token *T;
+       size_t token_len;
+
+       if (P->cur <= P->tok) {
+               return NULL;
+       }
+
+       token_len = P->cur - P->tok;
+
+       T = malloc(sizeof(*T) + token_len);
+       T->type = P->num;
+       T->line = P->line;
+       T->size = token_len;
+       T->text[token_len] = 0;
+       memcpy(T->text, P->tok, token_len);
+
+       return T;
+}
+
+#define PSI_PARSER_DEBUG 0x1
+
+PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags);
+void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...);
+size_t PSI_ParserFill(PSI_Parser *P, size_t n);
+token_t PSI_ParserScan(PSI_Parser *P);
+void PSI_ParserParse(PSI_Parser *P, PSI_Token *T);
+void PSI_ParserDtor(PSI_Parser *P);
+void PSI_ParserFree(PSI_Parser **P);
+
+#endif
diff --git a/src/parser.re b/src/parser.re
new file mode 100644 (file)
index 0000000..906e8b9
--- /dev/null
@@ -0,0 +1,268 @@
+#include <stdio.h>
+#include <assert.h>
+
+#include "parser.h"
+#include "parser_proc.h"
+
+void *PSI_ParserProcAlloc(void*(unsigned long));
+void PSI_ParserProcFree(void*, void(*)(void*));
+void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
+void PSI_ParserProcTrace(FILE *, const char*);
+
+PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags)
+{
+       FILE *fp;
+
+       if (!P) {
+               P = malloc(sizeof(*P));
+       }
+       memset(P, 0, sizeof(*P));
+
+       fp = fopen(filename, "r");
+
+       if (!fp) {
+               perror(filename);
+               return NULL;
+       }
+
+       if (!P) {
+               P = malloc(sizeof(*P));
+       }
+       memset(P, 0, sizeof(*P));
+
+       P->fp = fp;
+       P->fn = strdup(filename);
+       P->line = 1;
+       P->flags = flags;
+
+       P->proc = PSI_ParserProcAlloc(malloc);
+       if (flags & PSI_PARSER_DEBUG) {
+               PSI_ParserProcTrace(stderr, "PSI> ");
+       }
+
+       PSI_ParserFill(P, 0);
+
+       return P;
+}
+
+void PSI_ParserSyntaxError(PSI_Parser *P, 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);
+       }
+       ++P->errors;
+}
+
+size_t PSI_ParserFill(PSI_Parser *P, size_t n)
+{
+       if (P->flags & PSI_PARSER_DEBUG) {
+               fprintf(stderr, "PSI> Fill: n=%zu\n", n);
+       }
+       if (!n) {
+               P->cur = P->tok = P->lim = P->mrk = P->buf;
+               P->eof = NULL;
+       }
+
+       if (!P->eof) {
+               size_t consumed = P->tok - P->buf;
+               size_t reserved = P->lim - P->tok;
+               size_t available = BSIZE - reserved;
+               size_t didread;
+
+               if (consumed) {
+                       memmove(P->buf, P->tok, reserved);
+                       P->tok -= consumed;
+                       P->cur -= consumed;
+                       P->lim -= consumed;
+                       P->mrk -= consumed;
+               }
+
+               didread = fread(P->lim, 1, available, P->fp);
+               P->lim += didread;
+               if (didread < available) {
+                       P->eof = P->lim;
+               }
+
+               if (P->flags & PSI_PARSER_DEBUG) {
+                       fprintf(stderr, "PSI> Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
+                               consumed, reserved, available, didread);
+               }
+       }
+       if (P->flags & PSI_PARSER_DEBUG) {
+               fprintf(stderr, "PSI> Fill: avail=%zu\n", P->lim - P->cur);
+       }
+       return P->lim - P->cur;
+}
+
+void PSI_ParserParse(PSI_Parser *P, PSI_Token *T)
+{
+       if (T) {
+               PSI_ParserProc(P->proc, T->type, T, P);
+       } else {
+               PSI_ParserProc(P->proc, 0, NULL, P);
+       }
+}
+
+void PSI_ParserDtor(PSI_Parser *P)
+{
+       PSI_ParserProcFree(P->proc, free);
+
+       if (P->fp) {
+               fclose(P->fp);
+       }
+
+       PSI_DataDtor((PSI_Data *) P);
+
+       memset(P, 0, sizeof(*P));
+}
+
+void PSI_ParserFree(PSI_Parser **P)
+{
+       if (*P) {
+               PSI_ParserDtor(*P);
+               free(*P);
+               *P = NULL;
+       }
+}
+
+/*!max:re2c*/
+#define BSIZE 256
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater than YYMAXFILL
+#endif
+
+#define RETURN(t) do { \
+       P->num = t; \
+       return t; \
+} while(1)
+
+/*             DIGIT = [0-9]
+               DIGITS = DIGIT+
+               DECIMALS = (+|-)? DIGIT* "."
+               digits ::= digits DIGIT.
+               decimals ::= digits DOT digits.
+               decimals ::= DOT digits.
+               decimals ::= digits DOT.
+               number ::= digits.
+               number ::= PLUS digits.
+               number ::= MINUS digits.
+               number ::= decimals.
+               number ::= MINUS decimals.
+               number ::= PLUS decimals.
+
+*/
+token_t PSI_ParserScan(PSI_Parser *P)
+{
+       for (;;) {
+               P->tok = P->cur;
+               /*!re2c
+               re2c:indent:top = 2;
+               re2c:define:YYCTYPE = "unsigned char";
+               re2c:define:YYCURSOR = P->cur;
+               re2c:define:YYLIMIT = P->lim;
+               re2c:define:YYMARKER = P->mrk;
+               re2c:define:YYFILL = "{ if (!PSI_ParserFill(P,@@)) RETURN(-1); }";
+               re2c:yyfill:parameter = 0;
+
+               B = [^a-zA-Z0-9_];
+               W = [a-zA-Z0-9_];
+               NAME = [a-zA-Z_]W*;
+               NSNAME = (NAME)? ("\\" NAME)+;
+               QUOTED_STRING = "\"" ([^\"])+ "\"";
+               TRUE = 'TRUE';
+               FALSE = 'FALSE';
+               NULL = 'NULL';
+               MIXED = 'mixed';
+               VOID = 'void';
+               BOOL = 'bool';
+               INT = 'int';
+               FLOAT = 'float';
+               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';
+               STRLEN = 'strlen';
+               STRVAL = 'strval';
+               INTVAL = 'intval';
+               FLOATVAL = 'floatval';
+               BOOLVAL = 'boolval';
+               TO_STRING = 'to_string';
+               TO_INT = 'to_int';
+               TO_FLOAT = 'to_float';
+               TO_BOOL = 'to_bool';
+               NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
+
+               "#" .* "\n" { ++P->line; RETURN(PSI_T_COMMENT);}
+               "(" {RETURN(PSI_T_LPAREN);}
+               ")" {RETURN(PSI_T_RPAREN);}
+               ";" {RETURN(PSI_T_EOS);}
+               "," {RETURN(PSI_T_COMMA);}
+               ":" {RETURN(PSI_T_COLON);}
+               "{" {RETURN(PSI_T_LBRACE);}
+               "}" {RETURN(PSI_T_RBRACE);}
+               "=" {RETURN(PSI_T_EQUALS);}
+               "$" {RETURN(PSI_T_DOLLAR);}
+               "*" {RETURN(PSI_T_POINTER);}
+               "&" {RETURN(PSI_T_REFERENCE);}
+               [\r\n] { ++P->line; continue; }
+               [\t ]+ { continue; }
+               TRUE {RETURN(PSI_T_TRUE);}
+               FALSE {RETURN(PSI_T_FALSE);}
+               NULL {RETURN(PSI_T_NULL);}
+               MIXED {RETURN(PSI_T_MIXED);}
+               VOID {RETURN(PSI_T_VOID);}
+               BOOL {RETURN(PSI_T_BOOL);}
+               INT {RETURN(PSI_T_INT);}
+               FLOAT {RETURN(PSI_T_FLOAT);}
+               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);}
+               STRLEN {RETURN(PSI_T_STRLEN);}
+               STRVAL {RETURN(PSI_T_STRVAL);}
+               INTVAL {RETURN(PSI_T_INTVAL);}
+               FLOATVAL {RETURN(PSI_T_FLOATVAL);}
+               BOOLVAL {RETURN(PSI_T_BOOLVAL);}
+               TO_STRING {RETURN(PSI_T_TO_STRING);}
+               TO_INT {RETURN(PSI_T_TO_INT);}
+               TO_FLOAT {RETURN(PSI_T_TO_FLOAT);}
+               TO_BOOL {RETURN(PSI_T_TO_BOOL);}
+               NUMBER {RETURN(PSI_T_NUMBER);}
+               NAME {RETURN(PSI_T_NAME);}
+               NSNAME {RETURN(PSI_T_NSNAME);}
+               QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
+               */
+       }
+       return -1;
+}
diff --git a/src/parser_proc.h b/src/parser_proc.h
new file mode 100644 (file)
index 0000000..d8466df
--- /dev/null
@@ -0,0 +1,50 @@
+#define PSI_T_COMMENT                          1
+#define PSI_T_LIB                              2
+#define PSI_T_QUOTED_STRING                    3
+#define PSI_T_EOS                              4
+#define PSI_T_TYPEDEF                          5
+#define PSI_T_NAME                             6
+#define PSI_T_LPAREN                           7
+#define PSI_T_RPAREN                           8
+#define PSI_T_COMMA                            9
+#define PSI_T_VOID                            10
+#define PSI_T_INT                             11
+#define PSI_T_FLOAT                           12
+#define PSI_T_DOUBLE                          13
+#define PSI_T_SINT8                           14
+#define PSI_T_UINT8                           15
+#define PSI_T_SINT16                          16
+#define PSI_T_UINT16                          17
+#define PSI_T_SINT32                          18
+#define PSI_T_UINT32                          19
+#define PSI_T_SINT64                          20
+#define PSI_T_UINT64                          21
+#define PSI_T_LBRACE                          22
+#define PSI_T_RBRACE                          23
+#define PSI_T_FUNCTION                        24
+#define PSI_T_NSNAME                          25
+#define PSI_T_COLON                           26
+#define PSI_T_NULL                            27
+#define PSI_T_NUMBER                          28
+#define PSI_T_TRUE                            29
+#define PSI_T_FALSE                           30
+#define PSI_T_DOLLAR                          31
+#define PSI_T_REFERENCE                       32
+#define PSI_T_EQUALS                          33
+#define PSI_T_LET                             34
+#define PSI_T_STRLEN                          35
+#define PSI_T_STRVAL                          36
+#define PSI_T_INTVAL                          37
+#define PSI_T_FLOATVAL                        38
+#define PSI_T_BOOLVAL                         39
+#define PSI_T_SET                             40
+#define PSI_T_TO_STRING                       41
+#define PSI_T_TO_INT                          42
+#define PSI_T_TO_FLOAT                        43
+#define PSI_T_TO_BOOL                         44
+#define PSI_T_RET                             45
+#define PSI_T_MIXED                           46
+#define PSI_T_BOOL                            47
+#define PSI_T_STRING                          48
+#define PSI_T_ARRAY                           49
+#define PSI_T_POINTER                         50
diff --git a/src/parser_proc.y b/src/parser_proc.y
new file mode 100644 (file)
index 0000000..66946ca
--- /dev/null
@@ -0,0 +1,327 @@
+%include {
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "parser.h"
+
+}
+
+%name PSI_ParserProc
+%token_prefix PSI_T_
+%token_type {PSI_Token *}
+%token_destructor {free($$);}
+%extra_argument {PSI_Parser *P}
+/* TOKEN is defined inside syntax_error */
+%syntax_error {
+       PSI_ParserSyntaxError(P, P->fn, P->line, "Unexpected token '%s'.\n", TOKEN->text);
+}
+file ::= blocks.
+
+blocks ::= block.
+blocks ::= blocks block.
+
+block ::= COMMENT.
+
+block ::= LIB(T) QUOTED_STRING(libname) EOS. {
+       if (P->lib) {
+               PSI_ParserSyntaxError(P, P->fn, T->line, "Extra 'lib %s' statement has no effect.\n", libname->text);
+       } else {
+               P->lib = strndup(libname->text + 1, libname->size - 2);
+       }
+       free(libname);
+       free(T);
+}
+
+block ::= decl(decl). {
+       P->decls = add_decl(P->decls, decl);
+}
+block ::= impl(impl). {
+       P->impls = add_impl(P->impls, impl);
+}
+block ::= decl_typedef(def). {
+       P->defs = add_decl_typedef(P->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);
+}
+
+%type decl {decl*}
+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);
+       free(T);
+}
+decl_var(var) ::= pointers(p) NAME(T). {
+       var = init_decl_var(T->text, p);
+       free(T);
+}
+
+%type decl_vars {decl_vars*}
+decl_vars(vars) ::= decl_var(var). {
+       vars = init_decl_vars(var);
+}
+decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). {
+       vars = add_decl_var(vars_, var);
+}
+
+%type decl_arg {decl_arg*}
+decl_arg(arg) ::= decl_type(type) decl_var(var). {
+       arg = init_decl_arg(type, var);
+}
+
+%type decl_args {decl_args*}
+decl_args(args) ::= decl_arg(arg). {
+       args = init_decl_args(arg);
+}
+decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). {
+       args = add_decl_arg(args_, arg);
+}
+
+%type decl_type {decl_type*}
+decl_type(type_) ::= VOID(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+decl_type(type_) ::= INT(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+decl_type(type_) ::= FLOAT(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+decl_type(type_) ::= DOUBLE(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+decl_type(type_) ::= SINT8(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+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) LBRACE impl_stmts(stmts) RBRACE. {
+       impl = init_impl(func, stmts);
+}
+
+%type impl_func {impl_func*}
+impl_func(func) ::= FUNCTION NSNAME(NAME) LPAREN impl_args(args) RPAREN COLON impl_type(type). {
+       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(T). {
+       def = init_impl_def_val(T);
+}
+impl_def_val(def) ::= NUMBER(T). {
+       def = init_impl_def_val(T);
+}
+impl_def_val(def) ::= TRUE(T). {
+       def = init_impl_def_val(T);
+}
+impl_def_val(def) ::= FALSE(T). {
+       def = init_impl_def_val(T);
+}
+impl_def_val(def) ::= QUOTED_STRING(T). {
+       def = init_impl_def_val(T);
+}
+
+%type impl_var {impl_var*}
+impl_var(var) ::= DOLLAR NAME(T). {
+       var = init_impl_var(T->text, 0);
+       free(T);
+}
+impl_var(var) ::= REFERENCE DOLLAR NAME(T). {
+       var = init_impl_var(T->text, 1);
+       free(T);
+}
+
+%type impl_arg {impl_arg*}
+impl_arg(arg) ::= impl_type(type) impl_var(var). {
+       arg = init_impl_arg(type, var, NULL);
+}
+impl_arg(arg) ::= impl_type(type) impl_var(var) EQUALS impl_def_val(def). {
+       arg = init_impl_arg(type, var, def);
+}
+
+%type impl_args {impl_args*}
+impl_args(args) ::= impl_arg(arg). {
+       args = init_impl_args(arg);
+}
+impl_args(args) ::= impl_args(args_) COMMA impl_arg(arg). {
+       args = add_impl_arg(args_, arg);
+}
+
+%type impl_stmts {impl_stmts*}
+impl_stmts(stmts) ::= impl_stmt(stmt). {
+       stmts = init_impl_stmts(stmt);
+}
+impl_stmts(stmts) ::= impl_stmts(stmts_) impl_stmt(stmt). {
+       stmts = add_impl_stmt(stmts_, stmt);
+}
+
+%type impl_stmt {impl_stmt*}
+impl_stmt(stmt) ::= let_stmt(let). {
+       stmt = init_impl_stmt(PSI_T_LET, let);
+}
+impl_stmt(stmt) ::= set_stmt(set). {
+       stmt = init_impl_stmt(PSI_T_SET, set);
+}
+impl_stmt(stmt) ::= ret_stmt(ret). {
+       stmt = init_impl_stmt(PSI_T_RET, ret);
+}
+
+%type let_stmt {let_stmt*}
+let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. {
+       let = init_let_stmt(var, val);
+}
+
+%type let_value {let_value*}
+let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. {
+       val = init_let_value(func, var, 0);
+}
+let_value(val) ::= REFERENCE NULL. {
+       val = init_let_value(NULL, NULL, 1);
+}
+let_value(val) ::= NULL. {
+       val = init_let_value(NULL, NULL, 0);
+}
+
+%type let_func {let_func*}
+let_func(func) ::= STRLEN(T). {
+       func = init_let_func(T->type, T->text);
+       free(T);
+}
+let_func(func) ::= STRVAL(T). {
+       func = init_let_func(T->type, T->text);
+       free(T);
+}
+let_func(func) ::= INTVAL(T). {
+       func = init_let_func(T->type, T->text);
+       free(T);
+}
+let_func(func) ::= FLOATVAL(T). {
+       func = init_let_func(T->type, T->text);
+       free(T);
+}
+let_func(func) ::= BOOLVAL(T). {
+       func = init_let_func(T->type, T->text);
+       free(T);
+}
+
+%type set_stmt {set_stmt*}
+set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. {
+       set = init_set_stmt(var, val);
+}
+
+%type set_value {set_value*}
+set_value(val) ::= set_func(func) LPAREN decl_vars(vars) RPAREN. {
+       val = init_set_value(func, vars);
+}
+
+%type set_func {set_func*}
+set_func(func) ::= TO_STRING(T). {
+       func = init_set_func(T->type, T->text);
+       free(T);
+}
+set_func(func) ::= TO_INT(T). {
+       func = init_set_func(T->type, T->text);
+       free(T);
+}
+set_func(func) ::= TO_FLOAT(T). {
+       func = init_set_func(T->type, T->text);
+       free(T);
+}
+set_func(func) ::= TO_BOOL(T). {
+       func = init_set_func(T->type, T->text);
+       free(T);
+}
+
+%type ret_stmt {ret_stmt*}
+ret_stmt(ret) ::= RET set_func(func) LPAREN decl_var(var) RPAREN EOS. {
+       ret = init_ret_stmt(func, var);
+}
+
+%type impl_type {impl_type*}
+impl_type(type_) ::= VOID(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= MIXED(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= BOOL(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= INT(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= FLOAT(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= STRING(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+impl_type(type_) ::= ARRAY(T). {
+       type_ = init_impl_type(T->type, T->text);
+       free(T);
+}
+
+%type pointers {unsigned}
+pointers(p) ::= POINTER. {++p;}
+pointers(p) ::= pointers(P) POINTER. {p = ++P;}
diff --git a/src/validator.c b/src/validator.c
new file mode 100644 (file)
index 0000000..191124a
--- /dev/null
@@ -0,0 +1,310 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+
+#include <jit/jit.h>
+
+#include "validator.h"
+
+PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
+{
+       if (!V) {
+               V = malloc(sizeof(*V));
+       }
+       memset(V, 0, sizeof(*V));
+
+       PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
+
+       return V;
+}
+
+void PSI_ValidatorDtor(PSI_Validator *V)
+{
+       PSI_DataDtor((PSI_Data *) V);
+       memset(V, 0, sizeof(*V));
+}
+
+void PSI_ValidatorFree(PSI_Validator **V)
+{
+       if (*V) {
+               PSI_ValidatorDtor(*V);
+               free(*V);
+               *V = NULL;
+       }
+}
+
+static 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))) {
+               fprintf(stderr, "Could not open library '%s': %s.\n", V->lib, dlerror());
+               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 decl *locate_impl_decl(decls *decls, ret_stmt *ret) {
+       size_t i;
+
+       for (i = 0; i < decls->count; ++i) {
+               if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
+                       return decls->list[i];
+               }
+       }
+       return NULL;
+}
+static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
+       /* okay,
+        * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
+        * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
+        * - we can have any count of set stmts; processing out vars, etc.
+        */
+       size_t i, j;
+       ret_stmt *ret;
+       decl *decl;
+       int *check;
+
+        if (!stmts) {
+               fprintf(stderr, "Missing body for implementation %s!\n", impl->func->name);
+               return 0;
+       }
+       if (stmts->ret.count != 1) {
+               if (stmts->ret.count > 1) {
+                       fprintf(stderr, "Too many `ret` statements for implmentation %s; found %zu, exactly one is needed.\n",
+                               impl->func->name, stmts->ret.count);
+               } else {
+                       fprintf(stderr, "Missing `ret` statement for implementation %s.\n", impl->func->name);
+               }
+               return 0;
+       }
+
+       ret = stmts->ret.list[0];
+       decl = locate_impl_decl(V->decls, ret);
+       if (!decl) {
+               fprintf(stderr, "Missing declaration for implementation %s.\n", impl->func->name);
+               return 0;
+       }
+
+       /* check that we have a let stmt for every decl arg */
+       check = calloc(decl->args->count, sizeof(int));
+       for (i = 0; i < stmts->let.count; ++i) {
+               let_stmt *let = stmts->let.list[i];
+
+               for (j = 0; j < decl->args->count; ++j) {
+                       if (!strcmp(decl->args->args[j]->var->name, let->var->name)) {
+                               check[j] = 1;
+                               break;
+                       }
+               }
+       }
+       for (i = 0; i < decl->args->count; ++i) {
+               if (!check[i]) {
+                       fprintf(stderr, "Missing `let` statement for arg '%s %.*s%s' of declaration '%s' for implementation '%s'.\n",
+                               decl->args->args[i]->type->name, (int) decl->args->args[i]->var->pointer_level, "*****", decl->args->args[i]->var->name, decl->func->var->name, impl->func->name);
+                       free(check);
+                       return 0;
+               }
+       }
+       free(check);
+
+       impl->decl = decl;
+
+       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 (!validate_lib(V)) {
+               return 0;
+       }
+       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/src/validator.h b/src/validator.h
new file mode 100644 (file)
index 0000000..f96111c
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _PSI_VALIDATOR_H
+#define _PSI_VALIDATOR_H
+
+#include "parser.h"
+
+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_Parser *P);
+int PSI_ValidatorValidate(PSI_Validator *V);
+void PSI_ValidatorFree(PSI_Validator **V);
+void PSI_ValidatorDtor(PSI_Validator *V);
+
+#endif