From 6788e3ef72994a7bb8eff421249485e0a81c20ca Mon Sep 17 00:00:00 2001 From: nishi Date: Wed, 24 Apr 2024 03:00:55 +0000 Subject: [PATCH] mm git-svn-id: file:///raid/svn-main/nishi-serenade/trunk@29 0f02c867-ac3d-714e-8a88-971ba1f6efcf --- Makefile | 5 ++- Serenade/Makefile | 2 +- Serenade/ffi_binding.c | 90 ++++++++++++++++++++++++++++++++++++++++++ Serenade/ffi_binding.h | 38 ++++++++++++++++++ Serenade/interpreter.c | 13 +++--- Serenade/util.c | 21 +++++++--- Serenade/util.h | 3 ++ Tool/configgen.c | 20 ++++++++-- cmdline | 17 ++++++++ 9 files changed, 189 insertions(+), 20 deletions(-) create mode 100644 Serenade/ffi_binding.c create mode 100644 Serenade/ffi_binding.h create mode 100644 cmdline diff --git a/Makefile b/Makefile index 84f60dd..46f1eec 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ CC = cc CFLAGS = -std=c99 -g LDFLAGS = -LIBS = +LIBS = `cpp -DLIBS cmdline | grep -vE "^\#" | tr '\\n' ' '` +EXTRA_OBJS = `cpp -DOBJS cmdline | grep -vE "^\#" | tr '\\n' ' '` SUFFIX = .if "$(PLATFORM)" != "" @@ -24,7 +25,7 @@ all: ./Tool ./config.h ./Serenade ./Tool/configgen $@ ./Serenade:: - $(MAKE) -C ./Serenade CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBS="$(LIBS)" SUFFIX="$(SUFFIX)" + $(MAKE) -C ./Serenade CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBS="$(LIBS)" SUFFIX="$(SUFFIX)" EXTRA_OBJS="$(EXTRA_OBJS)" clean: $(MAKE) -C ./Tool clean diff --git a/Serenade/Makefile b/Serenade/Makefile index 8d44bbb..fa66520 100644 --- a/Serenade/Makefile +++ b/Serenade/Makefile @@ -1,6 +1,6 @@ # $Id$ -SERENADE_OBJS = main.o parser.o util.o run.o interpreter.o +SERENADE_OBJS = main.o parser.o util.o run.o interpreter.o $(EXTRA_OBJS) .PHONY: all clean .SUFFIXES: .o .c diff --git a/Serenade/ffi_binding.c b/Serenade/ffi_binding.c new file mode 100644 index 0000000..f6621b8 --- /dev/null +++ b/Serenade/ffi_binding.c @@ -0,0 +1,90 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* -------------------------------------------------------------------------- */ +/* Serenade is a Lisp Dialect */ +/* -------------------------------------------------------------------------- */ +/* Copyright (c) 2024 Nishi. */ +/* Redistribution and use in source and binary forms, with or without modific */ +/* ation, are permitted provided that the following conditions are met: */ +/* 1. Redistributions of source code must retain the above copyright noti */ +/* ce, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright n */ +/* otice, this list of conditions and the following disclaimer in the documen */ +/* tation and/or other materials provided with the distribution. */ +/* 3. Neither the name of the copyright holder nor the names of its contr */ +/* ibutors may be used to endorse or promote products derived from this softw */ +/* are without specific prior written permission. */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS */ +/* " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, TH */ +/* E IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPO */ +/* SE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CON */ +/* SEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU */ +/* TE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPT */ +/* ION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, S */ +/* TRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AN */ +/* Y WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY */ +/* OF SUCH DAMAGE. */ +/* -------------------------------------------------------------------------- */ +/* --- END LICENSE --- */ + +#include "ffi_binding.h" + +#include "parser.h" + +#include +#include + +#ifdef __MINGW32__ +#else +#include +#endif + +#include + +ffi_cif cif; + +struct sn_generic* ffi_symbol_handler(struct sn_interpreter* sn, int args, struct sn_generic** gens) { + struct sn_generic* gen = malloc(sizeof(struct sn_generic)); + gen->type = SN_TYPE_VOID; + void* ptr = NULL; + if(args == 3 && gens[1]->type == SN_TYPE_PTR && gens[2]->type == SN_TYPE_STRING) { + char* sym = malloc(gens[2]->string_length + 1); + memcpy(sym, gens[2]->string, gens[2]->string_length); + sym[gens[2]->string_length] = 0; + ptr = dlsym(gens[1]->ptr, sym); + free(sym); + } + if(ptr != NULL) { + gen->type = SN_TYPE_PTR; + gen->ptr = ptr; + } + return gen; +} + +struct sn_generic* ffi_load_handler(struct sn_interpreter* sn, int args, struct sn_generic** gens) { + struct sn_generic* gen = malloc(sizeof(struct sn_generic)); + gen->type = SN_TYPE_VOID; + void* lib = NULL; + if(args == 2 && gens[1]->type == SN_TYPE_STRING) { + char* path = malloc(gens[1]->string_length + 1); + memcpy(path, gens[1]->string, gens[1]->string_length); + path[gens[1]->string_length] = 0; + lib = dlopen(path, RTLD_LAZY); + free(path); + } + if(lib != NULL) { + gen->type = SN_TYPE_PTR; + gen->ptr = lib; + } + return gen; +} + +void ffi_init(struct sn_interpreter* sn) { + struct sn_generic* gen = malloc(sizeof(struct sn_generic)); + gen->type = SN_TYPE_DOUBLE; + gen->number = 1; + sn_set_variable(sn, "ffi-loaded", gen); + sn_set_handler(sn, "ffi-symbol", ffi_symbol_handler); + sn_set_handler(sn, "ffi-load", ffi_load_handler); +} diff --git a/Serenade/ffi_binding.h b/Serenade/ffi_binding.h new file mode 100644 index 0000000..3c47c67 --- /dev/null +++ b/Serenade/ffi_binding.h @@ -0,0 +1,38 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* -------------------------------------------------------------------------- */ +/* Serenade is a Lisp Dialect */ +/* -------------------------------------------------------------------------- */ +/* Copyright (c) 2024 Nishi. */ +/* Redistribution and use in source and binary forms, with or without modific */ +/* ation, are permitted provided that the following conditions are met: */ +/* 1. Redistributions of source code must retain the above copyright noti */ +/* ce, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright n */ +/* otice, this list of conditions and the following disclaimer in the documen */ +/* tation and/or other materials provided with the distribution. */ +/* 3. Neither the name of the copyright holder nor the names of its contr */ +/* ibutors may be used to endorse or promote products derived from this softw */ +/* are without specific prior written permission. */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS */ +/* " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, TH */ +/* E IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPO */ +/* SE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CON */ +/* SEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU */ +/* TE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPT */ +/* ION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, S */ +/* TRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AN */ +/* Y WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY */ +/* OF SUCH DAMAGE. */ +/* -------------------------------------------------------------------------- */ +/* --- END LICENSE --- */ + +#ifndef __SERENADE_FFI_BINDING_H__ +#define __SERENADE_FFI_BINDING_H__ + +#include "interpreter.h" + +void ffi_init(struct sn_interpreter* sn); + +#endif diff --git a/Serenade/interpreter.c b/Serenade/interpreter.c index 1d5879f..e3e56dc 100644 --- a/Serenade/interpreter.c +++ b/Serenade/interpreter.c @@ -30,6 +30,7 @@ #include "interpreter.h" +#include "../config.h" #include "run.h" #include "util.h" @@ -74,14 +75,7 @@ struct sn_generic* print_handler(struct sn_interpreter* sn, int args, struct sn_ for(i = 1; i < args; i++) { if(i > 1) printf(" "); fflush(stdout); - if(gens[i]->type == SN_TYPE_DOUBLE) { - printf("%f", gens[i]->number); - } else if(gens[i]->type == SN_TYPE_STRING) { - fwrite(gens[i]->string, 1, gens[i]->string_length, stdout); - } else if(gens[i]->type == SN_TYPE_VOID) { - printf(""); - } else if(gens[i]->type == SN_TYPE_FUNCTION) { - } + sn_print_to(stdout, gens[i]); fflush(stdout); } printf("\n"); @@ -138,6 +132,9 @@ struct sn_interpreter* sn_create_interpreter(void) { sn_set_handler(sn, "print", print_handler); sn_set_handler(sn, "eval", eval_handler); sn_set_handler(sn, "define-var", defvar_handler); +#ifdef HAS_FFI_SUPPORT + ffi_init(sn); +#endif return sn; } diff --git a/Serenade/util.c b/Serenade/util.c index a544c7b..b5afb21 100644 --- a/Serenade/util.c +++ b/Serenade/util.c @@ -49,6 +49,20 @@ char* sn_strdup(const char* str1) { return str; } +void sn_print_to(FILE* f, struct sn_generic* gen) { + if(gen->type == SN_TYPE_DOUBLE) { + fprintf(f, "%f", gen->number); + } else if(gen->type == SN_TYPE_STRING) { + fwrite(gen->string, 1, gen->string_length, f); + } else if(gen->type == SN_TYPE_VOID) { + fprintf(f, ""); + } else if(gen->type == SN_TYPE_FUNCTION) { + fprintf(f, "", gen->name); + } else if(gen->type == SN_TYPE_PTR) { + fprintf(f, "", gen->ptr); + } +} + void _sn_print_generic(struct sn_generic* gen, int n) { int i; fprintf(stderr, "[%2d]", gen->type); @@ -60,11 +74,8 @@ void _sn_print_generic(struct sn_generic* gen, int n) { _sn_print_generic(gen->tree->args[i], n + 1); } } - } else if(gen->type == SN_TYPE_DOUBLE) { - fprintf(stderr, "%f", gen->number); - fprintf(stderr, "\n"); - } else if(gen->type == SN_TYPE_STRING || gen->type == SN_TYPE_FUNCTION) { - fwrite(gen->string, 1, gen->string_length, stderr); + } else { + sn_print_to(stderr, gen); fprintf(stderr, "\n"); } } diff --git a/Serenade/util.h b/Serenade/util.h index d220850..0247ed8 100644 --- a/Serenade/util.h +++ b/Serenade/util.h @@ -33,8 +33,11 @@ #include "parser.h" +#include + char* sn_strcat(const char* str1, const char* str2); char* sn_strdup(const char* str1); +void sn_print_to(FILE* f, struct sn_generic* gen); void sn_print_generic(struct sn_generic* gen); #endif diff --git a/Tool/configgen.c b/Tool/configgen.c index 0df50ca..dcfd96f 100644 --- a/Tool/configgen.c +++ b/Tool/configgen.c @@ -30,8 +30,8 @@ #include #include -#include #include +#include char choice[256]; @@ -46,6 +46,14 @@ void show_dialog(int n) { fflush(stderr); } +void macro_print(FILE* out) { + fprintf(out, "#ifndef COMMANDLINE\n"); + fprintf(out, "#ifdef HAS_FFI_SUPPORT\n"); + fprintf(out, "#include \"Serenade/ffi_binding.h\"\n"); + fprintf(out, "#endif\n"); + fprintf(out, "#endif\n"); +} + int main(int argc, char** argv) { FILE* out = stdout; bool load = false; @@ -61,14 +69,14 @@ int main(int argc, char** argv) { fprintf(stderr, "%s: %s: couldn't open the file\n", argv[0], argv[1]); return 1; } - if(argv[2] != NULL && strcmp(argv[2], "default") == 0){ + if(argv[2] != NULL && strcmp(argv[2], "default") == 0) { def = true; } } fprintf(out, "/* Autogenerated config */\n"); - if(def){ + if(def) { int n; - for(n = 0; asks[n * 4] != NULL; n++){ + for(n = 0; asks[n * 4] != NULL; n++) { fprintf(out, "#%s %s\n", asks[n * 4 + 1][0] == 'y' ? "define" : "undef", asks[n * 4 + 2]); } fprintf(out, "#define PARSER_STACK_SIZE %d\n", stack_size); @@ -78,6 +86,8 @@ int main(int argc, char** argv) { fprintf(out, "%c%s", asks[n * 4 + 1][0] == 'y' ? '+' : '-', asks[n * 4]); } fprintf(out, "\"\n"); + fprintf(out, "\n"); + macro_print(out); return 0; } char c; @@ -113,5 +123,7 @@ int main(int argc, char** argv) { fprintf(out, "%c%s", choice[n] == 'y' ? '+' : '-', asks[n * 4]); } fprintf(out, "\"\n"); + fprintf(out, "\n"); + macro_print(out); if(load) fclose(out); } diff --git a/cmdline b/cmdline new file mode 100644 index 0000000..ad74781 --- /dev/null +++ b/cmdline @@ -0,0 +1,17 @@ +#define COMMANDLINE +#include "config.h" + +#ifdef LIBS +#ifdef HAS_FFI_SUPPORT +-lffi +#ifdef __linux__ +-ldl +#endif +#endif +#endif + +#ifdef OBJS +#ifdef HAS_FFI_SUPPORT +ffi_binding.o +#endif +#endif -- 2.43.0