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:
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);