Permalink
Browse files

Adding external code loader: part 1. (and did some misc. stuff)

  • Loading branch information...
1 parent 9ba1fab commit 9b12ef0a979bc4dba1d2dd5536cd956f1e1fe8fe @orangea orangea committed Dec 20, 2010
Showing with 117 additions and 4 deletions.
  1. +1 −1 Makefile
  2. +7 −1 core/file.c
  3. +1 −0 core/internal.c
  4. +106 −0 core/load.c
  5. +0 −2 core/number.c
  6. +2 −0 core/potion.h
View
2 Makefile
@@ -1,6 +1,6 @@
.SUFFIXES: .g .c .o
-SRC = core/asm.c core/ast.c core/callcc.c core/compile.c core/contrib.c core/file.c core/gc.c core/internal.c core/lick.c core/mt19937ar.c core/number.c core/objmodel.c core/primitive.c core/string.c core/syntax.c core/table.c core/vm.c core/vm-ppc.c core/vm-x86.c
+SRC = core/asm.c core/ast.c core/callcc.c core/compile.c core/contrib.c core/file.c core/gc.c core/internal.c core/lick.c core/load.c core/mt19937ar.c core/number.c core/objmodel.c core/primitive.c core/string.c core/syntax.c core/table.c core/vm.c core/vm-ppc.c core/vm-x86.c
OBJ = ${SRC:.c=.o}
OBJ_POTION = core/potion.o
OBJ_TEST = test/api/potion-test.o test/api/CuTest.o
View
8 core/file.c
@@ -12,7 +12,13 @@
#include "internal.h"
#include "table.h"
-extern char **environ;
+#ifdef __APPLE__
+# include <crt_externs.h>
+# undef environ
+# define environ (*_NSGetEnviron())
+#else
+ extern char **environ;
+#endif
typedef vPN(File) pn_file;
View
1 core/internal.c
@@ -92,6 +92,7 @@ static void potion_init(Potion *P) {
potion_lick_init(P);
potion_compiler_init(P);
potion_file_init(P);
+ potion_loader_init(P);
GC_PROTECT(P);
}
View
106 core/load.c
@@ -0,0 +1,106 @@
+//
+// load.c
+// loading of external code
+//
+// (c) 2008 why the lucky stiff, the freelance professor
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+#include "potion.h"
+#include "internal.h"
+#include "table.h"
+
+void potion_load_code(Potion *P, const char *filename) {
+ PN buf, code;
+ int fd = -1;
+ struct stat stats;
+ if (stat(filename, &stats) == -1) {
+ fprintf(stderr, "** %s does not exist.", filename);
+ goto done;
+ }
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd == -1) {
+ fprintf(stderr, "** could not open %s. check permissions.", filename);
+ goto done;
+ }
+ buf = potion_bytes(P, stats.st_size);
+ if (read(fd, PN_STR_PTR(buf), stats.st_size) == stats.st_size) {
+ PN_STR_PTR(buf)[stats.st_size] = '\0';
+ code = potion_source_load(P, PN_NIL, buf);
+ if (!PN_IS_PROTO(code)) {
+ potion_run(P, potion_send(
+ potion_parse(P, buf), PN_compile, potion_str(P, filename), PN_NIL));
+ }
+ } else {
+ fprintf(stderr, "** could not read entire file: %s.", filename);
+ }
+
+done:
+ if (fd != -1)
+ close(fd);
+}
+
+static PN potion_initializer_name(Potion *P, const char *filename, PN_SIZE len) {
+ PN_SIZE ext_name_len = 0;
+ char *ext_name;
+ PN func_name = potion_byte_str(P, "Potion_Init_");
+ while (*(filename + ++ext_name_len) != '.' && ext_name_len <= len);
+ ext_name = malloc(ext_name_len + 1);
+ if (ext_name == NULL) {
+ // TODO: fatal error
+ fprintf(stderr, "** Couldn't allocate memory.\n");
+ exit(1);
+ }
+ strncpy(ext_name, filename, ext_name_len);
+ ext_name[ext_name_len] = '\0';
+ pn_printf(P, func_name, "%s", ext_name);
+ free(ext_name);
+ return func_name;
+}
+
+void potion_load_dylib(Potion *P, const char *filename) {
+ void *handle = dlopen(filename, RTLD_LAZY);
+ void (*func)(Potion *);
+ char *err;
+ if (handle == NULL) {
+ // TODO: error
+ fprintf(stderr, "** error loading %s: %s\n", filename, dlerror());
+ return;
+ }
+ func = dlsym(handle, PN_STR_PTR(
+ potion_initializer_name(P, filename, strlen(filename))));
+ err = dlerror();
+ if (err != NULL) {
+ fprintf(stderr, "** error loading %s: %s\n", filename, err);
+ return;
+ }
+ func(P);
+}
+
+PN potion_load(Potion *P, PN cl, PN self, PN file) {
+ char *filename = PN_STR_PTR(file),
+ *file_ext = filename + PN_STR_LEN(file);
+ while (*--file_ext != '.' && file_ext >= filename);
+ if (file_ext++ != filename) {
+ if (strcmp(file_ext, "pn") == 0)
+ potion_load_code(P, filename);
+ else if (strcmp(file_ext, "so") == 0 ||
+ strcmp(file_ext, "dylib") == 0
+ )
+ potion_load_dylib(P, filename);
+ else
+ ; // TODO: error
+ } else {
+ // ...
+ }
+
+ return PN_NIL;
+}
+
+void potion_loader_init(Potion *P) {
+ potion_method(P->lobby, "load", potion_load, "file=S");
+}
View
2 core/number.c
@@ -11,8 +11,6 @@
#include "potion.h"
#include "internal.h"
-#define PN_DBL(num) (PN_IS_NUM(num) ? (double)PN_INT(num) : ((struct PNDecimal *)num)->value)
-
PN potion_real(Potion *P, double v) {
vPN(Decimal) d = PN_ALLOC_N(PN_TNUMBER, struct PNDecimal, 0);
d->value = v;
View
2 core/potion.h
@@ -113,6 +113,7 @@ struct PNVtable;
#define PN_NUM(i) ((PN)((((long)(i))<<1) + PN_FNUMBER))
#define PN_INT(x) ((long)((long)(x))>>1)
+#define PN_DBL(num) (PN_IS_NUM(num) ? (double)PN_INT(num) : ((struct PNDecimal *)num)->value)
#define PN_PREC 16
#define PN_RAND() PN_NUM(potion_rand_int())
#define PN_STR_PTR(x) potion_str_ptr(x)
@@ -619,6 +620,7 @@ void potion_lick_init(Potion *);
void potion_compiler_init(Potion *);
void potion_vm_init(Potion *);
void potion_file_init(Potion *);
+void potion_loader_init(Potion *);
void potion_cont_init(Potion *);
void potion_dump_stack(Potion *);

0 comments on commit 9b12ef0

Please sign in to comment.