diff -u IoDesktop-2005-08-30/IoVM/IoDynLib.c Io/IoVM/IoDynLib.c --- IoDesktop-2005-08-30/IoVM/IoDynLib.c 2005-08-30 23:19:55.000000000 +1000 +++ Io/IoVM/IoDynLib.c 2005-09-11 22:56:45.853086088 +1000 @@ -12,6 +12,9 @@ #include "IoNil.h" #include "IoState.h" #include "IoSeq.h" +#include "IoBlock.h" +#include "IoNumber.h" +#include "IoList.h" #include "IoMessage.h" #include "IoDynLib.h" #include "base/DynLib.h" @@ -40,6 +43,8 @@ {"open", IoDynLib_open}, {"close", IoDynLib_close}, {"isOpen", IoDynLib_isOpen}, + {"call", IoDynLib_call}, + {"returnsString", IoDynLib_returnsString}, {NULL, NULL}, }; @@ -190,3 +195,209 @@ return DynLib_isOpen(DATA(self)) ? self : IONIL(self); } + +int bouncer(IoBlock *self, int ret, int a, int b, int c, int d, int e) +{ + IoNumber *n; + static IoMessage *m = NULL; + IoObject *target = NULL; + List *argNames; + + if (!ISBLOCK(self)) { + target = IoObject_rawGetSlot_(self, IOSYMBOL("target")); + IoSeq *handler = IoObject_rawGetSlot_(self, IOSYMBOL("handler")); + if (ISSYMBOL(handler)) { + self = IoObject_rawGetSlot_(target, handler); + } else { + IoState_error_description_(IOSTATE, m, + "DynLoad.bouncer", "Error, handler isn't a symbol."); + } + } + if (target == NULL) + target = IoState_lobby(IOSTATE); + + if (self == NULL) + return 0; + + argNames = ((IoBlockData*)self->data)->argNames; + + if (m == NULL) + m = IoMessage_new(IOSTATE); + if (0 < argNames->size) + IoMessage_setCachedArg_toInt_(m, 0, a); + if (1 < argNames->size) + IoMessage_setCachedArg_toInt_(m, 1, b); + if (2 < argNames->size) + IoMessage_setCachedArg_toInt_(m, 2, c); + if (3 < argNames->size) + IoMessage_setCachedArg_toInt_(m, 3, d); + if (4 < argNames->size) + IoMessage_setCachedArg_toInt_(m, 4, e); + + n = IoBlock_activate(self, target, target, m, target); + + IoState_clearTopPool(IOSTATE); + + if (ISNUMBER(n)) + return IoNumber_asInt(n); + return 0; +} + +unsigned int marshal(IoDynLib *self, IoObject *arg) +{ + unsigned int n = 0; + + if (ISNUMBER(arg)) + n = IoNumber_asInt(arg); + else if (ISSYMBOL(arg)) + n = (unsigned int)CSTRING(arg); + else if (ISLIST(arg)) { + int i; + unsigned int *l = malloc(IoList_rawSize(arg) * sizeof(unsigned int)); + for (i = 0; i < IoList_rawSize(arg); i++) + l[i] = marshal(self, List_at_(IoList_rawList(arg), i)); + n = (unsigned int)l; + } else if (ISBUFFER(arg)) { + n = (unsigned int)IoSeq_rawBytes(arg); + } else if (ISBLOCK(arg) || ( + IoObject_rawGetSlot_(arg, IOSYMBOL("target")) && + IoObject_rawGetSlot_(arg, IOSYMBOL("handler")))) { + unsigned char *blk = malloc(20), *p = blk; + // FIXME: need trampoline code for other architectures + *p++ = 0x68; + *((int *)p) = (int)arg; + p += sizeof(int); + *p++ = 0xb8; + *((int *)p) = (int)bouncer; + p += sizeof(int); + *p++ = 0xff; + *p++ = 0xd0; + *p++ = 0x83; + *p++ = 0xc4; + *p++ = 0x04; + *p++ = 0xc3; + n = (unsigned int)blk; + } else { + return (unsigned int)IONIL(self); + } + + return n; +} + +IoObject *demarshal(IoObject *self, IoObject *arg, unsigned int n) +{ + if (ISNUMBER(arg)) { + return IONUMBER(n); + } else if (ISSYMBOL(arg)) { + if (n == 0) + return IOSYMBOL(""); + return IOSYMBOL((char*)n); + } else if (ISLIST(arg)) { + unsigned int *values = (unsigned int *)n; + int i; + for (i = 0; i < IoList_rawSize(arg); i++) { + IoObject *value = List_at_(IoList_rawList(arg), i); + List_at_put_(IoList_rawList(arg), i, demarshal(self, value, values[i])); + } + free(values); + return arg; + } else if (ISBUFFER(arg)) { + return arg; + } else if (ISBLOCK(arg)) { + return arg; + } + return IONIL(self); +} + +IoDynLib *IoDynLib_call(IoDynLib *self, IoObject *locals, IoMessage *m) +{ + int n, rc; + unsigned int *params = NULL; + void *f = DynLib_pointerForSymbolName_(DATA(self), + CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0))); + if (f == NULL) { + IoState_error_description_(IOSTATE, m, + "DynLoad.call", "Error resolving call '%s'.", + CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0))); + return IONIL(self); + } + + if (IoMessage_argCount(m) > 9) { + IoState_error_description_(IOSTATE, m, + "DynLoad.call", "Error, too many arguments (%i) to call '%s'.", + IoMessage_argCount(m) - 1, + CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0))); + return IONIL(self); + } + + if (IoMessage_argCount(m) > 1) + params = malloc(IoMessage_argCount(m) * sizeof(unsigned int)); + + for (n = 0; n < IoMessage_argCount(m) - 1; n++) { + IoObject *arg = IoMessage_locals_valueArgAt_(m, locals, n + 1); + params[n] = marshal(self, arg); + if ((IoObject*)params[n] == IONIL(self)) { + IoState_error_description_(IOSTATE, m, + "DynLoad.call", "Error marshalling argument (%i) to call '%s'.", + n + 1, + CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0))); + // FIXME this can leak memory. + free(params); + return IONIL(self); + } + } + +#if 0 + printf("calling %s with %i arguments\n", + CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0)), + IoMessage_argCount(m) - 1); +#endif + + switch(IoMessage_argCount(m) - 1) { + case 0: + rc = ((int (*)())f)(); + break; + case 1: + rc = ((int (*)(int))f)(params[0]); + break; + case 2: + rc = ((int (*)(int,int))f)(params[0], params[1]); + break; + case 3: + rc = ((int (*)(int,int,int))f)(params[0], params[1], params[2]); + break; + case 4: + rc = ((int (*)(int,int,int,int))f)(params[0], params[1], params[2], params[3]); + break; + case 5: + rc = ((int (*)(int,int,int,int,int))f)(params[0], params[1], params[2], params[3], params[4]); + break; + case 6: + rc = ((int (*)(int,int,int,int,int,int))f)(params[0], params[1], params[2], params[3], params[4], params[5]); + break; + case 7: + rc = ((int (*)(int,int,int,int,int,int,int))f)(params[0], params[1], params[2], params[3], params[4], params[5], params[6]); + break; + case 8: + rc = ((int (*)(int,int,int,int,int,int,int,int))f)(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]); + break; + } + + for (n = 0; n < IoMessage_argCount(m) - 1; n++) { + IoObject *arg = IoMessage_locals_valueArgAt_(m, locals, n + 1); + demarshal(self, arg, params[n]); + } + + free(params); + + return IONUMBER(rc); +} + +IoSeq *IoDynLib_returnsString(IoDynLib *self, IoObject *locals, IoMessage *m) +{ + int n = IoNumber_asInt(IoMessage_locals_numberArgAt_(m, locals, 0)); + if (n == 0) + return IOSYMBOL(""); + return IOSYMBOL((char*)n); +} + diff -u IoDesktop-2005-08-30/IoVM/IoDynLib.h Io/IoVM/IoDynLib.h --- IoDesktop-2005-08-30/IoVM/IoDynLib.h 2005-08-30 23:19:55.000000000 +1000 +++ Io/IoVM/IoDynLib.h 2005-09-09 13:03:24.000000000 +1000 @@ -45,6 +45,9 @@ IoObject *IoDynLib_close(IoDynLib *self, IoObject *locals, IoMessage *m); IoObject *IoDynLib_isOpen(IoDynLib *self, IoObject *locals, IoMessage *m); +IoObject *IoDynLib_call(IoDynLib *self, IoObject *locals, IoMessage *m); +IoSeq *IoDynLib_returnsString(IoDynLib *self, IoObject *locals, IoMessage *m); + #ifdef __cplusplus } #endif diff -u IoDesktop-2005-08-30/IoVM/IoState.c Io/IoVM/IoState.c --- IoDesktop-2005-08-30/IoVM/IoState.c 2005-08-30 23:19:55.000000000 +1000 +++ Io/IoVM/IoState.c 2005-09-06 13:36:50.000000000 +1000 @@ -227,9 +227,7 @@ sandbox = IoSandbox_proto(self); IoObject_setSlot_to_(vm, SIOSYMBOL("Sandbox"), sandbox); #if !defined(__SYMBIAN32__) - /* IoObject_setSlot_to_(vm, SIOSYMBOL("DynLib"), IoDynLib_proto(self)); - */ #endif self->store = IoStore_proto(self); diff -u IoDesktop-2005-08-30/IoVM/Makefile Io/IoVM/Makefile --- IoDesktop-2005-08-30/IoVM/Makefile 2005-08-30 23:19:55.000000000 +1000 +++ Io/IoVM/Makefile 2005-09-06 13:38:22.000000000 +1000 @@ -81,9 +81,9 @@ LIB := _libs/libIoVM.a OBJDIR := _objs - #IoDynLib.c \ sources := IoBlock.c \ + IoDynLib.c \ IoSeq.c \ IoSeq_immutable.c \ IoSeq_mutable.c \