tisp

tiny lisp
git clone git://edryd.org/tisp
Log | Files | Refs | LICENSE

commit 4c410c698790b6f5f8dfa94a88c663d285f46a06
parent 342c41a85d826c9516f775c249aa38dee351d695
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Sun, 12 Aug 2018 17:24:14 -0700

Add load primitive to dynamically include C libs

Diffstat:
Makefile | 12++++++++++--
config.def.h | 1+
config.mk | 6+++---
main.c | 6+++++-
t/math/add.tsp | 1+
t/math/compare.tsp | 1+
t/math/sub.tsp | 1+
t/prim/cond.tsp | 1+
t/prim/cons.tsp | 1+
t/prim/define.tsp | 1+
t/prim/eq.tsp | 1+
t/prim/lambda.tsp | 1+
t/prim/quote.tsp | 1+
t/simple/comments.tsp | 1+
t/t | 2++
tib/math.c | 1-
tisp.c | 39+++++++++++++++++++++++++++++++++++++++
tisp.h | 2++
18 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile @@ -6,6 +6,7 @@ include config.mk EXE = tisp SRC = $(wildcard *.c */*.c) OBJ = $(SRC:.c=.o) +LIB = tib/libtibmath.so all: options $(EXE) @@ -28,13 +29,17 @@ config.h: @echo creating $@ from config.def.h @cp config.def.h $@ -$(EXE): $(OBJ) +$(LIB): $(wildcard tib/*.c) + @echo $(CC) -o $@ + @gcc -shared -o $@ $(OBJ) + +$(EXE): $(OBJ) $(LIB) @echo $(CC) -o $@ @$(CC) -o $@ $(OBJ) $(LDFLAGS) clean: @echo cleaning - @rm -f $(OBJ) $(EXE) + @rm -f $(OBJ) $(LIB) $(EXE) install: all @echo installing $(EXE) to $(DESTDIR)$(PREFIX)/bin @@ -45,6 +50,9 @@ install: all @mkdir -p $(DESTDIR)$(MANPREFIX)/man1 @sed "s/VERSION/$(VERSION)/g" < $(EXE).1 > $(DESTDIR)$(MANPREFIX)/man1/$(EXE).1 @chmod 644 $(DESTDIR)$(MANPREFIX)/man1/$(EXE).1 + @echo installing libraries to $(DESTDIR)$(PREFIX)/lib/tisp + @mkdir -p $(DESTDIR)$(PREFIX)/lib/tisp + @cp -f $(LIB) $(DESTDIR)$(PREFIX)/lib/tisp uninstall: @echo removing $(EXE) from $(DESTDIR)$(PREFIX)/bin diff --git a/config.def.h b/config.def.h @@ -1 +1,2 @@ +#define TIB_STATIC 0 #define USE_LINENOISE 1 /* TODO implement */ diff --git a/config.mk b/config.mk @@ -7,12 +7,12 @@ MANPREFIX = $(PREFIX)/share/man # includes and libraries INCS = -Iinclude -LIBS = -lm +LIBS = -lm -ldl # flags CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=600 -CFLAGS = -g -std=c99 -pedantic -Wall $(INCS) $(CPPFLAGS) -LDFLAGS = -g $(LIBS) +CFLAGS = -g -std=c99 -pedantic -Wall -fPIC $(INCS) $(CPPFLAGS) +LDFLAGS = -g -Wl,-rpath=$(DESTDIR)$(PREFIX)/lib/tisp $(LIBS) # compiler and linker CC = cc diff --git a/main.c b/main.c @@ -10,7 +10,9 @@ #include "config.h" #include "tisp.h" -#include "tib/math.h" +#if TIB_STATIC +# include "tib/math.h" +#endif char *argv0; @@ -53,7 +55,9 @@ main(int argc, char *argv[]) FILE *fp; Val v; Env env = tisp_env_init(64); +#if TIB_STATIC tib_env_math(env); +#endif if (argc > 0) { if (!(fp = fopen(*argv, "r"))) diff --git a/t/math/add.tsp b/t/math/add.tsp @@ -1,3 +1,4 @@ +(load "math") (+ 1 1) (+ 1 2 3) (+ 1 2 (+ 1 2)) diff --git a/t/math/compare.tsp b/t/math/compare.tsp @@ -1,3 +1,4 @@ +(load "math") (< 2 3) (< 3 3) (< 4 3) diff --git a/t/math/sub.tsp b/t/math/sub.tsp @@ -1,3 +1,4 @@ +(load "math") (- 3) (- +3) (- -289) diff --git a/t/prim/cond.tsp b/t/prim/cond.tsp @@ -1,3 +1,4 @@ +(load "math") (cond) (cond (t 1)) (cond ((= 1 1) 1) ((= 1 2) 2) (t 3)) diff --git a/t/prim/cons.tsp b/t/prim/cons.tsp @@ -1,3 +1,4 @@ +(load "math") (cons 1 2) (cons 1 (cons 2 3)) (cons 1 (cons 2 (cons 3 4))) diff --git a/t/prim/define.tsp b/t/prim/define.tsp @@ -1,3 +1,4 @@ +(load "math") (define foo 4) foo (define bar foo) diff --git a/t/prim/eq.tsp b/t/prim/eq.tsp @@ -1,3 +1,4 @@ +(load "math") (=) (= 1) (= "foo") diff --git a/t/prim/lambda.tsp b/t/prim/lambda.tsp @@ -1,3 +1,4 @@ +(load "math") ((lambda (x) x) 3) ((lambda (x) x) (+ 1 2 3)) ((lambda (x) (+ x 1)) 8) diff --git a/t/prim/quote.tsp b/t/prim/quote.tsp @@ -1,3 +1,4 @@ +(load "math") (quote 1) (quote 9234) (quote "foo") diff --git a/t/simple/comments.tsp b/t/simple/comments.tsp @@ -1,3 +1,4 @@ +(load "math") ; commment ; (+ 1 1) (+ 1 1 ; more comments diff --git a/t/t b/t/t @@ -3,6 +3,8 @@ total=0 pass=0 +export LD_LIBRARY_PATH="$PWD/../tib:$LD_LIBRARY_PATH" + for file in */*.tsp; do expect=${file%.tsp}.expect diff --git a/tib/math.c b/tib/math.c @@ -2,7 +2,6 @@ #include <stdio.h> #include "../tisp.h" -#include "math.h" #define INC(SIGN, FUNC) do { \ if (car(v)->t == INTEGER) \ diff --git a/tisp.c b/tisp.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #include <ctype.h> +#include <dlfcn.h> #include <limits.h> #include <stdint.h> #include <stdio.h> @@ -553,6 +554,41 @@ prim_define(Env env, Val args) return NULL; } +static Val +prim_load(Env env, Val args) +{ + Val v; + void (*tibenv)(Env); + char *lib, *func; + if (list_len(args) != 1) + warn("load: incorrect format"); + if (!(v = tisp_eval(env, car(args)))) + return NULL; + + env->libh = erealloc(env->libh, (env->libhc+1)*sizeof(void*)); + + lib = ecalloc(strlen(v->v.s)+10, sizeof(char)); + strcat(lib, "libtib"); + strcat(lib, v->v.s); + strcat(lib, ".so"); + if (!(env->libh[env->libhc] = dlopen(lib, RTLD_LAZY))) + warnf("load: could not load [%s]: %s", v->v.s, dlerror()); + dlerror(); + efree(lib); + + func = ecalloc(strlen(v->v.s)+9, sizeof(char)); + strcat(func, "tib_env_"); + strcat(func, v->v.s); + tibenv = dlsym(env->libh[env->libhc], func); + if (dlerror()) + warnf("load: could not run [%s]: %s", v->v.s, dlerror()); + (*tibenv)(env); + efree(func); + + env->libhc++; + return NULL; +} + Env tisp_env_init(size_t cap) { @@ -573,7 +609,10 @@ tisp_env_init(size_t cap) hash_add(e->h, "cond", mk_prim(prim_cond)); hash_add(e->h, "lambda", mk_prim(prim_lambda)); hash_add(e->h, "define", mk_prim(prim_define)); + hash_add(e->h, "load", mk_prim(prim_load)); + e->libh = NULL; + e->libhc = 0; return e; } diff --git a/tisp.h b/tisp.h @@ -86,6 +86,8 @@ struct Val { struct Env { Val nil, t; Hash h; + void **libh; + size_t libhc; }; void skip_spaces(Str str);