/*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1997-2001 The R Development Core Team
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Dynamic Loading Support: See ../main/Rdynload.c and ../include/Rdynpriv.h
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <Defn.h>
#include <Rmath.h>
#include <direct.h>
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <R_ext/Rdynload.h>
#include <Rdynpriv.h>
/* Inserts the specified DLL at the head of the DLL list */
/* Returns 1 if the library was successfully added */
/* and returns 0 if the library table is full or */
/* or if LoadLibrary fails for some reason. */
static void fixPath(char *path)
{
char *p;
for(p = path; *p != '\0'; p++) if(*p == '\\') *p = '/';
}
static HINSTANCE R_loadLibrary(const char *path, int asLocal, int now);
static DL_FUNC getRoutine(DllInfo *info, char const *name);
static void R_deleteCachedSymbols(DllInfo *dll);
static void R_getDLLError(char *buf, int len);
static void GetFullDLLPath(SEXP call, char *buf, char *path);
static void closeLibrary(HINSTANCE handle)
{
FreeLibrary(handle);
}
void InitFunctionHashing()
{
R_osDynSymbol->loadLibrary = R_loadLibrary;
R_osDynSymbol->dlsym = getRoutine;
R_osDynSymbol->closeLibrary = closeLibrary;
R_osDynSymbol->getError = R_getDLLError;
R_osDynSymbol->deleteCachedSymbols = R_deleteCachedSymbols;
R_osDynSymbol->lookupCachedSymbol = Rf_lookupCachedSymbol;
R_osDynSymbol->fixPath = fixPath;
R_osDynSymbol->getFullDLLPath = GetFullDLLPath;
}
static void R_deleteCachedSymbols(DllInfo *dll)
{
int i;
for(i = nCPFun - 1; i >= 0; i--)
if(!strcmp(CPFun[i].pkg, dll->name)) {
if(i < nCPFun - 1) {
strcpy(CPFun[i].name, CPFun[--nCPFun].name);
strcpy(CPFun[i].pkg, CPFun[nCPFun].pkg);
CPFun[i].func = CPFun[nCPFun].func;
} else nCPFun--;
}
}
#ifndef _MCW_EM
_CRTIMP unsigned int __cdecl
_controlfp (unsigned int unNew, unsigned int unMask);
_CRTIMP unsigned int __cdecl _clearfp (void);
/* Control word masks for unMask */
#define _MCW_EM 0x0008001F /* Error masks */
#define _MCW_IC 0x00040000 /* Infinity */
#define _MCW_RC 0x00000300 /* Rounding */
#define _MCW_PC 0x00030000 /* Precision */
#endif
HINSTANCE R_loadLibrary(const char *path, int asLocal, int now)
{
HINSTANCE tdlh;
unsigned int dllcw, rcw;
rcw = _controlfp(0,0) & ~_MCW_IC; /* Infinity control is ignored */
_clearfp();
tdlh = LoadLibrary(path);
dllcw = _controlfp(0,0) & ~_MCW_IC;
if (dllcw != rcw) {
_controlfp(rcw, _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC);
if (LOGICAL(GetOption(install("warn.FPU"), R_BaseEnv))[0])
warning(_("DLL attempted to change FPU control word from %x to %x"),
rcw,dllcw);
}
return(tdlh);
}
static DL_FUNC getRoutine(DllInfo *info, char const *name)
{
DL_FUNC f;
f = (DL_FUNC) GetProcAddress(info->handle, name);
return(f);
}
static void R_getDLLError(char *buf, int len)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
strcpy(buf, "LoadLibrary failure: ");
strcat(buf, lpMsgBuf);
LocalFree(lpMsgBuf);
}
static void GetFullDLLPath(SEXP call, char *buf, char *path)
{
char *p;
if ((path[0] != '/') && (path[0] != '\\') && (path[1] != ':')) {
if (!getcwd(buf, MAX_PATH))
errorcall(call, _("cannot get working directory"));
strcat(buf, "\\");
strcat(buf, path);
} else
strcpy(buf, path);
/* fix slashes to allow inconsistent usage later */
for (p = buf; *p; p++) if (*p == '\\') *p = '/';
}
syntax highlighted by Code2HTML, v. 0.9.1