blob: 85af2f2aa32660add1900a0d3a13db83fb4b9080 [file] [log] [blame]
//===------- NativeUtil.cpp - Methods to call native functions --------------===//
//
// N3
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <dlfcn.h>
#include <string.h>
#include "llvm/DerivedTypes.h"
#include "NativeUtil.h"
#include "N3.h"
#include "VMArray.h"
#include "VMClass.h"
#include "VMThread.h"
using namespace n3;
static void cliToInternal(char* buf) {
uint32 i = 0;
while (buf[i] != 0) {
if (buf[i] == '.') buf[i] = '_';
++i;
}
}
static void* makeFull(VMCommonClass* cl, VMMethod* meth) {
char* buf = (char*)alloca(4096);
sprintf(buf,
"%s_%s_%s",
mvm::PrintBuffer(cl->nameSpace).cString(),
mvm::PrintBuffer(cl->name).cString(),
mvm::PrintBuffer(meth->name).cString());
std::vector<VMCommonClass*>::iterator i = meth->parameters.begin(),
e = meth->parameters.end();
// Remove return type;
++i;
for ( ; i!= e; ++i) {
VMCommonClass* cl = *i;
sprintf(buf, "%s_%s_%s", buf, mvm::PrintBuffer(cl->nameSpace).cString(), mvm::PrintBuffer(cl->name).cString());
}
cliToInternal(buf);
void* res = dlsym(0, buf);
if (!res) {
VMThread::get()->getVM()->error("unable to find native method %s",
mvm::PrintBuffer(meth).cString());
}
return res;
}
void* NativeUtil::nativeLookup(VMCommonClass* cl, VMMethod* meth) {
mvm::PrintBuffer _name(cl->name);
mvm::PrintBuffer _nameSpace(cl->nameSpace);
mvm::PrintBuffer _methName(meth->name);
char* name = _name.cString();
char* nameSpace = _nameSpace.cString();
char* methName = _methName.cString();
char* buf = (char*)alloca(6 + strlen(name) + strlen(nameSpace) +
strlen(methName));
sprintf(buf, "%s_%s_%s", nameSpace, name, methName);
cliToInternal(buf);
void* res = dlsym(0, buf);
if (!res) {
buf = (char*)alloca(6 + strlen(name) + strlen(nameSpace) +
strlen(methName) + 10);
sprintf(buf, "%s_%s_%s_%d", nameSpace, name, methName,
meth->getSignature(NULL)->getNumParams());
cliToInternal(buf);
res = dlsym(0, buf);
if (!res) {
return makeFull(cl, meth);
}
}
return res;
}