PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Source/Modules/emit.cxx

#
C++ | 520 lines | 335 code | 56 blank | 129 comment | 100 complexity | 7d7bac472b5165b36b71cce20e89654b 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. * emit.cxx
  10. *
  11. * Useful functions for emitting various pieces of code.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_emit_cxx[] = "$Id: emit.cxx 12830 2011-10-30 21:51:50Z wsfulton $";
  14. #include "swigmod.h"
  15. /* -----------------------------------------------------------------------------
  16. * emit_return_variable()
  17. *
  18. * Emits a variable declaration for a function return value.
  19. * The variable name is always called result.
  20. * n => Node of the method being wrapped
  21. * rt => the return type
  22. * f => the wrapper to generate code into
  23. * ----------------------------------------------------------------------------- */
  24. void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) {
  25. if (!GetFlag(n, "tmap:out:optimal")) {
  26. if (rt && (SwigType_type(rt) != T_VOID)) {
  27. SwigType *vt = cplus_value_type(rt);
  28. SwigType *tt = vt ? vt : rt;
  29. SwigType *lt = SwigType_ltype(tt);
  30. String *lstr = SwigType_str(lt, Swig_cresult_name());
  31. if (SwigType_ispointer(lt)) {
  32. Wrapper_add_localv(f, Swig_cresult_name(), lstr, "= 0", NULL);
  33. } else {
  34. Wrapper_add_local(f, Swig_cresult_name(), lstr);
  35. }
  36. if (vt) {
  37. Delete(vt);
  38. }
  39. Delete(lt);
  40. Delete(lstr);
  41. }
  42. }
  43. }
  44. /* -----------------------------------------------------------------------------
  45. * emit_parameter_variables()
  46. *
  47. * Emits a list of variable declarations for function parameters.
  48. * The variable names are always called arg1, arg2, etc...
  49. * l => the parameter list
  50. * f => the wrapper to generate code into
  51. * ----------------------------------------------------------------------------- */
  52. void emit_parameter_variables(ParmList *l, Wrapper *f) {
  53. Parm *p;
  54. String *tm;
  55. /* Emit function arguments */
  56. Swig_cargs(f, l);
  57. /* Attach typemaps to parameters */
  58. /* Swig_typemap_attach_parms("ignore",l,f); */
  59. Swig_typemap_attach_parms("default", l, f);
  60. Swig_typemap_attach_parms("arginit", l, f);
  61. /* Apply the arginit and default */
  62. p = l;
  63. while (p) {
  64. tm = Getattr(p, "tmap:arginit");
  65. if (tm) {
  66. Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
  67. Printv(f->code, tm, "\n", NIL);
  68. p = Getattr(p, "tmap:arginit:next");
  69. } else {
  70. p = nextSibling(p);
  71. }
  72. }
  73. /* Apply the default typemap */
  74. p = l;
  75. while (p) {
  76. tm = Getattr(p, "tmap:default");
  77. if (tm) {
  78. Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
  79. Printv(f->code, tm, "\n", NIL);
  80. p = Getattr(p, "tmap:default:next");
  81. } else {
  82. p = nextSibling(p);
  83. }
  84. }
  85. }
  86. /* -----------------------------------------------------------------------------
  87. * emit_attach_parmmaps()
  88. *
  89. * Attach the standard parameter related typemaps.
  90. * ----------------------------------------------------------------------------- */
  91. void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
  92. Swig_typemap_attach_parms("in", l, f);
  93. Swig_typemap_attach_parms("typecheck", l, 0);
  94. Swig_typemap_attach_parms("argout", l, f);
  95. Swig_typemap_attach_parms("check", l, f);
  96. Swig_typemap_attach_parms("freearg", l, f);
  97. {
  98. /* This is compatibility code to deal with the deprecated "ignore" typemap */
  99. Parm *p = l;
  100. Parm *np;
  101. String *tm;
  102. while (p) {
  103. tm = Getattr(p, "tmap:in");
  104. if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
  105. Replaceall(tm, "$target", Getattr(p, "lname"));
  106. Printv(f->code, tm, "\n", NIL);
  107. np = Getattr(p, "tmap:in:next");
  108. while (p && (p != np)) {
  109. /* Setattr(p,"ignore","1"); Deprecate */
  110. p = nextSibling(p);
  111. }
  112. } else if (tm) {
  113. p = Getattr(p, "tmap:in:next");
  114. } else {
  115. p = nextSibling(p);
  116. }
  117. }
  118. }
  119. /* Perform a sanity check on "in" and "freearg" typemaps. These
  120. must exactly match to avoid chaos. If a mismatch occurs, we
  121. nuke the freearg typemap */
  122. {
  123. Parm *p = l;
  124. Parm *npin, *npfreearg;
  125. while (p) {
  126. npin = Getattr(p, "tmap:in:next");
  127. /*
  128. if (Getattr(p,"tmap:ignore")) {
  129. npin = Getattr(p,"tmap:ignore:next");
  130. } else if (Getattr(p,"tmap:in")) {
  131. npin = Getattr(p,"tmap:in:next");
  132. }
  133. */
  134. if (Getattr(p, "tmap:freearg")) {
  135. npfreearg = Getattr(p, "tmap:freearg:next");
  136. if (npin != npfreearg) {
  137. while (p != npin) {
  138. Delattr(p, "tmap:freearg");
  139. Delattr(p, "tmap:freearg:next");
  140. p = nextSibling(p);
  141. }
  142. }
  143. }
  144. p = npin;
  145. }
  146. }
  147. /* Check for variable length arguments with no input typemap.
  148. If no input is defined, we set this to ignore and print a
  149. message.
  150. */
  151. {
  152. Parm *p = l;
  153. Parm *lp = 0;
  154. while (p) {
  155. if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
  156. lp = p;
  157. p = Getattr(p, "tmap:in:next");
  158. continue;
  159. }
  160. if (SwigType_isvarargs(Getattr(p, "type"))) {
  161. Swig_warning(WARN_LANG_VARARGS, input_file, line_number, "Variable length arguments discarded.\n");
  162. Setattr(p, "tmap:in", "");
  163. }
  164. lp = 0;
  165. p = nextSibling(p);
  166. }
  167. /* Check if last input argument is variable length argument */
  168. if (lp) {
  169. p = lp;
  170. while (p) {
  171. if (SwigType_isvarargs(Getattr(p, "type"))) {
  172. Setattr(l, "emit:varargs", lp);
  173. break;
  174. }
  175. p = nextSibling(p);
  176. }
  177. }
  178. }
  179. }
  180. /* -----------------------------------------------------------------------------
  181. * emit_num_arguments()
  182. *
  183. * Calculate the total number of arguments. This function is safe for use
  184. * with multi-argument typemaps which may change the number of arguments in
  185. * strange ways.
  186. * ----------------------------------------------------------------------------- */
  187. int emit_num_arguments(ParmList *parms) {
  188. Parm *p = parms;
  189. int nargs = 0;
  190. while (p) {
  191. if (Getattr(p, "tmap:in")) {
  192. nargs += GetInt(p, "tmap:in:numinputs");
  193. p = Getattr(p, "tmap:in:next");
  194. } else {
  195. p = nextSibling(p);
  196. }
  197. }
  198. /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
  199. /*
  200. if (parms && (p = Getattr(parms,"emit:varargs"))) {
  201. if (!nextSibling(p)) {
  202. nargs--;
  203. }
  204. }
  205. */
  206. return nargs;
  207. }
  208. /* -----------------------------------------------------------------------------
  209. * emit_num_required()
  210. *
  211. * Computes the number of required arguments. This function is safe for
  212. * use with multi-argument typemaps and knows how to skip over everything
  213. * properly. Note that parameters with default values are counted unless
  214. * the compact default args option is on.
  215. * ----------------------------------------------------------------------------- */
  216. int emit_num_required(ParmList *parms) {
  217. Parm *p = parms;
  218. int nargs = 0;
  219. Parm *first_default_arg = 0;
  220. int compactdefargs = ParmList_is_compactdefargs(p);
  221. while (p) {
  222. if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
  223. p = Getattr(p, "tmap:in:next");
  224. } else {
  225. if (Getattr(p, "tmap:default"))
  226. break;
  227. if (Getattr(p, "value")) {
  228. if (!first_default_arg)
  229. first_default_arg = p;
  230. if (compactdefargs)
  231. break;
  232. }
  233. nargs += GetInt(p, "tmap:in:numinputs");
  234. if (Getattr(p, "tmap:in")) {
  235. p = Getattr(p, "tmap:in:next");
  236. } else {
  237. p = nextSibling(p);
  238. }
  239. }
  240. }
  241. /* Print error message for non-default arguments following default arguments */
  242. /* The error message is printed more than once with most language modules, this ought to be fixed */
  243. if (first_default_arg) {
  244. p = first_default_arg;
  245. while (p) {
  246. if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
  247. p = Getattr(p, "tmap:in:next");
  248. } else {
  249. if (!Getattr(p, "value") && (!Getattr(p, "tmap:default"))) {
  250. Swig_error(Getfile(p), Getline(p), "Non-optional argument '%s' follows an optional argument.\n", Getattr(p, "name"));
  251. }
  252. if (Getattr(p, "tmap:in")) {
  253. p = Getattr(p, "tmap:in:next");
  254. } else {
  255. p = nextSibling(p);
  256. }
  257. }
  258. }
  259. }
  260. /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
  261. /*
  262. if (parms && (p = Getattr(parms,"emit:varargs"))) {
  263. if (!nextSibling(p)) {
  264. nargs--;
  265. }
  266. }
  267. */
  268. return nargs;
  269. }
  270. /* -----------------------------------------------------------------------------
  271. * emit_isvarargs()
  272. *
  273. * Checks if a function is a varargs function
  274. * ----------------------------------------------------------------------------- */
  275. int emit_isvarargs(ParmList *p) {
  276. if (!p)
  277. return 0;
  278. if (Getattr(p, "emit:varargs"))
  279. return 1;
  280. return 0;
  281. }
  282. /* -----------------------------------------------------------------------------
  283. * void emit_mark_vararg_parms()
  284. *
  285. * Marks the vararg parameters which are to be ignored.
  286. * Vararg parameters are marked as ignored if there is no 'in' varargs (...)
  287. * typemap.
  288. * ----------------------------------------------------------------------------- */
  289. void emit_mark_varargs(ParmList *l) {
  290. Parm *p = l;
  291. while (p) {
  292. if (SwigType_isvarargs(Getattr(p, "type")))
  293. if (!Getattr(p, "tmap:in"))
  294. Setattr(p, "varargs:ignore", "1");
  295. p = nextSibling(p);
  296. }
  297. }
  298. #if 0
  299. /* replace_contract_args. This function replaces argument names in contract
  300. specifications. Used in conjunction with the %contract directive. */
  301. static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
  302. while (cp && rp) {
  303. String *n = Getattr(cp, "name");
  304. if (n) {
  305. Replace(s, n, Getattr(rp, "lname"), DOH_REPLACE_ID);
  306. }
  307. cp = nextSibling(cp);
  308. rp = nextSibling(rp);
  309. }
  310. }
  311. #endif
  312. /* -----------------------------------------------------------------------------
  313. * int emit_action_code()
  314. *
  315. * Emits action code for a wrapper. Adds in exception handling code (%exception).
  316. * eaction -> the action code to emit
  317. * wrappercode -> the emitted code (output)
  318. * ----------------------------------------------------------------------------- */
  319. int emit_action_code(Node *n, String *wrappercode, String *eaction) {
  320. assert(Getattr(n, "wrap:name"));
  321. /* Look for except feature (%exception) */
  322. String *tm = GetFlagAttr(n, "feature:except");
  323. if (tm)
  324. tm = Copy(tm);
  325. if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
  326. if (Strstr(tm, "$")) {
  327. Replaceall(tm, "$name", Getattr(n, "name"));
  328. Replaceall(tm, "$symname", Getattr(n, "sym:name"));
  329. Replaceall(tm, "$function", eaction); // deprecated
  330. Replaceall(tm, "$action", eaction);
  331. Replaceall(tm, "$wrapname", Getattr(n, "wrap:name"));
  332. String *overloaded = Getattr(n, "sym:overloaded");
  333. Replaceall(tm, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
  334. if (Strstr(tm, "$decl")) {
  335. String *decl = Swig_name_decl(n);
  336. Replaceall(tm, "$decl", decl);
  337. Delete(decl);
  338. }
  339. if (Strstr(tm, "$fulldecl")) {
  340. String *fulldecl = Swig_name_fulldecl(n);
  341. Replaceall(tm, "$fulldecl", fulldecl);
  342. Delete(fulldecl);
  343. }
  344. }
  345. Printv(wrappercode, tm, "\n", NIL);
  346. Delete(tm);
  347. return 1;
  348. } else {
  349. Printv(wrappercode, eaction, "\n", NIL);
  350. return 0;
  351. }
  352. }
  353. /* -----------------------------------------------------------------------------
  354. * int emit_action()
  355. *
  356. * Emits the call to the wrapped function.
  357. * Adds in exception specification exception handling and %exception code.
  358. * ----------------------------------------------------------------------------- */
  359. String *emit_action(Node *n) {
  360. String *actioncode = NewStringEmpty();
  361. String *tm;
  362. String *action;
  363. String *wrap;
  364. ParmList *catchlist = Getattr(n, "catchlist");
  365. /* Look for fragments */
  366. {
  367. String *fragment = Getattr(n, "feature:fragment");
  368. if (fragment) {
  369. char *c, *tok;
  370. String *t = Copy(fragment);
  371. c = Char(t);
  372. tok = strtok(c, ",");
  373. while (tok) {
  374. String *fname = NewString(tok);
  375. Setfile(fname, Getfile(n));
  376. Setline(fname, Getline(n));
  377. Swig_fragment_emit(fname);
  378. Delete(fname);
  379. tok = strtok(NULL, ",");
  380. }
  381. Delete(t);
  382. }
  383. }
  384. /* Emit wrapper code (if any) */
  385. wrap = Getattr(n, "wrap:code");
  386. if (wrap && Swig_filebyname("header") != Getattr(n, "wrap:code:done")) {
  387. File *f_code = Swig_filebyname("header");
  388. if (f_code) {
  389. Printv(f_code, wrap, NIL);
  390. }
  391. Setattr(n, "wrap:code:done", f_code);
  392. }
  393. action = Getattr(n, "feature:action");
  394. if (!action)
  395. action = Getattr(n, "wrap:action");
  396. assert(action != 0);
  397. /* Emit contract code (if any) */
  398. if (Swig_contract_mode_get()) {
  399. /* Preassertion */
  400. tm = Getattr(n, "contract:preassert");
  401. if (Len(tm)) {
  402. Printv(actioncode, tm, "\n", NIL);
  403. }
  404. }
  405. /* Exception handling code */
  406. /* saves action -> eaction for postcatching exception */
  407. String *eaction = NewString("");
  408. /* If we are in C++ mode and there is an exception specification. We're going to
  409. enclose the block in a try block */
  410. if (catchlist) {
  411. Printf(eaction, "try {\n");
  412. }
  413. String *preaction = Getattr(n, "wrap:preaction");
  414. if (preaction)
  415. Printv(eaction, preaction, NIL);
  416. Printv(eaction, action, NIL);
  417. String *postaction = Getattr(n, "wrap:postaction");
  418. if (postaction)
  419. Printv(eaction, postaction, NIL);
  420. if (catchlist) {
  421. int unknown_catch = 0;
  422. Printf(eaction, "}\n");
  423. for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
  424. String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
  425. if (em) {
  426. SwigType *et = Getattr(ep, "type");
  427. SwigType *etr = SwigType_typedef_resolve_all(et);
  428. if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
  429. Printf(eaction, "catch(%s) {", SwigType_str(et, "_e"));
  430. } else if (SwigType_isvarargs(etr)) {
  431. Printf(eaction, "catch(...) {");
  432. } else {
  433. Printf(eaction, "catch(%s) {", SwigType_str(et, "&_e"));
  434. }
  435. Printv(eaction, em, "\n", NIL);
  436. Printf(eaction, "}\n");
  437. } else {
  438. Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
  439. unknown_catch = 1;
  440. }
  441. }
  442. if (unknown_catch) {
  443. Printf(eaction, "catch(...) { throw; }\n");
  444. }
  445. }
  446. /* Look for except typemap (Deprecated) */
  447. tm = Swig_typemap_lookup("except", n, Swig_cresult_name(), 0);
  448. if (tm) {
  449. Setattr(n, "feature:except", tm);
  450. tm = 0;
  451. }
  452. /* emit the except feature code */
  453. emit_action_code(n, actioncode, eaction);
  454. Delete(eaction);
  455. /* Emit contract code (if any) */
  456. if (Swig_contract_mode_get()) {
  457. /* Postassertion */
  458. tm = Getattr(n, "contract:postassert");
  459. if (Len(tm)) {
  460. Printv(actioncode, tm, "\n", NIL);
  461. }
  462. }
  463. return actioncode;
  464. }