*.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
--- /dev/null
+Michael Wallner <mike@php.net>
--- /dev/null
+Yay, no known and unresolved issues yet!
--- /dev/null
+# 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/.
--- /dev/null
+psi
+Michael Wallner
--- /dev/null
+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.
--- /dev/null
+# 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 $@ $<
--- /dev/null
+# 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).
--- /dev/null
+Thanks go to the following people, who have contributed to this project:
* 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
--- /dev/null
+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
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
+++ /dev/null
-%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;}
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+
+Parse error: parse error in /Users/Mike/Sources/repo-template.git/presets/package.xml on line 2
+
--- /dev/null
+
+#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
+ */
--- /dev/null
+#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();
+}
--- /dev/null
+#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
--- /dev/null
+
+#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
+ */
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+%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;}
--- /dev/null
+#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;
+}
--- /dev/null
+#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