The R Project SVN R

Rev

Rev 29864 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 29864 Rev 30691
Line 42... Line 42...
42
 
42
 
43
static SEXP NaokSymbol = NULL;
43
static SEXP NaokSymbol = NULL;
44
static SEXP DupSymbol = NULL;
44
static SEXP DupSymbol = NULL;
45
static SEXP PkgSymbol = NULL;
45
static SEXP PkgSymbol = NULL;
46
 
46
 
-
 
47
/* Global variable that should go. Should actually be doing this in a much more straightforward manner. */
-
 
48
#include <Rdynpriv.h>
-
 
49
enum {FILENAME, DLL_HANDLE, R_OBJECT, NOT_DEFINED};
-
 
50
typedef struct {
47
static char DLLname[PATH_MAX];
51
    char DLLname[PATH_MAX];
-
 
52
    HINSTANCE dll;
-
 
53
    SEXP  obj;
-
 
54
    int type;
-
 
55
} DllReference;
-
 
56
 
48
 
57
 
49
/* This looks up entry points in DLLs in a platform specific way. */
58
/* This looks up entry points in DLLs in a platform specific way. */
50
#include <Rdynpriv.h>
59
#include <Rdynpriv.h>
51
 
60
 
-
 
61
#define MAX_ARGS 65
-
 
62
 
-
 
63
static DL_FUNC R_FindNativeSymbolFromDLL(char *name, DllReference *dll, R_RegisteredNativeSymbol *symbol);
-
 
64
 
-
 
65
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup, DllReference *dll);
-
 
66
static SEXP pkgtrim(SEXP args, DllReference *dll);
-
 
67
 
-
 
68
/*
-
 
69
  Checks whether the specified object correctly identifies a native routine.
-
 
70
  This can be  
-
 
71
   a) a string,
-
 
72
   b) an external pointer giving the address of the routine (e.g. getNativeSymbolInfo("foo")$address)
-
 
73
   c) or a NativeSymbolInfo itself  (e.g. getNativeSymbolInfo("foo"))
-
 
74
 */
-
 
75
static int
-
 
76
checkValidSymbolId(SEXP op, SEXP call, DL_FUNC *fun)
-
 
77
{
-
 
78
    if (isValidString(op))
-
 
79
	return(0);
-
 
80
 
-
 
81
    else if((TYPEOF(op) == EXTPTRSXP && R_ExternalPtrTag(op) == Rf_install("native symbol"))) {
-
 
82
 
-
 
83
	if((*fun = R_ExternalPtrAddr(op)) == NULL) 
-
 
84
	    errorcall(call, "NULL value passed as symbol address.");
-
 
85
	return(0);
-
 
86
 
-
 
87
    } else if(inherits(op, "NativeSymbolInfo")) {
-
 
88
 
-
 
89
	return(checkValidSymbolId(VECTOR_ELT(op, 1), call, fun));
-
 
90
 
-
 
91
    }
-
 
92
 
-
 
93
    errorcall(call, "function name must be a string (of length 1) or native symbol reference.");
-
 
94
    return(0);
-
 
95
}
-
 
96
 
-
 
97
 
-
 
98
/*
-
 
99
  This is the routine that is called by do_dotCode, do_dotcall and do_External
-
 
100
  to find the DL_FUNC to invoke. It handles processing the arguments for the
-
 
101
  PACKAGE argument, if present, and also takes care of the cases where we are given
-
 
102
  a NativeSymbolInfo object, an address directly, and if the DLL is specified.
-
 
103
  If no PACKAGE is provided, we check whether the calling function is in a namespace
-
 
104
  and look there.
-
 
105
*/
-
 
106
SEXP
-
 
107
resolveNativeRoutine(SEXP args, DL_FUNC *fun, R_RegisteredNativeSymbol *symbol, char *buf, 
-
 
108
		     int *nargs, int *naok, int *dup, SEXP call)
-
 
109
{
-
 
110
    SEXP op;
-
 
111
    char *p, *q;
-
 
112
    DllReference dll = {"", NULL, NULL, NOT_DEFINED}; 
-
 
113
 
-
 
114
    op = CAR(args);
-
 
115
    checkValidSymbolId(op, call, fun);
-
 
116
 
-
 
117
    /* The following code modifies the argument list */
-
 
118
    /* We know this is ok because do_dotCode is entered */
-
 
119
    /* with its arguments evaluated. */
-
 
120
 
-
 
121
    strcpy(dll.DLLname, "");
-
 
122
    if(symbol->type == R_C_SYM || symbol->type == R_FORTRAN_SYM) {
-
 
123
	args = naokfind(CDR(args), nargs, naok, dup, &dll);
-
 
124
	
-
 
125
	if(*naok == NA_LOGICAL)
-
 
126
	    errorcall(call, "invalid naok value");
-
 
127
	if(*nargs > MAX_ARGS)
-
 
128
	    errorcall(call, "too many arguments in foreign function call");
-
 
129
    } else {
-
 
130
	if (PkgSymbol == NULL) PkgSymbol = install("PACKAGE");
-
 
131
	args = pkgtrim(args, &dll);
-
 
132
    }
-
 
133
 
-
 
134
    /* Make up the load symbol and look it up. */
-
 
135
 
-
 
136
    if(TYPEOF(op) == STRSXP) {
-
 
137
	p = CHAR(STRING_ELT(op, 0));
-
 
138
	q = buf;
-
 
139
	while ((*q = *p) != '\0') {
-
 
140
	    p++;
-
 
141
	    q++;
-
 
142
	}
-
 
143
    } 
-
 
144
 
-
 
145
    if(!*fun) {
-
 
146
	if(dll.type != FILENAME) {
-
 
147
	    *fun = R_FindNativeSymbolFromDLL(buf, &dll, symbol);
-
 
148
	    if(!fun) {
-
 
149
		errorcall(call, "cannot resolve native routine");
-
 
150
	    }
-
 
151
	} 
-
 
152
 
-
 
153
	if (!*fun && !(*fun = R_FindSymbol(buf, dll.DLLname, symbol))) {
-
 
154
	    if(strlen(dll.DLLname))
-
 
155
		errorcall(call, "%s function name not in DLL for package %s",
-
 
156
			   symbol->type == R_FORTRAN_SYM ? "Fortran" : "C", 
-
 
157
			   dll.DLLname);
-
 
158
	    else
-
 
159
		errorcall(call, "%s function name not in load table",
-
 
160
			  symbol->type == R_FORTRAN_SYM ? "Fortran" : "C"); 
-
 
161
	}
-
 
162
    }
-
 
163
 
-
 
164
    return(args);
-
 
165
}
-
 
166
 
-
 
167
 
-
 
168
 
52
/* Convert an R object to a non-moveable C/Fortran object and return
169
/* Convert an R object to a non-moveable C/Fortran object and return
53
   a pointer to it.  This leaves pointers for anything other
170
   a pointer to it.  This leaves pointers for anything other
54
   than vectors and lists unaltered.
171
   than vectors and lists unaltered.
55
*/
172
*/
56
 
173
 
Line 306... Line 423...
306
/* or Fortran code which is either statically or dynamically linked. */
423
/* or Fortran code which is either statically or dynamically linked. */
307
 
424
 
308
/* NB: despite its name, this leaves NAOK and DUP arguments on the list */
425
/* NB: despite its name, this leaves NAOK and DUP arguments on the list */
309
 
426
 
310
/* find NAOK and DUP, find and remove PACKAGE */
427
/* find NAOK and DUP, find and remove PACKAGE */
311
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup)
428
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup, DllReference *dll)
312
{
429
{
313
    SEXP s, prev;
430
    SEXP s, prev;
314
    int nargs=0, naokused=0, dupused=0, pkgused=0;
431
    int nargs=0, naokused=0, dupused=0, pkgused=0;
315
    char *p;
432
    char *p;
316
 
433
 
Line 325... Line 442...
325
	} else if(TAG(s) == DupSymbol) {
442
	} else if(TAG(s) == DupSymbol) {
326
	    *dup = asLogical(CAR(s));
443
	    *dup = asLogical(CAR(s));
327
	    /* SETCDR(prev, s = CDR(s)); */
444
	    /* SETCDR(prev, s = CDR(s)); */
328
	    if(dupused++ == 1) warning("DUP used more than once");
445
	    if(dupused++ == 1) warning("DUP used more than once");
329
	} else if(TAG(s) == PkgSymbol) {
446
	} else if(TAG(s) == PkgSymbol) {
-
 
447
	    dll->obj = CAR(s);
-
 
448
	    if(TYPEOF(CAR(s)) == STRSXP) {
330
	    p = CHAR(STRING_ELT(CAR(s), 0));
449
		p = CHAR(STRING_ELT(CAR(s), 0));
331
	    if(strlen(p) > PATH_MAX - 1)
450
		if(strlen(p) > PATH_MAX - 1)
332
		error("DLL name is too long");
451
		    error("DLL name is too long");
-
 
452
		dll->type = FILENAME;
333
	    strcpy(DLLname, p);
453
		strcpy(dll->DLLname, p);
334
	    if(pkgused++ > 1) warning("PACKAGE used more than once");
454
		if(pkgused++ > 1) warning("PACKAGE used more than once");
335
	    /* More generally, this should allow us to process
455
		/* More generally, this should allow us to process
336
               any additional arguments and not insist that PACKAGE
456
		   any additional arguments and not insist that PACKAGE
337
               be the last argument.
457
		   be the last argument.
-
 
458
		*/
338
             */
459
	    } else {
-
 
460
		    /* Have a DLL object*/
-
 
461
	        if(TYPEOF(CAR(s)) == EXTPTRSXP) {
-
 
462
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(CAR(s));
-
 
463
		    dll->type = DLL_HANDLE;
-
 
464
		} else if(TYPEOF(CAR(s)) == VECSXP) {
-
 
465
		    dll->type = R_OBJECT;
-
 
466
		    dll->obj = s;
-
 
467
		    strcpy(dll->DLLname, CHAR(STRING_ELT(VECTOR_ELT(CAR(s), 1), 0)));
-
 
468
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(VECTOR_ELT(s, 4));
-
 
469
		}
-
 
470
	    }
339
	} else {
471
	} else {
340
	    nargs++;
472
	    nargs++;
341
	    prev = s;
473
	    prev = s;
342
	    s = CDR(s);
474
	    s = CDR(s);
343
	    continue;
475
	    continue;
Line 349... Line 481...
349
    }
481
    }
350
    *len = nargs;
482
    *len = nargs;
351
    return args;
483
    return args;
352
}
484
}
353
 
485
 
354
static void setDLLname(SEXP s, char *DLLName)
486
static void setDLLname(SEXP s, char *DLLname)
355
{
487
{
356
    SEXP ss = CAR(s); char *name;
488
    SEXP ss = CAR(s); char *name;
357
    if(TYPEOF(ss) != STRSXP || length(ss) != 1)
489
    if(TYPEOF(ss) != STRSXP || length(ss) != 1)
358
	error("PACKAGE argument must be a single character string");
490
	error("PACKAGE argument must be a single character string");
359
    name = CHAR(STRING_ELT(ss, 0));
491
    name = CHAR(STRING_ELT(ss, 0));
Line 363... Line 495...
363
    if(strlen(name) > PATH_MAX - 1)
495
    if(strlen(name) > PATH_MAX - 1)
364
	error("PACKAGE argument is too long");
496
	error("PACKAGE argument is too long");
365
    strcpy(DLLname, name);
497
    strcpy(DLLname, name);
366
}
498
}
367
 
499
 
368
static SEXP pkgtrim(SEXP args)
500
static SEXP pkgtrim(SEXP args, DllReference *dll)
369
{
501
{
370
    SEXP s, ss;
502
    SEXP s, ss;
371
    int pkgused=0;
503
    int pkgused=0;
372
 
504
 
373
    for(s = args ; s != R_NilValue;) {
505
    for(s = args ; s != R_NilValue;) {
Line 375... Line 507...
375
	/* Look for PACKAGE=. We look at the next arg, unless
507
	/* Look for PACKAGE=. We look at the next arg, unless
376
	   this is the last one (which will only happen for one arg),
508
	   this is the last one (which will only happen for one arg),
377
	   and remove it */
509
	   and remove it */
378
	if(ss == R_NilValue && TAG(s) == PkgSymbol) {
510
	if(ss == R_NilValue && TAG(s) == PkgSymbol) {
379
	    if(pkgused++ == 1) warning("PACKAGE used more than once");
511
	    if(pkgused++ == 1) warning("PACKAGE used more than once");
380
	    setDLLname(s, DLLname);
512
	    setDLLname(s, dll->DLLname);
-
 
513
	    dll->type = FILENAME;
381
	    return R_NilValue;
514
	    return R_NilValue;
382
	}
515
	}
383
	if(TAG(ss) == PkgSymbol) {
516
	if(TAG(ss) == PkgSymbol) {
384
	    if(pkgused++ == 1) warning("PACKAGE used more than once");
517
	    if(pkgused++ == 1) warning("PACKAGE used more than once");
385
	    setDLLname(ss, DLLname);
518
	    setDLLname(ss, dll->DLLname);
-
 
519
	    dll->type = FILENAME;
386
	    SETCDR(s, CDR(ss));
520
	    SETCDR(s, CDR(ss));
387
	}
521
	}
388
	s = CDR(s);
522
	s = CDR(s);
389
    }
523
    }
390
    return args;
524
    return args;
391
}
525
}
392
 
526
 
393
#define MAX_ARGS 65
-
 
-
 
527
 
394
 
528
 
395
SEXP do_symbol(SEXP call, SEXP op, SEXP args, SEXP env)
529
SEXP do_symbol(SEXP call, SEXP op, SEXP args, SEXP env)
396
{
530
{
397
    char buf[128], *p, *q;
531
    char buf[128], *p, *q;
398
    checkArity(op, args);
532
    checkArity(op, args);
Line 439... Line 573...
439
/*   Call dynamically loaded "internal" functions */
573
/*   Call dynamically loaded "internal" functions */
440
/*   code by Jean Meloche <jean@stat.ubc.ca> */
574
/*   code by Jean Meloche <jean@stat.ubc.ca> */
441
 
575
 
442
SEXP do_External(SEXP call, SEXP op, SEXP args, SEXP env)
576
SEXP do_External(SEXP call, SEXP op, SEXP args, SEXP env)
443
{
577
{
444
    DL_FUNC fun;
578
    DL_FUNC fun = NULL;
445
    SEXP retval;
579
    SEXP retval;
446
    R_RegisteredNativeSymbol symbol = {R_EXTERNAL_SYM, {NULL}, NULL};
580
    R_RegisteredNativeSymbol symbol = {R_EXTERNAL_SYM, {NULL}, NULL};
447
    /* I don't like this messing with vmax <TSL> */
581
    /* I don't like this messing with vmax <TSL> */
448
    /* But it is needed for clearing R_alloc and to be like .Call <BDR>*/
582
    /* But it is needed for clearing R_alloc and to be like .Call <BDR>*/
449
    char *vmax = vmaxget();
583
    char *vmax = vmaxget(), buf[128];
450
 
584
 
451
    op = CAR(args);
-
 
452
    if (!isValidString(op))
-
 
453
	errorcall(call, "function name must be a string (of length 1)");
-
 
454
    if (PkgSymbol == NULL) PkgSymbol = install("PACKAGE");
-
 
455
    strcpy(DLLname, "");
-
 
456
    args = pkgtrim(args);
-
 
457
 
-
 
458
    if (!(fun=R_FindSymbol(CHAR(STRING_ELT(op, 0)), DLLname, NULL))) {
585
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL, NULL, call);
459
	if(strlen(DLLname))
-
 
460
	    errorcall(call,
-
 
461
		      ".External function name not in DLL for package %s", 
-
 
462
		      DLLname);
-
 
463
	else
-
 
464
	    errorcall(call, ".External function name not in load table");
-
 
465
    }
-
 
466
 
586
 
-
 
587
    /* Some external symbols that are registered may have 0 as the expected number of arguments.
-
 
588
       We may want a warning here. However, the number of values may vary across calls
-
 
589
       and that is why people use the .External() mechanism.  So perhaps we should just kill this 
-
 
590
       check. */
-
 
591
#ifdef CHECK_EXTERNAL_ARG_COUNT         /* Off by default. */
467
    if(symbol.symbol.external && symbol.symbol.external->numArgs > -1) {
592
    if(symbol.symbol.external && symbol.symbol.external->numArgs > -1) {
468
	if(symbol.symbol.external->numArgs != length(args))
593
	if(symbol.symbol.external->numArgs != length(args))
469
	    error("Incorrect number of arguments (%d), expecting %d for %s",
594
	    error("Incorrect number of arguments (%d), expecting %d for %s",
470
		  length(args), symbol.symbol.external->numArgs, CHAR(STRING_ELT(op, 0)));
595
		  length(args), symbol.symbol.external->numArgs, CHAR(STRING_ELT(op, 0)));
471
    }
596
    }
-
 
597
#endif
-
 
598
 
472
    retval = (SEXP)fun(args);
599
    retval = (SEXP)fun(args);
473
    vmaxset(vmax);
600
    vmaxset(vmax);
474
    return retval;
601
    return retval;
475
}
602
}
476
 
603
 
477
 
604
 
478
/* .Call(name, <args>) */
605
/* .Call(name, <args>) */
479
SEXP do_dotcall(SEXP call, SEXP op, SEXP args, SEXP env)
606
SEXP do_dotcall(SEXP call, SEXP op, SEXP args, SEXP env)
480
{
607
{
481
    DL_FUNC fun;
608
    DL_FUNC fun = NULL;
482
    SEXP retval, cargs[MAX_ARGS], pargs;
609
    SEXP retval, cargs[MAX_ARGS], pargs;
483
    R_RegisteredNativeSymbol symbol = {R_CALL_SYM, {NULL}, NULL};
610
    R_RegisteredNativeSymbol symbol = {R_CALL_SYM, {NULL}, NULL};
484
    int nargs;
611
    int nargs;
485
    char *vmax = vmaxget();
612
    char *vmax = vmaxget();
486
    op = CAR(args);
613
    char buf[128];
487
    if (!isValidString(op))
-
 
488
	errorcall(call, "function name must be a string (of length 1)");
-
 
489
 
614
 
490
    if (PkgSymbol == NULL) PkgSymbol = install("PACKAGE");
-
 
491
    strcpy(DLLname, "");
-
 
492
    args = pkgtrim(args);
-
 
493
 
-
 
494
    if (!(fun=R_FindSymbol(CHAR(STRING_ELT(op, 0)), DLLname, &symbol))) {
615
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL, NULL, call);
495
	if(strlen(DLLname))
-
 
496
	    errorcall(call, ".Call function name not in DLL for package %s", 
-
 
497
		      DLLname);
-
 
498
	else
-
 
499
	    errorcall(call, ".Call function name not in load table");
-
 
500
    }
-
 
501
    args = CDR(args);
616
    args = CDR(args);
502
 
617
 
503
    for(nargs = 0, pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
618
    for(nargs = 0, pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
504
        if (nargs == MAX_ARGS)
619
        if (nargs == MAX_ARGS)
505
            errorcall(call, "too many arguments in foreign function call");
620
            errorcall(call, "too many arguments in foreign function call");
Line 1194... Line 1309...
1194
    }
1309
    }
1195
    return retval;
1310
    return retval;
1196
}
1311
}
1197
 
1312
 
1198
 
1313
 
-
 
1314
 
-
 
1315
static SEXP
-
 
1316
Rf_getCallingDLL()
-
 
1317
{
-
 
1318
    SEXP e, ans;
-
 
1319
    PROTECT(e = allocVector(LANGSXP, 1));
-
 
1320
    SETCAR(e, Rf_install("getCallingDLL"));
-
 
1321
    ans = eval(e,  R_GlobalEnv);
-
 
1322
 
-
 
1323
    UNPROTECT(1);
-
 
1324
    return(ans);
-
 
1325
}
-
 
1326
 
-
 
1327
 
-
 
1328
/*
-
 
1329
  We are given the PACKAGE argument in dll.obj
-
 
1330
  and we can try to figure out how to resolve this.
-
 
1331
  0) dll.obj is NULL.  Then find the environment of the 
-
 
1332
   calling function and if it is a namespace, get the 
-
 
1333
   
-
 
1334
  1) dll.obj is a DLLInfo object
-
 
1335
*/
-
 
1336
static DL_FUNC
-
 
1337
R_FindNativeSymbolFromDLL(char *name, DllReference *dll, R_RegisteredNativeSymbol *symbol)
-
 
1338
{
-
 
1339
    int numProtects = 0;
-
 
1340
    DllInfo *info;
-
 
1341
    DL_FUNC fun = NULL;
-
 
1342
 
-
 
1343
    if(dll->obj == NULL) {
-
 
1344
	dll->obj = Rf_getCallingDLL();
-
 
1345
	PROTECT(dll->obj); numProtects++;
-
 
1346
    }
-
 
1347
 
-
 
1348
    if(inherits(dll->obj, "DLLInfo")) {
-
 
1349
	SEXP tmp;
-
 
1350
/*XXX*/
-
 
1351
DL_FUNC R_dlsym(DllInfo *info, char const *name, R_RegisteredNativeSymbol *symbol);
-
 
1352
	tmp = VECTOR_ELT(dll->obj, 4);
-
 
1353
	info = (DllInfo *) R_ExternalPtrAddr(tmp);
-
 
1354
	if(!info) 
-
 
1355
	    error("NULL value for DLLInfoReference when looking for DLL");
-
 
1356
	fun = R_dlsym(info, name, symbol);
-
 
1357
    }
-
 
1358
 
-
 
1359
    if(numProtects)
-
 
1360
	UNPROTECT(numProtects);
-
 
1361
 
-
 
1362
    return(fun);
-
 
1363
}
-
 
1364
 
-
 
1365
 
-
 
1366
 
1199
/* .C() {op=0}  or  .Fortran() {op=1} */
1367
/* .C() {op=0}  or  .Fortran() {op=1} */
1200
SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env)
1368
SEXP do_dotCode(SEXP call, SEXP op, SEXP args, SEXP env)
1201
{
1369
{
1202
    void **cargs;
1370
    void **cargs;
1203
    int dup, havenames, naok, nargs, which;
1371
    int dup, havenames, naok, nargs, which;
1204
    DL_FUNC fun;
1372
    DL_FUNC fun = NULL;
1205
    SEXP ans, pargs, s;
1373
    SEXP ans, pargs, s;
1206
    R_toCConverter  *argConverters[65]; /* the post-call converters back to R objects. */
1374
    R_toCConverter  *argConverters[65]; /* the post-call converters back to R objects. */
1207
    R_RegisteredNativeSymbol symbol = {R_C_SYM, {NULL}, NULL};
1375
    R_RegisteredNativeSymbol symbol = {R_C_SYM, {NULL}, NULL};
1208
    R_NativePrimitiveArgType *checkTypes = NULL;
1376
    R_NativePrimitiveArgType *checkTypes = NULL;
1209
    R_NativeArgStyle *argStyles = NULL;
1377
    R_NativeArgStyle *argStyles = NULL;
-
 
1378
    char *vmax, symName[128];
1210
 
1379
 
1211
    char buf[128], *p, *q, *vmax;
-
 
1212
    if (NaokSymbol == NULL || DupSymbol == NULL || PkgSymbol == NULL) {
1380
    if (NaokSymbol == NULL || DupSymbol == NULL || PkgSymbol == NULL) {
1213
	NaokSymbol = install("NAOK");
1381
	NaokSymbol = install("NAOK");
1214
	DupSymbol = install("DUP");
1382
	DupSymbol = install("DUP");
1215
	PkgSymbol = install("PACKAGE");
1383
	PkgSymbol = install("PACKAGE");
1216
    }
1384
    }
1217
    vmax = vmaxget();
1385
    vmax = vmaxget();
1218
    which = PRIMVAL(op);
1386
    which = PRIMVAL(op);
1219
    if(which)
1387
    if(which)
1220
	symbol.type = R_FORTRAN_SYM;
1388
	symbol.type = R_FORTRAN_SYM;
1221
    op = CAR(args);
-
 
1222
    if (!isValidString(op))
-
 
1223
	errorcall(call, "function name must be a string (of length 1)");
-
 
1224
 
1389
 
1225
    /* The following code modifies the argument list */
-
 
1226
    /* We know this is ok because do_dotCode is entered */
-
 
1227
    /* with its arguments evaluated. */
-
 
1228
 
-
 
1229
    strcpy(DLLname, "");
-
 
1230
    args = naokfind(CDR(args), &nargs, &naok, &dup);
1390
    args = resolveNativeRoutine(args, &fun, &symbol, symName, &nargs, &naok, &dup, call);
1231
    if(naok == NA_LOGICAL)
-
 
1232
	errorcall(call, "invalid naok value");
-
 
1233
    if(nargs > MAX_ARGS)
-
 
1234
	errorcall(call, "too many arguments in foreign function call");
-
 
1235
 
-
 
1236
    /* Make up the load symbol and look it up. */
-
 
1237
 
-
 
1238
    p = CHAR(STRING_ELT(op, 0));
-
 
1239
    q = buf;
-
 
1240
    while ((*q = *p) != '\0') {
-
 
1241
	p++;
-
 
1242
	q++;
-
 
1243
    }
-
 
1244
 
-
 
1245
    if (!(fun = R_FindSymbol(buf, DLLname, &symbol))) {
-
 
1246
	if(strlen(DLLname))
-
 
1247
	    errorcall(call, "%s function name not in DLL for package %s",
-
 
1248
		      which ? "Fortran" : "C", DLLname);
-
 
1249
	else
-
 
1250
	    errorcall(call, "%s function name not in load table",
-
 
1251
		      which ? "Fortran" : "C");
-
 
1252
    }
-
 
1253
 
1391
 
1254
    if(symbol.symbol.c && symbol.symbol.c->numArgs > -1) {
1392
    if(symbol.symbol.c && symbol.symbol.c->numArgs > -1) {
1255
	if(symbol.symbol.c->numArgs != nargs)
1393
	if(symbol.symbol.c->numArgs != nargs)
1256
	    error("Incorrect number of arguments (%d), expecting %d for %s",
1394
	    error("Incorrect number of arguments (%d), expecting %d for %s",
1257
		  nargs, symbol.symbol.c->numArgs, buf);
1395
		  nargs, symbol.symbol.c->numArgs, symName);
1258
 
1396
 
1259
        checkTypes = symbol.symbol.c->types;
1397
	checkTypes = symbol.symbol.c->types;
1260
        argStyles = symbol.symbol.c->styles;
1398
	argStyles = symbol.symbol.c->styles;
1261
    }
1399
    }
1262
 
1400
 
-
 
1401
 
1263
    /* Convert the arguments for use in foreign */
1402
    /* Convert the arguments for use in foreign */
1264
    /* function calls.  Note that we copy twice */
1403
    /* function calls.  Note that we copy twice */
1265
    /* once here, on the way into the call, and */
1404
    /* once here, on the way into the call, and */
1266
    /* once below on the way out. */
1405
    /* once below on the way out. */
1267
    cargs = (void**)R_alloc(nargs, sizeof(void*));
1406
    cargs = (void**)R_alloc(nargs, sizeof(void*));
Line 1273... Line 1412...
1273
               but then we would also want to avoid the conversions.
1412
               but then we would also want to avoid the conversions.
1274
               Also, in the future, we may just attempt to coerce the value
1413
               Also, in the future, we may just attempt to coerce the value
1275
               to the appropriate type. This is why we pass the checkTypes[nargs]
1414
               to the appropriate type. This is why we pass the checkTypes[nargs]
1276
               value to RObjToCPtr(). We just have to sort out the ability to
1415
               value to RObjToCPtr(). We just have to sort out the ability to
1277
               return the correct value which is complicated by dup, etc. */
1416
               return the correct value which is complicated by dup, etc. */
1278
  	   error("Wrong type for argument %d in call to %s", nargs+1, buf);
1417
	    error("Wrong type for argument %d in call to %s", nargs+1, symName);
1279
	}
1418
	}
1280
#endif
1419
#endif
1281
	cargs[nargs] = RObjToCPtr(CAR(pargs), naok, dup, nargs + 1,
1420
	cargs[nargs] = RObjToCPtr(CAR(pargs), naok, dup, nargs + 1,
1282
				  which, buf, argConverters + nargs,
1421
				  which, symName, argConverters + nargs,
1283
				  checkTypes ? checkTypes[nargs] : 0);
1422
				  checkTypes ? checkTypes[nargs] : 0);
1284
	nargs++;
1423
	nargs++;
1285
    }
1424
    }
1286
 
1425
 
1287
 
1426
 
Line 1884... Line 2023...
1884
    if (dup) {
2023
    if (dup) {
1885
	R_FromCConvertInfo info;
2024
	R_FromCConvertInfo info;
1886
	info.cargs = cargs;
2025
	info.cargs = cargs;
1887
	info.allArgs = args;
2026
	info.allArgs = args;
1888
	info.nargs = nargs;
2027
	info.nargs = nargs;
1889
	info.functionName = buf;
2028
	info.functionName = symName;
1890
	nargs = 0;
2029
	nargs = 0;
1891
	for (pargs = args ; pargs != R_NilValue ; pargs = CDR(pargs)) {
2030
	for (pargs = args ; pargs != R_NilValue ; pargs = CDR(pargs)) {
1892
	    if(argStyles && argStyles[nargs] == R_ARG_IN) {
2031
	    if(argStyles && argStyles[nargs] == R_ARG_IN) {
1893
	        PROTECT(s = R_NilValue);
2032
	        PROTECT(s = R_NilValue);
1894
	    } else if(argConverters[nargs]) {
2033
	    } else if(argConverters[nargs]) {