/* nl-import.c --- shared library interface for newLISP
Copyright (C) 2007 Lutz Mueller
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "newlisp.h"
#include "protos.h"
#ifdef WINCE
#define _stdcall __stdcall
#endif
#ifndef WIN_32
#ifdef MAC_102
#include "osx-dlfcn.h"
#else
#include
#endif
#endif
UINT cdeclFunction(UINT fAddress, UINT * args, int count);
extern int evalCatchFlag;
#ifdef WIN_32
UINT stdcallFunction(UINT fAddress, UINT * args, int count);
CELL * p_importLib(CELL * params)
{
char * libName;
char * funcName;
char * options = NULL;
HINSTANCE hLibrary;
CELL * pCell;
SYMBOL * symbol;
FARPROC initProc;
params = getString(params, &libName);
params = getString(params, &funcName);
if(params != nilCell)
getString(params, &options);
/* hLibrary = NULL; */
if( (UINT)(hLibrary = LoadLibrary(libName)) < 32)
return(errorProcExt2(ERR_IMPORT_LIB_NOT_FOUND, stuffString(libName)));
if(options != NULL && strcmp(options, "cdecl") == 0)
pCell = getCell(CELL_IMPORT_CDECL);
else
pCell = getCell(CELL_IMPORT_DLL);
symbol = translateCreateSymbol(funcName, pCell->type, currentContext, TRUE);
if(isProtected(symbol->flags))
return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
deleteList((CELL *)symbol->contents);
symbol->contents = (UINT)pCell;
pCell->contents = (UINT)GetProcAddress(hLibrary, (LPCSTR)funcName);
pCell->aux = (UINT)symbol->name;
/* put name of imported DLL into DLLs space for loadStartup() */
initProc = GetProcAddress(hLibrary, (LPCSTR)"dllName");
if(initProc != 0) (*initProc)(libName);
if(pCell->contents == 0)
return(errorProcExt2(ERR_IMPORT_FUNC_NOT_FOUND, stuffString(funcName)));
return(copyCell(pCell));
}
#else /* UNIX and compatible operating systems */
CELL * p_importLib(CELL * params)
{
char * libName;
char * funcName;
void * hLibrary;
CELL * pCell;
SYMBOL * symbol;
char * error;
params = getString(params, &libName);
getString(params, &funcName);
hLibrary = 0;
#ifdef TRU64
if((hLibrary = dlopen(libName, RTLD_LAZY)) == 0)
#else
if((hLibrary = dlopen(libName, RTLD_GLOBAL|RTLD_LAZY)) == 0)
#endif
return(errorProcExt2(ERR_IMPORT_LIB_NOT_FOUND, stuffString((char *)dlerror())));
pCell = getCell(CELL_IMPORT_CDECL);
symbol = translateCreateSymbol(funcName, CELL_IMPORT_CDECL, currentContext, TRUE);
if(isProtected(symbol->flags))
return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
deleteList((CELL *)symbol->contents);
symbol->contents = (UINT)pCell;
pCell->contents = (UINT)dlsym(hLibrary, funcName);
if((error = (char *)dlerror()) != NULL)
return(errorProcExt2(ERR_IMPORT_FUNC_NOT_FOUND, stuffString(error)));
pCell->aux = (UINT)symbol->name;
return(copyCell(pCell));
}
#endif
CELL * executeLibfunction(CELL * pCell, CELL * params)
{
CELL * arg;
UINT args[14];
int count;
count = 0;
while(params->type != CELL_NIL && count < 14)
{
arg = evaluateExpression(params);
switch(arg->type)
{
case CELL_LONG:
case CELL_STRING:
case CELL_PRIMITIVE:
args[count++] = arg->contents;
break;
#ifndef NEWLISP64
case CELL_INT64:
args[count++] = *(INT64 *)&arg->aux;
break;
#endif
case CELL_FLOAT:
#ifndef NEWLISP64
args[count++] = arg->aux;
#endif
args[count++] = arg->contents;
break;
default:
args[count++] = (UINT)arg;
break;
}
params = (CELL *)params->next;
}
#ifdef WIN_32
if(pCell->type == CELL_IMPORT_DLL)
return(stuffInteger(stdcallFunction(pCell->contents, args, count)));
else
#endif
return(stuffInteger(cdeclFunction(pCell->contents, args, count)));
}
UINT cdeclFunction(UINT fAddress, UINT * args, int count)
{
UINT (*function)();
function = (UINT (*)())fAddress;
switch(count)
{
case 0:
return (*function)();
case 1:
return (*function)(args[0]);
case 2:
return (*function)(args[0], args[1]);
case 3:
return (*function)(args[0], args[1], args[2]);
case 4:
return (*function)(args[0], args[1], args[2], args[3]);
case 5:
return (*function)(args[0], args[1], args[2], args[3],
args[4]);
case 6:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5]);
case 7:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6]);
case 8:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7]);
case 9:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7], args[8]);
case 10:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7], args[8], args[9]);
case 11:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10]);
case 12:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11]);
case 13:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11],
args[12]);
case 14:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11],
args[12], args[13]);
default:
break;
}
return(0);
}
#ifdef WIN_32
UINT stdcallFunction(UINT fAddress, UINT * args, int count)
{
UINT _stdcall (*function)();
function = (UINT _stdcall (*)())fAddress;
switch(count)
{
case 0:
return (*function)();
case 1:
return (*function)(args[0]);
case 2:
return (*function)(args[0], args[1]);
case 3:
return (*function)(args[0], args[1], args[2]);
case 4:
return (*function)(args[0], args[1], args[2], args[3]);
case 5:
return (*function)(args[0], args[1], args[2], args[3],
args[4]);
case 6:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5]);
case 7:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6]);
case 8:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7]);
case 9:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7], args[8]);
case 10:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7], args[8], args[9]);
case 11:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10]);
case 12:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11]);
case 13:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11],
args[12]);
case 14:
return (*function)(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11],
args[12], args[13]);
default:
break;
}
return(0);
}
#endif
/* used when passing 32bit floats to library routines */
CELL * p_flt(CELL * params)
{
double dfloatV;
float floatV;
unsigned int number;
getFloat(params, &dfloatV);
floatV = dfloatV;
memcpy(&number, &floatV, 4);
return(stuffInteger(number));
}
/* 8 callback functions for up to 4 parameters */
long template(long n, long p1, long p2, long p3, long p4);
long callback0(long p1, long p2, long p3, long p4) {return template(0, p1, p2, p3, p4);}
long callback1(long p1, long p2, long p3, long p4) {return template(1, p1, p2, p3, p4);}
long callback2(long p1, long p2, long p3, long p4) {return template(2, p1, p2, p3, p4);}
long callback3(long p1, long p2, long p3, long p4) {return template(3, p1, p2, p3, p4);}
long callback4(long p1, long p2, long p3, long p4) {return template(4, p1, p2, p3, p4);}
long callback5(long p1, long p2, long p3, long p4) {return template(5, p1, p2, p3, p4);}
long callback6(long p1, long p2, long p3, long p4) {return template(6, p1, p2, p3, p4);}
long callback7(long p1, long p2, long p3, long p4) {return template(7, p1, p2, p3, p4);}
typedef struct {
SYMBOL * sym;
UINT func;
} LIBCALLBACK;
LIBCALLBACK callback[] = {
{ NULL, (UINT)callback0 },
{ NULL, (UINT)callback1 },
{ NULL, (UINT)callback2 },
{ NULL, (UINT)callback3 },
{ NULL, (UINT)callback4 },
{ NULL, (UINT)callback5 },
{ NULL, (UINT)callback6 },
{ NULL, (UINT)callback7 },
};
long template(long n, long p1, long p2, long p3, long p4)
{
CELL * args;
long result;
jmp_buf errorJumpSave;
memcpy(errorJumpSave, errorJump, sizeof(errorJump));
if(setjmp(errorJump))
{
reset();
initStacks();
result = -1;
goto FINISH_CALLBACK;
}
args = stuffIntegerList(4, p1, p2, p3, p4);
result = executeSymbol(callback[n].sym, (CELL *)args->contents);
args->contents = (UINT)nilCell;
deleteList(args);
FINISH_CALLBACK:
memcpy(errorJump, errorJumpSave, sizeof(errorJump));
return(result);
}
CELL * p_callback(CELL * params)
{
SYMBOL * sPtr;
UINT n;
params = getInteger(params, &n);
if(n > 7) n = 7;
getSymbol(params, &sPtr);
callback[n].sym = sPtr;
return(stuffInteger(callback[n].func));
}
/* end of file */