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)" != ""
./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
# $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
--- /dev/null
+/* $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 <stdlib.h>
+#include <string.h>
+
+#ifdef __MINGW32__
+#else
+#include <dlfcn.h>
+#endif
+
+#include <ffi.h>
+
+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);
+}
--- /dev/null
+/* $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
#include "interpreter.h"
+#include "../config.h"
#include "run.h"
#include "util.h"
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("<void>");
- } else if(gens[i]->type == SN_TYPE_FUNCTION) {
- }
+ sn_print_to(stdout, gens[i]);
fflush(stdout);
}
printf("\n");
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;
}
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, "<void>");
+ } else if(gen->type == SN_TYPE_FUNCTION) {
+ fprintf(f, "<function %s>", gen->name);
+ } else if(gen->type == SN_TYPE_PTR) {
+ fprintf(f, "<pointer %x>", gen->ptr);
+ }
+}
+
void _sn_print_generic(struct sn_generic* gen, int n) {
int i;
fprintf(stderr, "[%2d]", gen->type);
_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");
}
}
#include "parser.h"
+#include <stdio.h>
+
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
#include <ctype.h>
#include <stdbool.h>
-#include <string.h>
#include <stdio.h>
+#include <string.h>
char choice[256];
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;
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);
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;
fprintf(out, "%c%s", choice[n] == 'y' ? '+' : '-', asks[n * 4]);
}
fprintf(out, "\"\n");
+ fprintf(out, "\n");
+ macro_print(out);
if(load) fclose(out);
}
--- /dev/null
+#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