PageRenderTime 60ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Modules/r.cxx

#
C++ | 2303 lines | 1619 code | 393 blank | 291 comment | 356 complexity | 0cca9d9c96a54dc3a1036496592ca751 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * r.cxx
  10. *
  11. * R language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_r_cxx[] = "$Id: r.cxx 12937 2012-03-18 17:11:02Z drjoe $";
  14. #include "swigmod.h"
  15. static const double DEFAULT_NUMBER = .0000123456712312312323;
  16. static const int MAX_OVERLOAD_ARGS = 5;
  17. static String* replaceInitialDash(const String *name)
  18. {
  19. String *retval;
  20. if (!Strncmp(name, "_", 1)) {
  21. retval = Copy(name);
  22. Insert(retval, 0, "s");
  23. } else {
  24. retval = Copy(name);
  25. }
  26. return retval;
  27. }
  28. static String * getRTypeName(SwigType *t, int *outCount = NULL) {
  29. String *b = SwigType_base(t);
  30. List *els = SwigType_split(t);
  31. int count = 0;
  32. int i;
  33. if(Strncmp(b, "struct ", 7) == 0)
  34. Replace(b, "struct ", "", DOH_REPLACE_FIRST);
  35. /* Printf(stdout, "<getRTypeName> %s,base = %s\n", t, b);
  36. for(i = 0; i < Len(els); i++)
  37. Printf(stdout, "%d) %s, ", i, Getitem(els,i));
  38. Printf(stdout, "\n"); */
  39. for(i = 0; i < Len(els); i++) {
  40. String *el = Getitem(els, i);
  41. if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) {
  42. count++;
  43. Append(b, "Ref");
  44. }
  45. }
  46. if(outCount)
  47. *outCount = count;
  48. String *tmp = NewString("");
  49. char *retName = Char(SwigType_manglestr(t));
  50. Insert(tmp, 0, retName);
  51. return tmp;
  52. /*
  53. if(count)
  54. return(b);
  55. Delete(b);
  56. return(NewString(""));
  57. */
  58. }
  59. /*********************
  60. Tries to get the name of the R class corresponding to the given type
  61. e.g. struct A * is ARef, struct A** is ARefRef.
  62. Now handles arrays, i.e. struct A[2]
  63. ****************/
  64. static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
  65. String *tmp = NewString("");
  66. SwigType *resolved = SwigType_typedef_resolve_all(retType);
  67. char *retName = Char(SwigType_manglestr(resolved));
  68. if (upRef) {
  69. Printf(tmp, "_p%s", retName);
  70. } else{
  71. Insert(tmp, 0, retName);
  72. }
  73. return tmp;
  74. /*
  75. #if 1
  76. List *l = SwigType_split(retType);
  77. int n = Len(l);
  78. if(!l || n == 0) {
  79. #ifdef R_SWIG_VERBOSE
  80. if (debugMode)
  81. Printf(stdout, "SwigType_split return an empty list for %s\n",
  82. retType);
  83. #endif
  84. return(tmp);
  85. }
  86. String *el = Getitem(l, n-1);
  87. char *ptr = Char(el);
  88. if(strncmp(ptr, "struct ", 7) == 0)
  89. ptr += 7;
  90. Printf(tmp, "%s", ptr);
  91. if(addRef) {
  92. for(int i = 0; i < n; i++) {
  93. if(Strcmp(Getitem(l, i), "p.") == 0 ||
  94. Strncmp(Getitem(l, i), "a(", 2) == 0)
  95. Printf(tmp, "Ref");
  96. }
  97. }
  98. #else
  99. char *retName = Char(SwigType_manglestr(retType));
  100. if(!retName)
  101. return(tmp);
  102. if(addRef) {
  103. while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) {
  104. retName += 2;
  105. Printf(tmp, "Ref");
  106. }
  107. }
  108. if(retName[0] == '_')
  109. retName ++;
  110. Insert(tmp, 0, retName);
  111. #endif
  112. return tmp;
  113. */
  114. }
  115. /*********************
  116. Tries to get the name of the R class corresponding to the given type
  117. e.g. struct A * is ARef, struct A** is ARefRef.
  118. Now handles arrays, i.e. struct A[2]
  119. ****************/
  120. static String * getRClassNameCopyStruct(String *retType, int addRef) {
  121. String *tmp = NewString("");
  122. #if 1
  123. List *l = SwigType_split(retType);
  124. int n = Len(l);
  125. if(!l || n == 0) {
  126. #ifdef R_SWIG_VERBOSE
  127. Printf(stdout, "SwigType_split return an empty list for %s\n", retType);
  128. #endif
  129. return(tmp);
  130. }
  131. String *el = Getitem(l, n-1);
  132. char *ptr = Char(el);
  133. if(strncmp(ptr, "struct ", 7) == 0)
  134. ptr += 7;
  135. Printf(tmp, "%s", ptr);
  136. if(addRef) {
  137. for(int i = 0; i < n; i++) {
  138. if(Strcmp(Getitem(l, i), "p.") == 0 ||
  139. Strncmp(Getitem(l, i), "a(", 2) == 0)
  140. Printf(tmp, "Ref");
  141. }
  142. }
  143. #else
  144. char *retName = Char(SwigType_manglestr(retType));
  145. if(!retName)
  146. return(tmp);
  147. if(addRef) {
  148. while(retName && strlen(retName) > 1 &&
  149. strncmp(retName, "_p", 2) == 0) {
  150. retName += 2;
  151. Printf(tmp, "Ref");
  152. }
  153. }
  154. if(retName[0] == '_')
  155. retName ++;
  156. Insert(tmp, 0, retName);
  157. #endif
  158. return tmp;
  159. }
  160. /*********************************
  161. Write the elements of a list to the File*, one element per line.
  162. If quote is true, surround the element with "element".
  163. This takes care of inserting a tab in front of each line and also
  164. a comma after each element, except the last one.
  165. **********************************/
  166. static void writeListByLine(List *l, File *out, bool quote = 0) {
  167. int i, n = Len(l);
  168. for(i = 0; i < n; i++)
  169. Printf(out, "%s%s%s%s%s\n", tab8,
  170. quote ? "\"" :"",
  171. Getitem(l, i),
  172. quote ? "\"" :"", i < n-1 ? "," : "");
  173. }
  174. static const char *usage = (char *)"\
  175. R Options (available with -r)\n\
  176. -copystruct - Emit R code to copy C structs (on by default)\n\
  177. -cppcast - Enable C++ casting operators (default) \n\
  178. -debug - Output debug\n\
  179. -dll <name> - Name of the DLL (without the .dll or .so suffix).\n\
  180. Default is the module name.\n\
  181. -gc - Aggressive garbage collection\n\
  182. -memoryprof - Add memory profile\n\
  183. -namespace - Output NAMESPACE file\n\
  184. -no-init-code - Turn off the generation of the R_init_<pkgname> code\n\
  185. (registration information still generated)\n\
  186. -package <name> - Package name for the PACKAGE argument of the R .Call()\n\
  187. invocations. Default is the module name.\n\
  188. ";
  189. /************
  190. Display the help for this module on the screen/console.
  191. *************/
  192. static void showUsage() {
  193. fputs(usage, stdout);
  194. }
  195. static bool expandTypedef(SwigType *t) {
  196. if (SwigType_isenum(t)) return false;
  197. String *prefix = SwigType_prefix(t);
  198. if (Strncmp(prefix, "f", 1)) return false;
  199. if (Strncmp(prefix, "p.f", 3)) return false;
  200. return true;
  201. }
  202. /*****
  203. Determine whether we should add a .copy argument to the S function
  204. that wraps/interfaces to the routine that returns the given type.
  205. *****/
  206. static int addCopyParameter(SwigType *type) {
  207. int ok = 0;
  208. ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0;
  209. if(!ok) {
  210. ok = Strncmp(type, "p.", 2);
  211. }
  212. return(ok);
  213. }
  214. static void replaceRClass(String *tm, SwigType *type) {
  215. String *tmp = getRClassName(type);
  216. String *tmp_base = getRClassName(type, 0);
  217. String *tmp_ref = getRClassName(type, 1, 1);
  218. Replaceall(tm, "$R_class", tmp);
  219. Replaceall(tm, "$*R_class", tmp_base);
  220. Replaceall(tm, "$&R_class", tmp_ref);
  221. Delete(tmp); Delete(tmp_base); Delete(tmp_ref);
  222. }
  223. static double getNumber(String *value) {
  224. double d = DEFAULT_NUMBER;
  225. if(Char(value)) {
  226. if(sscanf(Char(value), "%lf", &d) != 1)
  227. return(DEFAULT_NUMBER);
  228. }
  229. return(d);
  230. }
  231. class R : public Language {
  232. public:
  233. R();
  234. void registerClass(Node *n);
  235. void main(int argc, char *argv[]);
  236. int top(Node *n);
  237. void dispatchFunction(Node *n);
  238. int functionWrapper(Node *n);
  239. int variableWrapper(Node *n);
  240. int classDeclaration(Node *n);
  241. int enumDeclaration(Node *n);
  242. int membervariableHandler(Node *n);
  243. int typedefHandler(Node *n);
  244. static List *Swig_overload_rank(Node *n,
  245. bool script_lang_wrapping);
  246. int memberfunctionHandler(Node *n) {
  247. if (debugMode)
  248. Printf(stdout, "<memberfunctionHandler> %s %s\n",
  249. Getattr(n, "name"),
  250. Getattr(n, "type"));
  251. member_name = Getattr(n, "sym:name");
  252. processing_class_member_function = 1;
  253. int status = Language::memberfunctionHandler(n);
  254. processing_class_member_function = 0;
  255. return status;
  256. }
  257. /* Grab the name of the current class being processed so that we can
  258. deal with members of that class. */
  259. int classHandler(Node *n){
  260. if(!ClassMemberTable)
  261. ClassMemberTable = NewHash();
  262. class_name = Getattr(n, "name");
  263. int status = Language::classHandler(n);
  264. class_name = NULL;
  265. return status;
  266. }
  267. // Not used:
  268. String *runtimeCode();
  269. protected:
  270. int addRegistrationRoutine(String *rname, int nargs);
  271. int outputRegistrationRoutines(File *out);
  272. int outputCommandLineArguments(File *out);
  273. int generateCopyRoutines(Node *n);
  274. int DumpCode(Node *n);
  275. int OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out);
  276. int OutputArrayMethod(String *className, List *el, File *out);
  277. int OutputClassMemberTable(Hash *tb, File *out);
  278. int OutputClassMethodsTable(File *out);
  279. int OutputClassAccessInfo(Hash *tb, File *out);
  280. int defineArrayAccessors(SwigType *type);
  281. void addNamespaceFunction(String *name) {
  282. if(!namespaceFunctions)
  283. namespaceFunctions = NewList();
  284. Append(namespaceFunctions, name);
  285. }
  286. void addNamespaceMethod(String *name) {
  287. if(!namespaceMethods)
  288. namespaceMethods = NewList();
  289. Append(namespaceMethods, name);
  290. }
  291. String* processType(SwigType *t, Node *n, int *nargs = NULL);
  292. String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs);
  293. int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) {
  294. /*XXX Do we need to put the t in there to get the return type later. */
  295. if(!functionPointerProxyTable)
  296. functionPointerProxyTable = NewHash();
  297. Setattr(functionPointerProxyTable, name, n);
  298. Setattr(SClassDefs, name, name);
  299. Printv(s_classes, "setClass('",
  300. name,
  301. "',\n", tab8,
  302. "prototype = list(parameterTypes = c(", s_paramTypes, "),\n",
  303. tab8, tab8, tab8,
  304. "returnType = '", SwigType_manglestr(t), "'),\n", tab8,
  305. "contains = 'CRoutinePointer')\n\n##\n", NIL);
  306. return SWIG_OK;
  307. }
  308. void addSMethodInfo(String *name,
  309. String *argType, int nargs);
  310. // Simple initialization such as constant strings that can be reused.
  311. void init();
  312. void addAccessor(String *memberName, Wrapper *f,
  313. String *name, int isSet = -1);
  314. static int getFunctionPointerNumArgs(Node *n, SwigType *tt);
  315. protected:
  316. bool copyStruct;
  317. bool memoryProfile;
  318. bool aggressiveGc;
  319. // Strings into which we cumulate the generated code that is to be written
  320. //vto the files.
  321. String *sfile;
  322. String *f_init;
  323. String *s_classes;
  324. String *f_begin;
  325. String *f_runtime;
  326. String *f_wrapper;
  327. String *s_header;
  328. String *f_wrappers;
  329. String *s_init;
  330. String *s_init_routine;
  331. String *s_namespace;
  332. // State variables that carry information across calls to functionWrapper()
  333. // from member accessors and class declarations.
  334. String *opaqueClassDeclaration;
  335. int processing_variable;
  336. int processing_member_access_function;
  337. String *member_name;
  338. String *class_name;
  339. int processing_class_member_function;
  340. List *class_member_functions;
  341. List *class_member_set_functions;
  342. /* */
  343. Hash *ClassMemberTable;
  344. Hash *ClassMethodsTable;
  345. Hash *SClassDefs;
  346. Hash *SMethodInfo;
  347. // Information about routines that are generated and to be registered with
  348. // R for dynamic lookup.
  349. Hash *registrationTable;
  350. Hash *functionPointerProxyTable;
  351. List *namespaceFunctions;
  352. List *namespaceMethods;
  353. List *namespaceClasses; // Probably can do this from ClassMemberTable.
  354. // Store a copy of the command line.
  355. // Need only keep a string that has it formatted.
  356. char **Argv;
  357. int Argc;
  358. bool inCPlusMode;
  359. // State variables that we remember from the command line settings
  360. // potentially that govern the code we generate.
  361. String *DllName;
  362. String *Rpackage;
  363. bool noInitializationCode;
  364. bool outputNamespaceInfo;
  365. String *UnProtectWrapupCode;
  366. // Static members
  367. static bool debugMode;
  368. };
  369. R::R() :
  370. copyStruct(false),
  371. memoryProfile(false),
  372. aggressiveGc(false),
  373. sfile(0),
  374. f_init(0),
  375. s_classes(0),
  376. f_begin(0),
  377. f_runtime(0),
  378. f_wrapper(0),
  379. s_header(0),
  380. f_wrappers(0),
  381. s_init(0),
  382. s_init_routine(0),
  383. s_namespace(0),
  384. opaqueClassDeclaration(0),
  385. processing_variable(0),
  386. processing_member_access_function(0),
  387. member_name(0),
  388. class_name(0),
  389. processing_class_member_function(0),
  390. class_member_functions(0),
  391. class_member_set_functions(0),
  392. ClassMemberTable(0),
  393. ClassMethodsTable(0),
  394. SClassDefs(0),
  395. SMethodInfo(0),
  396. registrationTable(0),
  397. functionPointerProxyTable(0),
  398. namespaceFunctions(0),
  399. namespaceMethods(0),
  400. namespaceClasses(0),
  401. Argv(0),
  402. Argc(0),
  403. inCPlusMode(false),
  404. DllName(0),
  405. Rpackage(0),
  406. noInitializationCode(false),
  407. outputNamespaceInfo(false),
  408. UnProtectWrapupCode(0) {
  409. }
  410. bool R::debugMode = false;
  411. int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) {
  412. (void) tt;
  413. n = Getattr(n, "type");
  414. if (debugMode)
  415. Printf(stdout, "type: %s\n", n);
  416. ParmList *parms = Getattr(n, "parms");
  417. if (debugMode)
  418. Printf(stdout, "parms = %p\n", parms);
  419. return ParmList_len(parms);
  420. }
  421. void R::addSMethodInfo(String *name, String *argType, int nargs) {
  422. (void) argType;
  423. if(!SMethodInfo)
  424. SMethodInfo = NewHash();
  425. if (debugMode)
  426. Printf(stdout, "[addMethodInfo] %s\n", name);
  427. Hash *tb = Getattr(SMethodInfo, name);
  428. if(!tb) {
  429. tb = NewHash();
  430. Setattr(SMethodInfo, name, tb);
  431. }
  432. String *str = Getattr(tb, "max");
  433. int max = -1;
  434. if(str)
  435. max = atoi(Char(str));
  436. if(max < nargs) {
  437. if(str) Delete(str);
  438. str = NewStringf("%d", max);
  439. Setattr(tb, "max", str);
  440. }
  441. }
  442. /*
  443. Returns the name of the new routine.
  444. */
  445. String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
  446. String *funName = SwigType_manglestr(t);
  447. /* See if we have already processed this one. */
  448. if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName))
  449. return funName;
  450. if (debugMode)
  451. Printf(stdout, "<createFunctionPointerHandler> Defining %s\n", t);
  452. SwigType *rettype = Copy(Getattr(n, "type"));
  453. SwigType *funcparams = SwigType_functionpointer_decompose(rettype);
  454. String *rtype = SwigType_str(rettype, 0);
  455. // ParmList *parms = Getattr(n, "parms");
  456. // memory leak
  457. ParmList *parms = SwigType_function_parms(SwigType_del_pointer(Copy(t)), n);
  458. if (debugMode) {
  459. Printf(stdout, "Type: %s\n", t);
  460. Printf(stdout, "Return type: %s\n", SwigType_base(t));
  461. }
  462. bool isVoidType = Strcmp(rettype, "void") == 0;
  463. if (debugMode)
  464. Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype);
  465. Wrapper *f = NewWrapper();
  466. /* Go through argument list, attach lnames for arguments */
  467. int i = 0;
  468. Parm *p = parms;
  469. for (i = 0; p; p = nextSibling(p), ++i) {
  470. String *arg = Getattr(p, "name");
  471. String *lname = NewString("");
  472. if (!arg && Cmp(Getattr(p, "type"), "void")) {
  473. lname = NewStringf("s_arg%d", i+1);
  474. Setattr(p, "name", lname);
  475. } else
  476. lname = arg;
  477. Setattr(p, "lname", lname);
  478. }
  479. Swig_typemap_attach_parms("out", parms, f);
  480. Swig_typemap_attach_parms("scoerceout", parms, f);
  481. Swig_typemap_attach_parms("scheck", parms, f);
  482. Printf(f->def, "%s %s(", rtype, funName);
  483. emit_parameter_variables(parms, f);
  484. emit_return_variable(n, rettype, f);
  485. // emit_attach_parmmaps(parms,f);
  486. /* Using weird name and struct to avoid potential conflicts. */
  487. Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()");
  488. String *lvar = NewString("r_swig_cb_data");
  489. Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call.
  490. Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call.
  491. Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call.
  492. // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap
  493. // whereas the type makes are reverse
  494. Wrapper_add_local(f, "ecode", "int ecode = 0");
  495. p = parms;
  496. int nargs = ParmList_len(parms);
  497. if(numArgs) {
  498. *numArgs = nargs;
  499. if (debugMode)
  500. Printf(stdout, "Setting number of parameters to %d\n", *numArgs);
  501. }
  502. String *setExprElements = NewString("");
  503. String *s_paramTypes = NewString("");
  504. for(i = 0; p; i++) {
  505. SwigType *tt = Getattr(p, "type");
  506. SwigType *name = Getattr(p, "name");
  507. String *tm = Getattr(p, "tmap:out");
  508. Printf(f->def, "%s %s", SwigType_str(tt, 0), name);
  509. if(tm) {
  510. Replaceall(tm, "$1", name);
  511. if (SwigType_isreference(tt)) {
  512. String *tmp = NewString("");
  513. Append(tmp, "*");
  514. Append(tmp, name);
  515. Replaceall(tm, tmp, name);
  516. }
  517. Replaceall(tm, "$result", "r_tmp");
  518. replaceRClass(tm, Getattr(p,"type"));
  519. Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
  520. }
  521. Printf(setExprElements, "%s\n", tm);
  522. Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp");
  523. Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
  524. Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt));
  525. p = nextSibling(p);
  526. if(p) {
  527. Printf(f->def, ", ");
  528. Printf(s_paramTypes, ", ");
  529. }
  530. }
  531. Printf(f->def, ") {\n");
  532. Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1);
  533. Printf(f->code, "r_nprotect++;\n");
  534. Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n");
  535. Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n");
  536. Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
  537. Printf(f->code, "%s\n\n", setExprElements);
  538. Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(",
  539. "r_swig_cb_data->expr,",
  540. " R_GlobalEnv,",
  541. " &r_swig_cb_data->errorOccurred",
  542. ");\n",
  543. NIL);
  544. Printv(f->code, "\n",
  545. "if(r_swig_cb_data->errorOccurred) {\n",
  546. "R_SWIG_popCallbackFunctionData(1);\n",
  547. "Rf_error(\"error in calling R function as a function pointer (",
  548. funName,
  549. ")\");\n",
  550. "}\n",
  551. NIL);
  552. if(!isVoidType) {
  553. /* Need to deal with the return type of the function pointer, not the function pointer itself.
  554. So build a new node that has the relevant pieces.
  555. XXX Have to be a little more clever so that we can deal with struct A * - the * is getting lost.
  556. Is this still true? If so, will a SwigType_push() solve things?
  557. */
  558. Parm *bbase = NewParm(rettype, Swig_cresult_name(), n);
  559. String *returnTM = Swig_typemap_lookup("in", bbase, Swig_cresult_name(), f);
  560. if(returnTM) {
  561. String *tm = returnTM;
  562. Replaceall(tm,"$input", "r_swig_cb_data->retValue");
  563. Replaceall(tm,"$target", Swig_cresult_name());
  564. replaceRClass(tm, rettype);
  565. Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
  566. Replaceall(tm,"$disown","0");
  567. Printf(f->code, "%s\n", tm);
  568. }
  569. Delete(bbase);
  570. }
  571. Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL);
  572. Printv(f->code, "\n", UnProtectWrapupCode, NIL);
  573. if (SwigType_isreference(rettype)) {
  574. Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL);
  575. } else if(!isVoidType)
  576. Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL);
  577. Printv(f->code, "\n}\n", NIL);
  578. Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn");
  579. /* To coerce correctly in S, we really want to have an extra/intermediate
  580. function that handles the scoerceout.
  581. We need to check if any of the argument types have an entry in
  582. that map. If none do, the ignore and call the function straight.
  583. Otherwise, generate the a marshalling function.
  584. Need to be able to find it in S. Or use an entirely generic one
  585. that evaluates the expressions.
  586. Handle errors in the evaluation of the function by restoring
  587. the stack, if there is one in use for this function (i.e. no
  588. userData).
  589. */
  590. Wrapper_print(f, f_wrapper);
  591. addFunctionPointerProxy(funName, n, t, s_paramTypes);
  592. Delete(s_paramTypes);
  593. Delete(rtype);
  594. Delete(rettype);
  595. Delete(funcparams);
  596. return funName;
  597. }
  598. void R::init() {
  599. UnProtectWrapupCode =
  600. NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n");
  601. SClassDefs = NewHash();
  602. sfile = NewString("");
  603. f_init = NewString("");
  604. s_header = NewString("");
  605. f_begin = NewString("");
  606. f_runtime = NewString("");
  607. f_wrapper = NewString("");
  608. s_classes = NewString("");
  609. s_init = NewString("");
  610. s_init_routine = NewString("");
  611. }
  612. #if 0
  613. int R::cDeclaration(Node *n) {
  614. SwigType *t = Getattr(n, "type");
  615. SwigType *name = Getattr(n, "name");
  616. if (debugMode)
  617. Printf(stdout, "cDeclaration (%s): %s\n", name, SwigType_lstr(t, 0));
  618. return Language::cDeclaration(n);
  619. }
  620. #endif
  621. /**
  622. Method from Language that is called to start the entire
  623. processing off, i.e. the generation of the code.
  624. It is called after the input has been read and parsed.
  625. Here we open the output streams and generate the code.
  626. ***/
  627. int R::top(Node *n) {
  628. String *module = Getattr(n, "name");
  629. if(!Rpackage)
  630. Rpackage = Copy(module);
  631. if(!DllName)
  632. DllName = Copy(module);
  633. if(outputNamespaceInfo) {
  634. s_namespace = NewString("");
  635. Swig_register_filebyname("snamespace", s_namespace);
  636. Printf(s_namespace, "useDynLib(%s)\n", DllName);
  637. }
  638. /* Associate the different streams with names so that they can be used in %insert directives by the
  639. typemap code. */
  640. Swig_register_filebyname("sinit", s_init);
  641. Swig_register_filebyname("sinitroutine", s_init_routine);
  642. Swig_register_filebyname("begin", f_begin);
  643. Swig_register_filebyname("runtime", f_runtime);
  644. Swig_register_filebyname("init", f_init);
  645. Swig_register_filebyname("header", s_header);
  646. Swig_register_filebyname("wrapper", f_wrapper);
  647. Swig_register_filebyname("s", sfile);
  648. Swig_register_filebyname("sclasses", s_classes);
  649. Swig_banner(f_begin);
  650. Printf(f_runtime, "\n");
  651. Printf(f_runtime, "#define SWIGR\n");
  652. Printf(f_runtime, "\n");
  653. Swig_banner_target_lang(s_init, "#");
  654. outputCommandLineArguments(s_init);
  655. Printf(f_wrapper, "#ifdef __cplusplus\n");
  656. Printf(f_wrapper, "extern \"C\" {\n");
  657. Printf(f_wrapper, "#endif\n\n");
  658. Language::top(n);
  659. Printf(f_wrapper, "#ifdef __cplusplus\n");
  660. Printf(f_wrapper, "}\n");
  661. Printf(f_wrapper, "#endif\n");
  662. String *type_table = NewString("");
  663. SwigType_emit_type_table(f_runtime,f_wrapper);
  664. Delete(type_table);
  665. if(ClassMemberTable) {
  666. //XXX OutputClassAccessInfo(ClassMemberTable, sfile);
  667. Delete(ClassMemberTable);
  668. ClassMemberTable = NULL;
  669. }
  670. Printf(f_init,"}\n");
  671. if(registrationTable)
  672. outputRegistrationRoutines(f_init);
  673. /* Now arrange to write the 2 files - .S and .c. */
  674. DumpCode(n);
  675. Delete(sfile);
  676. Delete(s_classes);
  677. Delete(s_init);
  678. Delete(f_wrapper);
  679. Delete(f_init);
  680. Delete(s_header);
  681. Close(f_begin);
  682. Delete(f_runtime);
  683. Delete(f_begin);
  684. return SWIG_OK;
  685. }
  686. /*****************************************************
  687. Write the generated code to the .S and the .c files.
  688. ****************************************************/
  689. int R::DumpCode(Node *n) {
  690. String *output_filename = NewString("");
  691. /* The name of the file in which we will generate the S code. */
  692. Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage);
  693. #ifdef R_SWIG_VERBOSE
  694. Printf(stdout, "Writing S code to %s\n", output_filename);
  695. #endif
  696. File *scode = NewFile(output_filename, "w", SWIG_output_files());
  697. if (!scode) {
  698. FileErrorDisplay(output_filename);
  699. SWIG_exit(EXIT_FAILURE);
  700. }
  701. Delete(output_filename);
  702. Printf(scode, "%s\n\n", s_init);
  703. Printf(scode, "%s\n\n", s_classes);
  704. Printf(scode, "%s\n", sfile);
  705. Close(scode);
  706. // Delete(scode);
  707. String *outfile = Getattr(n,"outfile");
  708. File *runtime = NewFile(outfile,"w", SWIG_output_files());
  709. if (!runtime) {
  710. FileErrorDisplay(outfile);
  711. SWIG_exit(EXIT_FAILURE);
  712. }
  713. Printf(runtime, "%s", f_begin);
  714. Printf(runtime, "%s\n", f_runtime);
  715. Printf(runtime, "%s\n", s_header);
  716. Printf(runtime, "%s\n", f_wrapper);
  717. Printf(runtime, "%s\n", f_init);
  718. Close(runtime);
  719. Delete(runtime);
  720. if(outputNamespaceInfo) {
  721. output_filename = NewString("");
  722. Printf(output_filename, "%sNAMESPACE", SWIG_output_directory());
  723. File *ns = NewFile(output_filename, "w", SWIG_output_files());
  724. if (!ns) {
  725. FileErrorDisplay(output_filename);
  726. SWIG_exit(EXIT_FAILURE);
  727. }
  728. Delete(output_filename);
  729. Printf(ns, "%s\n", s_namespace);
  730. Printf(ns, "\nexport(\n");
  731. writeListByLine(namespaceFunctions, ns);
  732. Printf(ns, ")\n");
  733. Printf(ns, "\nexportMethods(\n");
  734. writeListByLine(namespaceFunctions, ns, 1);
  735. Printf(ns, ")\n");
  736. Close(ns);
  737. Delete(ns);
  738. Delete(s_namespace);
  739. }
  740. return SWIG_OK;
  741. }
  742. /*
  743. We may need to do more.... so this is left as a
  744. stub for the moment.
  745. */
  746. int R::OutputClassAccessInfo(Hash *tb, File *out) {
  747. int n = OutputClassMemberTable(tb, out);
  748. OutputClassMethodsTable(out);
  749. return n;
  750. }
  751. /************************************************************************
  752. Currently this just writes the information collected about the
  753. different methods of the C++ classes that have been processed
  754. to the console.
  755. This will be used later to define S4 generics and methods.
  756. **************************************************************************/
  757. int R::OutputClassMethodsTable(File *) {
  758. Hash *tb = ClassMethodsTable;
  759. if(!tb)
  760. return SWIG_OK;
  761. List *keys = Keys(tb);
  762. String *key;
  763. int i, n = Len(keys);
  764. if (debugMode) {
  765. for(i = 0; i < n ; i++ ) {
  766. key = Getitem(keys, i);
  767. Printf(stdout, "%d) %s\n", i, key);
  768. List *els = Getattr(tb, key);
  769. int nels = Len(els);
  770. Printf(stdout, "\t");
  771. for(int j = 0; j < nels; j+=2) {
  772. Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : "");
  773. Printf(stdout, "%s\n", Getitem(els, j+1));
  774. }
  775. Printf(stdout, "\n");
  776. }
  777. }
  778. return SWIG_OK;
  779. }
  780. /*
  781. Iterate over the <class name>_set and <>_get
  782. elements and generate the $ and $<- functions
  783. that provide constrained access to the member
  784. fields in these elements.
  785. tb - a hash table that is built up in functionWrapper
  786. as we process each membervalueHandler.
  787. The entries are indexed by <class name>_set and
  788. <class_name>_get. Each entry is a List *.
  789. out - the stram where the code is to be written. This is the S
  790. code stream as we generate only S code here..
  791. */
  792. int R::OutputClassMemberTable(Hash *tb, File *out) {
  793. List *keys = Keys(tb), *el;
  794. String *key;
  795. int i, n = Len(keys);
  796. /* Loop over all the <Class>_set and <Class>_get entries in the table. */
  797. if(n && outputNamespaceInfo) {
  798. Printf(s_namespace, "exportClasses(");
  799. }
  800. for(i = 0; i < n; i++) {
  801. key = Getitem(keys, i);
  802. el = Getattr(tb, key);
  803. String *className = Getitem(el, 0);
  804. char *ptr = Char(key);
  805. ptr = &ptr[Len(key) - 3];
  806. int isSet = strcmp(ptr, "set") == 0;
  807. // OutputArrayMethod(className, el, out);
  808. OutputMemberReferenceMethod(className, isSet, el, out);
  809. if(outputNamespaceInfo)
  810. Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : "");
  811. }
  812. if(n && outputNamespaceInfo) {
  813. Printf(s_namespace, ")\n");
  814. }
  815. return n;
  816. }
  817. /*******************************************************************
  818. Write the methods for $ or $<- for accessing a member field in an
  819. struct or union (or class).
  820. className - the name of the struct or union (e.g. Bar for struct Bar)
  821. isSet - a logical value indicating whether the method is for
  822. modifying ($<-) or accessing ($) the member field.
  823. el - a list of length 2 * # accessible member elements + 1.
  824. The first element is the name of the class.
  825. The other pairs are member name and the name of the R function to access it.
  826. out - the stream where we write the code.
  827. ********************************************************************/
  828. int R::OutputMemberReferenceMethod(String *className, int isSet,
  829. List *el, File *out) {
  830. int numMems = Len(el), j;
  831. int varaccessor = 0;
  832. if (numMems == 0)
  833. return SWIG_OK;
  834. Wrapper *f = NewWrapper(), *attr = NewWrapper();
  835. Printf(f->def, "function(x, name%s)", isSet ? ", value" : "");
  836. Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : "");
  837. Printf(f->code, "{\n");
  838. Printf(f->code, "%saccessorFuns = list(", tab8);
  839. Node *itemList = NewHash();
  840. bool has_prev = false;
  841. for(j = 0; j < numMems; j+=3) {
  842. String *item = Getitem(el, j);
  843. if (Getattr(itemList, item))
  844. continue;
  845. Setattr(itemList, item, "1");
  846. String *dup = Getitem(el, j + 1);
  847. char *ptr = Char(dup);
  848. ptr = &ptr[Len(dup) - 3];
  849. if (!strcmp(ptr, "get"))
  850. varaccessor++;
  851. String *pitem;
  852. if (!Strcmp(item, "operator ()")) {
  853. pitem = NewString("call");
  854. } else if (!Strcmp(item, "operator ->")) {
  855. pitem = NewString("deref");
  856. } else if (!Strcmp(item, "operator +")) {
  857. pitem = NewString("add");
  858. } else if (!Strcmp(item, "operator -")) {
  859. pitem = NewString("sub");
  860. } else {
  861. pitem = Copy(item);
  862. }
  863. if (has_prev)
  864. Printf(f->code, ", ");
  865. Printf(f->code, "'%s' = %s", pitem, dup);
  866. has_prev = true;
  867. Delete(pitem);
  868. }
  869. Delete(itemList);
  870. Printf(f->code, ");\n");
  871. if (!isSet && varaccessor > 0) {
  872. Printf(f->code, "%svaccessors = c(", tab8);
  873. int vcount = 0;
  874. for(j = 0; j < numMems; j+=3) {
  875. String *item = Getitem(el, j);
  876. String *dup = Getitem(el, j + 1);
  877. char *ptr = Char(dup);
  878. ptr = &ptr[Len(dup) - 3];
  879. if (!strcmp(ptr, "get")) {
  880. vcount++;
  881. Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : "");
  882. }
  883. }
  884. Printf(f->code, ");\n");
  885. }
  886. /* Printv(f->code, tab8,
  887. "idx = pmatch(name, names(accessorFuns))\n",
  888. tab8,
  889. "if(is.na(idx)) {\n",
  890. tab8, tab4,
  891. "stop(\"No ", (isSet ? "modifiable" : "accessible"), " field named \", name, \" in ", className,
  892. ": fields are \", paste(names(accessorFuns), sep = \", \")",
  893. ")", "\n}\n", NIL); */
  894. Printv(f->code, ";", tab8,
  895. "idx = pmatch(name, names(accessorFuns));\n",
  896. tab8,
  897. "if(is.na(idx)) \n",
  898. tab8, tab4, NIL);
  899. Printf(f->code, "return(callNextMethod(x, name%s));\n",
  900. isSet ? ", value" : "");
  901. Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL);
  902. if(isSet) {
  903. Printv(f->code, tab8, "f(x, value);\n", NIL);
  904. Printv(f->code, tab8, "x;\n", NIL); // make certain to return the S value.
  905. } else {
  906. if (varaccessor) {
  907. Printv(f->code, tab8,
  908. "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL);
  909. } else {
  910. Printv(f->code, tab8, "function(...){f(x, ...)};\n", NIL);
  911. }
  912. }
  913. Printf(f->code, "}\n");
  914. Printf(out, "# Start of accessor method for %s\n", className);
  915. Printf(out, "setMethod('$%s', '_p%s', ",
  916. isSet ? "<-" : "",
  917. getRClassName(className));
  918. Wrapper_print(f, out);
  919. Printf(out, ");\n");
  920. if(isSet) {
  921. Printf(out, "setMethod('[[<-', c('_p%s', 'character'),",
  922. getRClassName(className));
  923. Insert(f->code, 2, "name = i;\n");
  924. Printf(attr->code, "%s", f->code);
  925. Wrapper_print(attr, out);
  926. Printf(out, ");\n");
  927. }
  928. DelWrapper(attr);
  929. DelWrapper(f);
  930. Printf(out, "# end of accessor method for %s\n", className);
  931. return SWIG_OK;
  932. }
  933. /*******************************************************************
  934. Write the methods for [ or [<- for accessing a member field in an
  935. struct or union (or class).
  936. className - the name of the struct or union (e.g. Bar for struct Bar)
  937. el - a list of length 2 * # accessible member elements + 1.
  938. The first element is the name of the class.
  939. The other pairs are member name and the name of the R function to access it.
  940. out - the stream where we write the code.
  941. ********************************************************************/
  942. int R::OutputArrayMethod(String *className, List *el, File *out) {
  943. int numMems = Len(el), j;
  944. if(!el || numMems == 0)
  945. return(0);
  946. Printf(out, "# start of array methods for %s\n", className);
  947. for(j = 0; j < numMems; j+=3) {
  948. String *item = Getitem(el, j);
  949. String *dup = Getitem(el, j + 1);
  950. if (!Strcmp(item, "__getitem__")) {
  951. Printf(out,
  952. "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ",
  953. getRClassName(className));
  954. Printf(out, " sapply(i, function (n) %s(x, as.integer(n-1))))\n\n", dup);
  955. }
  956. if (!Strcmp(item, "__setitem__")) {
  957. Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)",
  958. getRClassName(className));
  959. Printf(out, " sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup);
  960. }
  961. }
  962. Printf(out, "# end of array methods for %s\n", className);
  963. return SWIG_OK;
  964. }
  965. /************************************************************
  966. Called when a enumeration is to be processed.
  967. We want to call the R function defineEnumeration().
  968. tdname is the typedef of the enumeration, i.e. giving its name.
  969. *************************************************************/
  970. int R::enumDeclaration(Node *n) {
  971. String *name = Getattr(n, "name");
  972. String *tdname = Getattr(n, "tdname");
  973. /* Using name if tdname is empty. */
  974. if(Len(tdname) == 0)
  975. tdname = name;
  976. if(!tdname || Strcmp(tdname, "") == 0) {
  977. Language::enumDeclaration(n);
  978. return SWIG_OK;
  979. }
  980. String *mangled_tdname = SwigType_manglestr(tdname);
  981. String *scode = NewString("");
  982. Printv(scode, "defineEnumeration('", mangled_tdname, "'",
  983. ",\n", tab8, tab8, tab4, ".values = c(\n", NIL);
  984. Node *c;
  985. int value = -1; // First number is zero
  986. for (c = firstChild(n); c; c = nextSibling(c)) {
  987. // const char *tag = Char(nodeType(c));
  988. // if (Strcmp(tag,"cdecl") == 0) {
  989. name = Getattr(c, "name");
  990. String *val = Getattr(c, "enumvalue");
  991. if(val && Char(val)) {
  992. int inval = (int) getNumber(val);
  993. if(inval == DEFAULT_NUMBER)
  994. value++;
  995. else
  996. value = inval;
  997. } else
  998. value++;
  999. Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value,
  1000. nextSibling(c) ? ", " : "");
  1001. // }
  1002. }
  1003. Printv(scode, "))", NIL);
  1004. Printf(sfile, "%s\n", scode);
  1005. Delete(scode);
  1006. Delete(mangled_tdname);
  1007. return SWIG_OK;
  1008. }
  1009. /*************************************************************
  1010. **************************************************************/
  1011. int R::variableWrapper(Node *n) {
  1012. String *name = Getattr(n, "sym:name");
  1013. processing_variable = 1;
  1014. Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
  1015. processing_variable = 0;
  1016. SwigType *ty = Getattr(n, "type");
  1017. int addCopyParam = addCopyParameter(ty);
  1018. //XXX
  1019. processType(ty, n);
  1020. if(!SwigType_isconst(ty)) {
  1021. Wrapper *f = NewWrapper();
  1022. Printf(f->def, "%s = \nfunction(value%s)\n{\n",
  1023. name, addCopyParam ? ", .copy = FALSE" : "");
  1024. Printv(f->code, "if(missing(value)) {\n",
  1025. name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL);
  1026. Printv(f->code, " else {\n",
  1027. name, "_set(value)\n}\n}", NIL);
  1028. Wrapper_print(f, sfile);
  1029. DelWrapper(f);
  1030. } else {
  1031. Printf(sfile, "%s = %s_get\n", name, name);
  1032. }
  1033. return SWIG_OK;
  1034. }
  1035. void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
  1036. int isSet) {
  1037. if(isSet < 0) {
  1038. int n = Len(name);
  1039. char *ptr = Char(name);
  1040. isSet = Strcmp(NewString(&ptr[n-3]), "set") == 0;
  1041. }
  1042. List *l = isSet ? class_member_set_functions : class_member_functions;
  1043. if(!l) {
  1044. l = NewList();
  1045. if(isSet)
  1046. class_member_set_functions = l;
  1047. else
  1048. class_member_functions = l;
  1049. }
  1050. Append(l, memberName);
  1051. Append(l, name);
  1052. String *tmp = NewString("");
  1053. Wrapper_print(wrapper, tmp);
  1054. Append(l, tmp);
  1055. // if we could put the wrapper in directly: Append(l, Copy(sfun));
  1056. if (debugMode)
  1057. Printf(stdout, "Adding accessor: %s (%s) => %s\n", memberName, name, tmp);
  1058. }
  1059. #define MAX_OVERLOAD 256
  1060. struct Overloaded {
  1061. Node *n; /* Node */
  1062. int argc; /* Argument count */
  1063. ParmList *parms; /* Parameters used for overload check */
  1064. int error; /* Ambiguity error */
  1065. };
  1066. List * R::Swig_overload_rank(Node *n,
  1067. bool script_lang_wrapping) {
  1068. Overloaded nodes[MAX_OVERLOAD];
  1069. int nnodes = 0;
  1070. Node *o = Getattr(n,"sym:overloaded");
  1071. if (!o) return 0;
  1072. Node *c = o;
  1073. while (c) {
  1074. if (Getattr(c,"error")) {
  1075. c = Getattr(c,"sym:nextSibling");
  1076. continue;
  1077. }
  1078. /* if (SmartPointer && Getattr(c,"cplus:staticbase")) {
  1079. c = Getattr(c,"sym:nextSibling");
  1080. continue;
  1081. } */
  1082. /* Make a list of all the declarations (methods) that are overloaded with
  1083. * this one particular method name */
  1084. if (Getattr(c,"wrap:name")) {
  1085. nodes[nnodes].n = c;
  1086. nodes[nnodes].parms = Getattr(c,"wrap:parms");
  1087. nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
  1088. nodes[nnodes].error = 0;
  1089. nnodes++;
  1090. }
  1091. c = Getattr(c,"sym:nextSibling");
  1092. }
  1093. /* Sort the declarations by required argument count */
  1094. {
  1095. int i,j;
  1096. for (i = 0; i < nnodes; i++) {
  1097. for (j = i+1; j < nnodes; j++) {
  1098. if (nodes[i].argc > nodes[j].argc) {
  1099. Overloaded t = nodes[i];
  1100. nodes[i] = nodes[j];
  1101. nodes[j] = t;
  1102. }
  1103. }
  1104. }
  1105. }
  1106. /* Sort the declarations by argument types */
  1107. {
  1108. int i,j;
  1109. for (i = 0; i < nnodes-1; i++) {
  1110. if (nodes[i].argc == nodes[i+1].argc) {
  1111. for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
  1112. Parm *p1 = nodes[i].parms;
  1113. Parm *p2 = nodes[j].parms;
  1114. int differ = 0;
  1115. int num_checked = 0;
  1116. while (p1 && p2 && (num_checked < nodes[i].argc)) {
  1117. if (debugMode) {
  1118. Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
  1119. }
  1120. if (checkAttribute(p1,"tmap:in:numinputs","0")) {
  1121. p1 = Getattr(p1,"tmap:in:next");
  1122. continue;
  1123. }
  1124. if (checkAttribute(p2,"tmap:in:numinputs","0")) {
  1125. p2 = Getattr(p2,"tmap:in:next");
  1126. continue;
  1127. }
  1128. String *t1 = Getattr(p1,"tmap:typecheck:precedence");
  1129. String *t2 = Getattr(p2,"tmap:typecheck:precedence");
  1130. if (debugMode) {
  1131. Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2);
  1132. }
  1133. if ((!t1) && (!nodes[i].error)) {
  1134. Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
  1135. "Overloaded method %s not supported (no type checking rule for '%s').\n",
  1136. Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
  1137. nodes[i].error = 1;
  1138. } else if ((!t2) && (!nodes[j].error)) {
  1139. Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
  1140. "xx Overloaded method %s not supported (no type checking rule for '%s').\n",
  1141. Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
  1142. nodes[j].error = 1;
  1143. }
  1144. if (t1 && t2) {
  1145. int t1v, t2v;
  1146. t1v = atoi(Char(t1));
  1147. t2v = atoi(Char(t2));
  1148. differ = t1v-t2v;
  1149. }
  1150. else if (!t1 && t2) differ = 1;
  1151. else if (t1 && !t2) differ = -1;
  1152. else if (!t1 && !t2) differ = -1;
  1153. num_checked++;
  1154. if (differ > 0) {
  1155. Overloaded t = nodes[i];
  1156. nodes[i] = nodes[j];
  1157. nodes[j] = t;
  1158. break;
  1159. } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) {
  1160. t1 = Getattr(p1,"ltype");
  1161. if (!t1) {
  1162. t1 = SwigType_ltype(Getattr(p1,"type"));
  1163. if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) {
  1164. SwigType_add_pointer(t1);
  1165. }
  1166. Setattr(p1,"ltype",t1);
  1167. }
  1168. t2 = Getattr(p2,"ltype");
  1169. if (!t2) {
  1170. t2 = SwigType_ltype(Getattr(p2,"type"));
  1171. if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) {
  1172. SwigType_add_pointer(t2);
  1173. }
  1174. Setattr(p2,"ltype",t2);
  1175. }
  1176. /* Need subtype check here. If t2 is a subtype of t1, then we need to change the
  1177. order */
  1178. if (SwigType_issubtype(t2,t1)) {
  1179. Overloaded t = nodes[i];
  1180. nodes[i] = nodes[j];
  1181. nodes[j] = t;
  1182. }
  1183. if (Strcmp(t1,t2) != 0) {
  1184. differ = 1;
  1185. break;
  1186. }
  1187. } else if (differ) {
  1188. break;
  1189. }
  1190. if (Getattr(p1,"tmap:in:next")) {
  1191. p1 = Getattr(p1,"tmap:in:next");
  1192. } else {
  1193. p1 = nextSibling(p1);
  1194. }
  1195. if (Getattr(p2,"tmap:in:next")) {
  1196. p2 = Getattr(p2,"tmap:in:next");
  1197. } else {
  1198. p2 = nextSibling(p2);
  1199. }
  1200. }
  1201. if (!differ) {
  1202. /* See if declarations differ by const only */
  1203. String *d1 = Getattr(nodes[i].n, "decl");
  1204. String *d2 = Getattr(nodes[j].n, "decl");
  1205. if (d1 && d2) {
  1206. String *dq1 = Copy(d1);
  1207. String *dq2 = Copy(d2);
  1208. if (SwigType_isconst(d1)) {
  1209. Delete(SwigType_pop(dq1));
  1210. }
  1211. if (SwigType_isconst(d2)) {
  1212. Delete(SwigType_pop(dq2));
  1213. }
  1214. if (Strcmp(dq1, dq2) == 0) {
  1215. if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
  1216. if (script_lang_wrapping) {
  1217. // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
  1218. Overloaded t = nodes[i];
  1219. nodes[i] = nodes[j];
  1220. nodes[j] = t;
  1221. }
  1222. differ = 1;
  1223. if (!nodes[j].error) {
  1224. if (script_lang_wrapping) {
  1225. Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
  1226. "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
  1227. Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
  1228. "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
  1229. } else {
  1230. if (!Getattr(nodes[j].n, "overload:ignore"))
  1231. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
  1232. "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
  1233. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
  1234. "using %s instead.\n", Swig_name_decl(nodes[i].n));
  1235. }
  1236. }
  1237. nodes[j].error = 1;
  1238. } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
  1239. differ = 1;
  1240. if (!nodes[j].error) {
  1241. if (script_lang_wrapping) {
  1242. Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
  1243. "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
  1244. Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
  1245. "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
  1246. } else {
  1247. if (!Getattr(nodes[j].n, "overload:ignore"))
  1248. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
  1249. "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
  1250. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
  1251. "using %s instead.\n", Swig_name_decl(nodes[i].n));
  1252. }
  1253. }
  1254. nodes[j].error = 1;
  1255. }
  1256. }
  1257. Delete(dq1);
  1258. Delete(dq2);
  1259. }
  1260. }
  1261. if (!differ) {
  1262. if (!nodes[j].error) {
  1263. if (script_lang_wrapping) {
  1264. Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
  1265. "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
  1266. Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
  1267. "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
  1268. } else {
  1269. if (!Getattr(nodes[j].n, "overload:ignore"))
  1270. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
  1271. "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
  1272. Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
  1273. "using %s instead.\n", Swig_name_decl(nodes[i].n));
  1274. }
  1275. nodes[j].error = 1;
  1276. }
  1277. }
  1278. }
  1279. }
  1280. }
  1281. }
  1282. List *result = NewList();
  1283. {
  1284. int i;
  1285. for (i = 0; i < nnodes; i++) {
  1286. if (nodes[i].error)
  1287. Setattr(nodes[i].n, "overload:ignore", "1");
  1288. Append(result,nodes[i].n);
  1289. // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms));
  1290. // Swig_print_node(nodes[i].n);
  1291. }
  1292. }
  1293. return result;
  1294. }
  1295. void R::dispatchFunction(Node *n) {
  1296. Wrapper *f = NewWrapper();
  1297. String *symname = Getattr(n, "sym:name");
  1298. String *nodeType = Getattr(n, "nodeType");
  1299. bool constructor = (!Cmp(nodeType, "constructor"));
  1300. String *sfname = NewString(symname);
  1301. if (constructor)
  1302. Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
  1303. Printf(f->def,
  1304. "`%s` <- function(...) {", sfname);
  1305. if (debugMode) {
  1306. Swig_print_node(n);
  1307. }
  1308. List *dispatch = Swig_overload_rank(n, true);
  1309. int nfunc = Len(dispatch);
  1310. Printv(f->code,
  1311. "argtypes <- mapply(class, list(...));\n",
  1312. "argv <- list(...);\n",
  1313. "argc <- length(argtypes);\n", NIL );
  1314. Printf(f->code, "# dispatch functions %d\n", nfunc);
  1315. int cur_args = -1;
  1316. bool first_compare = true;
  1317. for (int i=0; i < nfunc; i++) {
  1318. Node *ni = Getitem(dispatch,i);
  1319. Parm *pi = Getattr(ni,"wrap:parms");
  1320. int num_arguments = emit_num_arguments(pi);
  1321. String *overname = Getattr(ni,"sym:overname");
  1322. if (cur_args != num_arguments) {
  1323. if (cur_args != -1) {
  1324. Printv(f->code, "} else ", NIL);
  1325. }
  1326. Printf(f->code, "if (argc == %d) {", num_arguments);
  1327. cur_args = num_arguments;
  1328. first_compare = true;
  1329. }
  1330. Parm *p;
  1331. int j;
  1332. if (num_arguments > 0) {
  1333. if (!first_compare) {
  1334. Printv(f->code, " else ", NIL);
  1335. } else {
  1336. first_compare = false;
  1337. }
  1338. Printv(f->code, "if (", NIL);
  1339. for (p =pi, j = 0 ; j < num_arguments ; j++) {
  1340. if (debugMode) {
  1341. Swig_print_node(p);
  1342. }
  1343. String *tm = Swig_typemap_lookup("rtype", p, "", 0);
  1344. if(tm) {
  1345. replaceRClass(tm, Getattr(p, "type"));
  1346. }
  1347. String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0);
  1348. if (tmcheck) {
  1349. String *tmp = NewString("");
  1350. Printf(tmp, "argv[[%d]]", j+1);
  1351. Replaceall(tmcheck, "$arg", tmp);
  1352. Printf(tmp, "argtype[%d]", j+1);
  1353. Replaceall(tmcheck, "$argtype", tmp);
  1354. if (tm) {
  1355. Replaceall(tmcheck, "$rtype", tm);
  1356. }
  1357. if (debugMode) {
  1358. Printf(stdout, "<rtypecheck>%s\n", tmcheck);
  1359. }
  1360. Printf(f->code, "%s(%s)",
  1361. j == 0? "" : " && ",
  1362. tmcheck);
  1363. p = Getattr(p, "tmap:in:next");
  1364. continue;
  1365. }
  1366. if (DohStrcmp(tm,"numeric")==0) {
  1367. Printf(f->code, "%sis.numeric(argv[[%d]])",
  1368. j == 0 ? "" : " && ",
  1369. j+1);
  1370. }
  1371. else if (DohStrcmp(tm,"integer")==0) {
  1372. Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))",
  1373. j == 0 ? "" : " && ",
  1374. j+1, j+1);
  1375. }
  1376. else if (DohStrcmp(tm,"character")==0) {
  1377. Printf(f->code, "%sis.character(argv[[%d]])",
  1378. j == 0 ? "" : " && ",
  1379. j+1);
  1380. }
  1381. else {
  1382. Printf(f->code, "%sextends(argtypes[%d], '%s')",
  1383. j == 0 ? "" : " && ",
  1384. j+1,
  1385. tm);
  1386. }
  1387. if (!SwigType_ispointer(Getattr(p, "type"))) {
  1388. Printf(f->code, " && length(argv[[%d]]) == 1",
  1389. j+1);
  1390. }
  1391. p = Getattr(p, "tmap:in:next");
  1392. }
  1393. Printf(f->code, ") { f <- %s%s; }\n", sfname, overname);
  1394. } else {
  1395. Printf(f->code, "f <- %s%s; ", sfname, overname);
  1396. }
  1397. }
  1398. if (cur_args != -1) {
  1399. Printf(f->code, "} else {\n"
  1400. "stop(\"cannot find overloaded function for %s with argtypes (\","
  1401. "toString(argtypes),\")\");\n"
  1402. "}", sfname);
  1403. }
  1404. Printv(f->code, ";\nf(...)", NIL);
  1405. Printv(f->code, ";\n}", NIL);
  1406. Wrapper_print(f, sfile);
  1407. Printv(sfile, "# Dispatch function\n", NIL);
  1408. DelWrapper(f);
  1409. }
  1410. /******************************************************************
  1411. *******************************************************************/
  1412. int R::functionWrapper(Node *n) {
  1413. String *fname = Getattr(n, "name");
  1414. String *iname = Getattr(n, "sym:name");
  1415. String *type = Getattr(n, "type");
  1416. if (debugMode) {
  1417. Printf(stdout,
  1418. "<functionWrapper> %s %s %s\n", fname, iname, type);
  1419. }
  1420. String *overname = 0;
  1421. String *nodeType = Getattr(n, "nodeType");
  1422. bool constructor = (!Cmp(nodeType, "constructor"));
  1423. bool destructor = (!Cmp(nodeType, "destructor"));
  1424. String *sfname = NewString(iname);
  1425. if (constructor)
  1426. Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
  1427. if (Getattr(n,"sym:overloaded")) {
  1428. overname = Getattr(n,"sym:overname");
  1429. Append(sfname, overname);
  1430. }
  1431. if (debugMode)
  1432. Printf(stdout,
  1433. "<functionWrapper> processing parameters\n");
  1434. ParmList *l = Getattr(n, "parms");
  1435. Parm *p;
  1436. String *tm;
  1437. p = l;
  1438. while(p) {
  1439. SwigType *resultType = Getattr(p, "type");
  1440. if (expandTypedef(resultType) &&
  1441. SwigType_istypedef(resultType)) {
  1442. SwigType *resolved =
  1443. SwigType_typedef_resolve_all(resultType);
  1444. if (expandTypedef(resolved)) {
  1445. Setattr(p, "type", Copy(resolved));
  1446. }
  1447. }
  1448. p = nextSibling(p);
  1449. }
  1450. String *unresolved_return_type =
  1451. Copy(type);
  1452. if (expandTypedef(type) &&
  1453. SwigType_istypedef(type)) {
  1454. SwigType *resolved =
  1455. SwigType_typedef_resolve_all(type);
  1456. if (expandTypedef(resolved)) {
  1457. type = Copy(resolved);
  1458. Setattr(n, "type", type);
  1459. }
  1460. }
  1461. if (debugMode)
  1462. Printf(stdout, "<functionWrapper> unresolved_return_type %s\n",
  1463. unresolved_return_type);
  1464. if(processing_member_access_function) {
  1465. if (debugMode)
  1466. Printf(stdout, "<functionWrapper memberAccess> '%s' '%s' '%s' '%s'\n",
  1467. fname, iname, member_name, class_name);
  1468. if(opaqueClassDeclaration)
  1469. return SWIG_OK;
  1470. /* Add the name of this member to a list for this class_name.
  1471. We will dump all these at the end. */
  1472. int n = Len(iname);
  1473. char *ptr = Char(iname);
  1474. bool isSet(Strcmp(NewString(&ptr[n-3]), "set") == 0);
  1475. String *tmp = NewString("");
  1476. Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get");
  1477. List *memList = Getattr(ClassMemberTable, tmp);
  1478. if(!memList) {
  1479. memList = NewList();
  1480. Append(memList, class_name);
  1481. Setattr(ClassMemberTable, tmp, memList);
  1482. }
  1483. Delete(tmp);
  1484. Append(memList, member_name);
  1485. Append(memList, iname);
  1486. }
  1487. int i;
  1488. int nargs;
  1489. String *wname = Swig_name_wrapper(iname);
  1490. Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST);
  1491. if(overname)
  1492. Append(wname, overname);
  1493. Setattr(n,"wrap:name", wname);
  1494. Wrapper *f = NewWrapper();
  1495. Wrapper *sfun = NewWrapper();
  1496. int isVoidReturnType = (Strcmp(type, "void") == 0);
  1497. // Need to use the unresolved return type since
  1498. // typedef resolution removes the const which causes a
  1499. // mismatch with the function action
  1500. emit_return_variable(n, unresolved_return_type, f);
  1501. SwigType *rtype = Getattr(n, "type");
  1502. int addCopyParam = 0;
  1503. if(!isVoidReturnType)
  1504. addCopyParam = addCopyParameter(rtype);
  1505. // Can we get the nodeType() of the type node! and see if it is a struct.
  1506. // int addCopyParam = SwigType_isclass(rtype);
  1507. // if(addCopyParam)
  1508. if (debugMode)
  1509. Printf(stdout, "Adding a .copy argument to %s for %s = %s\n",
  1510. iname, type, addCopyParam ? "yes" : "no");
  1511. Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL);
  1512. Printf(sfun->def, "# Start of %s\n", iname);
  1513. Printv(sfun->def, "\n`", sfname, "` = function(", NIL);
  1514. if(outputNamespaceInfo) //XXX Need to be a little more discriminating
  1515. addNamespaceFunction(iname);
  1516. Swig_typemap_attach_parms("scoercein", l, f);
  1517. Swig_typemap_attach_parms("scoerceout", l, f);
  1518. Swig_typemap_attach_parms("scheck", l, f);
  1519. emit_parameter_variables(l, f);
  1520. emit_attach_parmmaps(l,f);
  1521. Setattr(n,"wrap:parms",l);
  1522. nargs = emit_num_arguments(l);
  1523. Wrapper_add_local(f, "r_nprotect", "unsigned int r_nprotect = 0");
  1524. Wrapper_add_localv(f, "r_ans", "SEXP", "r_ans = R_NilValue", NIL);
  1525. Wrapper_add_localv(f, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL);
  1526. String *sargs = NewString("");
  1527. String *s_inputTypes = NewString("");
  1528. String *s_inputMap = NewString("");
  1529. bool inFirstArg = true;
  1530. bool inFirstType = true;
  1531. Parm *curP;
  1532. for (p =l, i = 0 ; i < nargs ; i++) {
  1533. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  1534. p = Getattr(p, "tmap:in:next");
  1535. }
  1536. SwigType *tt = Getattr(p, "type");
  1537. int nargs = -1;
  1538. String *funcptr_name = processType(tt, p, &nargs);
  1539. // SwigType *tp = Getattr(p, "type");
  1540. String *name = Getattr(p,"name");
  1541. String *lname = Getattr(p,"lname");
  1542. // R keyword renaming
  1543. if (name && Swig_name_warning(p, 0, name, 0))
  1544. name = 0;
  1545. /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then
  1546. we need to remove that prefix. */
  1547. while (Strstr(name, "::")) {
  1548. //XXX need to free.
  1549. name = NewStringf("%s", Strchr(name, ':') + 2);
  1550. if (debugMode)
  1551. Printf(stdout, "+++ parameter name with :: in it %s\n", name);
  1552. }
  1553. if (Len(name) == 0)
  1554. name = NewStringf("s_arg%d", i+1);
  1555. name = replaceInitialDash(name);
  1556. if (!Strncmp(name, "arg", 3)) {
  1557. name = Copy(name);
  1558. Insert(name, 0, "s_");
  1559. }
  1560. if(processing_variable) {
  1561. name = Copy(name);
  1562. Insert(name, 0, "s_");
  1563. }
  1564. if(!Strcmp(name, fname)) {
  1565. name = Copy(name);
  1566. Insert(name, 0, "s_");
  1567. }
  1568. Printf(sargs, "%s, ", name);
  1569. String *tm;
  1570. if((tm = Getattr(p, "tmap:scoercein"))) {
  1571. Replaceall(tm, "$input", name);
  1572. replaceRClass(tm, Getattr(p, "type"));
  1573. if(funcptr_name) {
  1574. //XXX need to get this to return non-zero
  1575. if(nargs == -1)
  1576. nargs = getFunctionPointerNumArgs(p, tt);
  1577. String *snargs = NewStringf("%d", nargs);
  1578. Printv(sfun->code, "if(is.function(", name, ")) {", "\n",
  1579. "assert('...' %in% names(formals(", name,
  1580. ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL);
  1581. Delete(snargs);
  1582. Printv(sfun->code, "else {\n",
  1583. "if(is.character(", name, ")) {\n",
  1584. name, " = getNativeSymbolInfo(", name, ");",
  1585. "\n};\n",
  1586. "if(is(", name, ", \"NativeSymbolInfo\")) {\n",
  1587. name, " = ", name, "$address", ";\n}\n",
  1588. "}; \n",
  1589. NIL);
  1590. } else {
  1591. Printf(sfun->code, "%s\n", tm);
  1592. }
  1593. }
  1594. Printv(sfun->def, inFirstArg ? "" : ", ", name, NIL);
  1595. if ((tm = Getattr(p,"tmap:scheck"))) {
  1596. Replaceall(tm,"$target", lname);
  1597. Replaceall(tm,"$source", name);
  1598. Replaceall(tm,"$input", name);
  1599. replaceRClass(tm, Getattr(p, "type"));
  1600. Printf(sfun->code,"%s\n",tm);
  1601. }
  1602. curP = p;
  1603. if ((tm = Getattr(p,"tmap:in"))) {
  1604. Replaceall(tm,"$target", lname);
  1605. Replaceall(tm,"$source", name);
  1606. Replaceall(tm,"$input", name);
  1607. if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) {
  1608. Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
  1609. } else {
  1610. Replaceall(tm,"$disown","0");
  1611. }
  1612. if(funcptr_name) {
  1613. /* have us a function pointer */
  1614. Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name);
  1615. Replaceall(tm,"$R_class", "");
  1616. } else {
  1617. replaceRClass(tm, Getattr(p, "type"));
  1618. }
  1619. Printf(f->code,"%s\n",tm);
  1620. if(funcptr_name)
  1621. Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n",
  1622. lname, funcptr_name, name);
  1623. Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL);
  1624. if (Len(name) != 0)
  1625. inFirstArg = false;
  1626. p = Getattr(p,"tmap:in:next");
  1627. } else {
  1628. p = nextSibling(p);
  1629. }
  1630. tm = Swig_typemap_lookup("rtype", curP, "", 0);
  1631. if(tm) {
  1632. replaceRClass(tm, Getattr(curP, "type"));
  1633. }
  1634. Printf(s_inputTypes, "%s'%s'", inFirstType ? "" : ", ", tm);
  1635. Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm);
  1636. inFirstType = false;
  1637. if(funcptr_name)
  1638. Delete(funcptr_name);
  1639. } /* end of looping over parameters. */
  1640. if(addCopyParam) {
  1641. Printf(sfun->def, "%s.copy = FALSE", nargs > 0 ? ", " : "");
  1642. Printf(f->def, "%sSEXP s_swig_copy", nargs > 0 ? ", " : "");
  1643. Printf(sargs, "as.logical(.copy), ");
  1644. }
  1645. Printv(f->def, ")\n{\n", NIL);
  1646. Printv(sfun->def, ")\n{\n", NIL);
  1647. /* Insert cleanup code */
  1648. String *cleanup = NewString("");
  1649. for (p = l; p;) {
  1650. if ((tm = Getattr(p, "tmap:freearg"))) {
  1651. Replaceall(tm, "$source", Getattr(p, "lname"));
  1652. Printv(cleanup, tm, "\n", NIL);
  1653. p = Getattr(p, "tmap:freearg:next");
  1654. } else {
  1655. p = nextSibling(p);
  1656. }
  1657. }
  1658. String *outargs = NewString("");
  1659. int numOutArgs = isVoidReturnType ? -1 : 0;
  1660. for(p = l, i = 0; p; i++) {
  1661. if((tm = Getattr(p, "tmap:argout"))) {
  1662. // String *lname = Getattr(p, "lname");
  1663. numOutArgs++;
  1664. String *pos = NewStringf("%d", numOutArgs);
  1665. Replaceall(tm,"$source", Getattr(p, "lname"));
  1666. Replaceall(tm,"$result", "r_ans");
  1667. Replaceall(tm,"$n", pos); // The position into which to store the answer.
  1668. Replaceall(tm,"$arg", Getattr(p, "emit:input"));
  1669. Replaceall(tm,"$input", Getattr(p, "emit:input"));
  1670. Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
  1671. Printf(outargs, "%s\n", tm);
  1672. p = Getattr(p,"tmap:argout:next");
  1673. } else
  1674. p = nextSibling(p);
  1675. }
  1676. String *actioncode = emit_action(n);
  1677. /* Deal with the explicit return value. */
  1678. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  1679. SwigType *retType = Getattr(n, "type");
  1680. //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");
  1681. /* if(SwigType_isarray(retType)) {
  1682. defineArrayAccessors(retType);
  1683. } */
  1684. Replaceall(tm,"$1", Swig_cresult_name());
  1685. Replaceall(tm,"$result", "r_ans");
  1686. replaceRClass(tm, retType);
  1687. if (GetFlag(n,"feature:new")) {
  1688. Replaceall(tm, "$owner", "R_SWIG_OWNER");
  1689. } else {
  1690. Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
  1691. }
  1692. #if 0
  1693. if(addCopyParam) {
  1694. Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n");
  1695. Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n");
  1696. Printf(f->code, "}\n else {\n");
  1697. }
  1698. #endif
  1699. Printf(f->code, "%s\n", tm);
  1700. #if 0
  1701. if(addCopyParam)
  1702. Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */
  1703. #endif
  1704. } else {
  1705. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
  1706. "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), fname);
  1707. }
  1708. if(Len(outargs)) {
  1709. Wrapper_add_local(f, "R_OutputValues", "SEXP R_OutputValues");
  1710. String *tmp = NewString("");
  1711. if(!isVoidReturnType)
  1712. Printf(tmp, "Rf_protect(r_ans);\n");
  1713. Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n",
  1714. numOutArgs + !isVoidReturnType,
  1715. isVoidReturnType ? 1 : 2);
  1716. if(!isVoidReturnType)
  1717. Printf(tmp, "SET_VECTOR_ELT(R_OutputValues, 0, r_ans);\n");
  1718. Printf(tmp, "r_ans = R_OutputValues;\n");
  1719. Insert(outargs, 0, tmp);
  1720. Delete(tmp);
  1721. Printv(f->code, outargs, NIL);
  1722. Delete(outargs);
  1723. }
  1724. /* Output cleanup code */
  1725. Printv(f->code, cleanup, NIL);
  1726. Delete(cleanup);
  1727. /* Look to see if there is any newfree cleanup code */
  1728. if (GetFlag(n, "feature:new")) {
  1729. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  1730. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  1731. Printf(f->code, "%s\n", tm);
  1732. }
  1733. }
  1734. Printv(f->code, UnProtectWrapupCode, NIL);
  1735. /*If the user gave us something to convert the result in */
  1736. if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) {
  1737. Replaceall(tm,"$source","ans");
  1738. Replaceall(tm,"$result","ans");
  1739. replaceRClass(tm, Getattr(n, "type"));
  1740. Chop(tm);
  1741. }
  1742. Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname,
  1743. "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL);
  1744. if(Len(tm))
  1745. {
  1746. Printf(sfun->code, "%s\n\n", tm);
  1747. if (constructor)
  1748. {
  1749. String *finalizer = NewString(iname);
  1750. Replace(finalizer, "new_", "", DOH_REPLACE_FIRST);
  1751. Printf(sfun->code, "reg.finalizer(ans, delete_%s)\n", finalizer);
  1752. }
  1753. Printf(sfun->code, "ans\n");
  1754. }
  1755. if (destructor)
  1756. Printv(f->code, "R_ClearExternalPtr(self);\n", NIL);
  1757. Printv(f->code, "return r_ans;\n}\n", NIL);
  1758. Printv(sfun->code, "\n}", NIL);
  1759. /* Substitute the function name */
  1760. Replaceall(f->code,"$symname",iname);
  1761. Wrapper_print(f, f_wrapper);
  1762. Wrapper_print(sfun, sfile);
  1763. Printf(sfun->code, "\n# End of %s\n", iname);
  1764. tm = Swig_typemap_lookup("rtype", n, "", 0);
  1765. if(tm) {
  1766. SwigType *retType = Getattr(n, "type");
  1767. replaceRClass(tm, retType);
  1768. }
  1769. Printv(sfile, "attr(`", sfname, "`, 'returnType') = '",
  1770. isVoidReturnType ? "void" : (tm ? tm : ""),
  1771. "'\n", NIL);
  1772. if(nargs > 0)
  1773. Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(",
  1774. s_inputTypes, ")\n", NIL);
  1775. Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('",
  1776. sfname, "'))\n\n", NIL);
  1777. if (memoryProfile) {
  1778. Printv(sfile, "memory.profile()\n", NIL);
  1779. }
  1780. if (aggressiveGc) {
  1781. Printv(sfile, "gc()\n", NIL);
  1782. }
  1783. // Printv(sfile, "setMethod('", name, "', '", name, "', ", iname, ")\n\n\n");
  1784. /* If we are dealing with a method in an C++ class, then
  1785. add the name of the R function and its definition.
  1786. XXX need to figure out how to store the Wrapper if possible in the hash/list.
  1787. Would like to be able to do this so that we can potentialy insert
  1788. */
  1789. if(processing_member_access_function || processing_class_member_function) {
  1790. addAccessor(member_name, sfun, iname);
  1791. }
  1792. if (Getattr(n, "sym:overloaded") &&
  1793. !Getattr(n, "sym:nextSibling")) {
  1794. dispatchFunction(n);
  1795. }
  1796. addRegistrationRoutine(wname, addCopyParam ? nargs +1 : nargs);
  1797. DelWrapper(f);
  1798. DelWrapper(sfun);
  1799. Delete(sargs);
  1800. Delete(sfname);
  1801. return SWIG_OK;
  1802. }
  1803. /*****************************************************
  1804. Add the specified routine name to the collection of
  1805. generated routines that are called from R functions.
  1806. This is used to register the routines with R for
  1807. resolving symbols.
  1808. rname - the name of the routine
  1809. nargs - the number of arguments it expects.
  1810. ******************************************************/
  1811. int R::addRegistrationRoutine(String *rname, int nargs) {
  1812. if(!registrationTable)
  1813. registrationTable = NewHash();
  1814. String *el =
  1815. NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs);
  1816. Setattr(registrationTable, rname, el);
  1817. return SWIG_OK;
  1818. }
  1819. /*****************************************************
  1820. Write the registration information to an array and
  1821. create the initialization routine for registering
  1822. these.
  1823. ******************************************************/
  1824. int R::outputRegistrationRoutines(File *out) {
  1825. int i, n;
  1826. if(!registrationTable)
  1827. return(0);
  1828. if(inCPlusMode)
  1829. Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
  1830. Printf(out, "#include <R_ext/Rdynload.h>\n\n");
  1831. if(inCPlusMode)
  1832. Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n");
  1833. Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n");
  1834. List *keys = Keys(registrationTable);
  1835. n = Len(keys);
  1836. for(i = 0; i < n; i++)
  1837. Printf(out, " %s,\n", Getattr(registrationTable, Getitem(keys, i)));
  1838. Printf(out, " {NULL, NULL, 0}\n};\n\n");
  1839. if(!noInitializationCode) {
  1840. if (inCPlusMode)
  1841. Printv(out, "extern \"C\" ", NIL);
  1842. Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage);
  1843. Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4);
  1844. if(Len(s_init_routine)) {
  1845. Printf(out, "\n%s\n", s_init_routine);
  1846. }
  1847. Printf(out, "}\n");
  1848. }
  1849. return n;
  1850. }
  1851. /****************************************************************************
  1852. Process a struct, union or class declaration in the source code,
  1853. or an anonymous typedef struct
  1854. *****************************************************************************/
  1855. //XXX What do we need to do here -
  1856. // Define an S4 class to refer to this.
  1857. void R::registerClass(Node *n) {
  1858. String *name = Getattr(n, "name");
  1859. String *kind = Getattr(n, "kind");
  1860. if (debugMode)
  1861. Swig_print_node(n);
  1862. String *sname = NewStringf("_p%s", SwigType_manglestr(name));
  1863. if(!Getattr(SClassDefs, sname)) {
  1864. Setattr(SClassDefs, sname, sname);
  1865. String *base;
  1866. if(Strcmp(kind, "class") == 0) {
  1867. base = NewString("");
  1868. List *l = Getattr(n, "bases");
  1869. if(Len(l)) {
  1870. Printf(base, "c(");
  1871. for(int i = 0; i < Len(l); i++) {
  1872. registerClass(Getitem(l, i));
  1873. Printf(base, "'_p%s'%s",
  1874. SwigType_manglestr(Getattr(Getitem(l, i), "name")),
  1875. i < Len(l)-1 ? ", " : "");
  1876. }
  1877. Printf(base, ")");
  1878. } else {
  1879. base = NewString("'C++Reference'");
  1880. }
  1881. } else
  1882. base = NewString("'ExternalReference'");
  1883. Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base);
  1884. Delete(base);
  1885. }
  1886. }
  1887. int R::classDeclaration(Node *n) {
  1888. String *name = Getattr(n, "name");
  1889. String *kind = Getattr(n, "kind");
  1890. if (debugMode)
  1891. Swig_print_node(n);
  1892. registerClass(n);
  1893. /* If we have a typedef union { ... } U, then we never get to see the typedef
  1894. via a regular call to typedefHandler. Instead, */
  1895. if(Getattr(n, "unnamed") && Strcmp(Getattr(n, "storage"), "typedef") == 0
  1896. && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) {
  1897. if (de