/tags/rel-2.0.2/Source/Modules/typepass.cxx

# · C++ · 1223 lines · 958 code · 116 blank · 149 comment · 255 complexity · 089aaccfecfba2667550f28a16f7e5c2 MD5 · raw file

  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. * typepass.cxx
  10. *
  11. * This module builds all of the internal type information by collecting
  12. * typedef declarations as well as registering classes, structures, and unions.
  13. * This information is needed to correctly handle shadow classes and other
  14. * advanced features. This phase of compilation is also used to perform
  15. * type-expansion. All types are fully qualified with namespace prefixes
  16. * and other information needed for compilation.
  17. * ----------------------------------------------------------------------------- */
  18. char cvsroot_typepass_cxx[] = "$Id: typepass.cxx 12419 2011-02-01 07:02:50Z wsfulton $";
  19. #include "swigmod.h"
  20. #include "cparse.h"
  21. struct normal_node {
  22. Symtab *symtab;
  23. Hash *typescope;
  24. List *normallist;
  25. normal_node *next;
  26. };
  27. static normal_node *patch_list = 0;
  28. /* Singleton class - all non-static methods in this class are private */
  29. class TypePass:private Dispatcher {
  30. Node *inclass;
  31. Node *module;
  32. int importmode;
  33. String *nsname;
  34. String *nssymname;
  35. Hash *classhash;
  36. List *normalize;
  37. TypePass() {
  38. }
  39. /* Normalize a type. Replaces type with fully qualified version */
  40. void normalize_type(SwigType *ty) {
  41. SwigType *qty;
  42. if (CPlusPlus) {
  43. Replaceall(ty, "struct ", "");
  44. Replaceall(ty, "union ", "");
  45. Replaceall(ty, "class ", "");
  46. }
  47. qty = SwigType_typedef_qualified(ty);
  48. /* Printf(stdout,"%s --> %s\n", ty, qty); */
  49. Clear(ty);
  50. Append(ty, qty);
  51. Delete(qty);
  52. }
  53. /* Normalize a parameter list */
  54. void normalize_parms(ParmList *p) {
  55. while (p) {
  56. SwigType *ty = Getattr(p, "type");
  57. normalize_type(ty);
  58. /* This is a check for a function type */
  59. {
  60. SwigType *qty = SwigType_typedef_resolve_all(ty);
  61. if (SwigType_isfunction(qty)) {
  62. SwigType_add_pointer(ty);
  63. }
  64. Delete(qty);
  65. }
  66. String *value = Getattr(p, "value");
  67. if (value) {
  68. Node *n = Swig_symbol_clookup(value, 0);
  69. if (n) {
  70. String *q = Swig_symbol_qualified(n);
  71. if (q && Len(q)) {
  72. String *vb = Swig_scopename_last(value);
  73. Clear(value);
  74. Printf(value, "%s::%s", SwigType_namestr(q), vb);
  75. Delete(q);
  76. }
  77. }
  78. }
  79. if (value && SwigType_istemplate(value)) {
  80. String *nv = SwigType_namestr(value);
  81. Setattr(p, "value", nv);
  82. }
  83. p = nextSibling(p);
  84. }
  85. }
  86. void normalize_later(ParmList *p) {
  87. while (p) {
  88. SwigType *ty = Getattr(p, "type");
  89. Append(normalize, ty);
  90. p = nextSibling(p);
  91. }
  92. }
  93. /* Walk through entries in normalize list and patch them up */
  94. void normalize_list() {
  95. Hash *currentsym = Swig_symbol_current();
  96. normal_node *nn = patch_list;
  97. normal_node *np;
  98. while (nn) {
  99. Swig_symbol_setscope(nn->symtab);
  100. SwigType_set_scope(nn->typescope);
  101. Iterator t;
  102. for (t = First(nn->normallist); t.item; t = Next(t)) {
  103. normalize_type(t.item);
  104. }
  105. Delete(nn->normallist);
  106. np = nn->next;
  107. delete(nn);
  108. nn = np;
  109. }
  110. Swig_symbol_setscope(currentsym);
  111. }
  112. /* generate C++ inheritance type-relationships */
  113. void cplus_inherit_types_impl(Node *first, Node *cls, String *clsname, const char *bases, const char *baselist, int ispublic, String *cast = 0) {
  114. if (first == cls)
  115. return; /* The Marcelo check */
  116. if (!cls)
  117. cls = first;
  118. List *alist = 0;
  119. List *ilist = Getattr(cls, bases);
  120. if (!ilist) {
  121. List *nlist = Getattr(cls, baselist);
  122. if (nlist) {
  123. int len = Len(nlist);
  124. int i;
  125. for (i = 0; i < len; i++) {
  126. Node *bcls = 0;
  127. int clsforward = 0;
  128. String *bname = Getitem(nlist, i);
  129. String *sname = bname;
  130. String *tname = 0;
  131. /* Try to locate the base class. We look in the symbol table and we chase
  132. typedef declarations to get to the base class if necessary */
  133. Symtab *st = Getattr(cls, "sym:symtab");
  134. if (SwigType_istemplate(bname)) {
  135. tname = SwigType_typedef_resolve_all(bname);
  136. sname = tname;
  137. }
  138. while (1) {
  139. String *qsname = SwigType_typedef_qualified(sname);
  140. bcls = Swig_symbol_clookup(qsname, st);
  141. Delete(qsname);
  142. if (bcls) {
  143. if (Strcmp(nodeType(bcls), "class") != 0) {
  144. /* Not a class. The symbol could be a typedef. */
  145. if (checkAttribute(bcls, "storage", "typedef")) {
  146. SwigType *decl = Getattr(bcls, "decl");
  147. if (!decl || !(Len(decl))) {
  148. sname = Getattr(bcls, "type");
  149. st = Getattr(bcls, "sym:symtab");
  150. if (SwigType_istemplate(sname)) {
  151. if (tname)
  152. Delete(tname);
  153. tname = SwigType_typedef_resolve_all(sname);
  154. sname = tname;
  155. }
  156. continue;
  157. }
  158. }
  159. if (Strcmp(nodeType(bcls), "classforward") != 0) {
  160. Swig_error(Getfile(bname), Getline(bname), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
  161. Swig_error(Getfile(bcls), Getline(bcls), "See definition of '%s'.\n", SwigType_namestr(bname));
  162. } else {
  163. Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bname), Getline(bname), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
  164. Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname));
  165. clsforward = 1;
  166. }
  167. bcls = 0;
  168. } else {
  169. if (Getattr(bcls, "typepass:visit")) {
  170. if (!ilist)
  171. ilist = alist = NewList();
  172. Append(ilist, bcls);
  173. } else {
  174. Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
  175. Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
  176. }
  177. }
  178. }
  179. break;
  180. }
  181. if (tname)
  182. Delete(tname);
  183. if (!bcls) {
  184. if (!clsforward) {
  185. if (ispublic && !Getmeta(bname, "already_warned")) {
  186. Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
  187. if (Strchr(bname, '<')) {
  188. Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname));
  189. }
  190. Setmeta(bname, "already_warned", "1");
  191. }
  192. }
  193. SwigType_inherit(clsname, bname, cast, 0);
  194. }
  195. }
  196. }
  197. if (ilist) {
  198. Setattr(cls, bases, ilist);
  199. }
  200. }
  201. if (alist)
  202. Delete(alist);
  203. if (!ilist)
  204. return;
  205. int len = Len(ilist);
  206. int i;
  207. for (i = 0; i < len; i++) {
  208. Node *n = Getitem(ilist, i);
  209. String *bname = Getattr(n, "name");
  210. Node *bclass = n; /* Getattr(n,"class"); */
  211. Hash *scopes = Getattr(bclass, "typescope");
  212. SwigType_inherit(clsname, bname, cast, 0);
  213. String *smartptr = Getattr(first, "feature:smartptr");
  214. if (smartptr) {
  215. SwigType *smart = 0;
  216. SwigType *spt = Swig_cparse_type(smartptr);
  217. if (spt) {
  218. smart = SwigType_typedef_resolve_all(spt);
  219. Delete(spt);
  220. /* Record a (fake) inheritance relationship between smart pointer
  221. and smart pointer to base class, so that smart pointer upcasts
  222. are automatically generated. */
  223. SwigType *bsmart = Copy(smart);
  224. SwigType *rclsname = SwigType_typedef_resolve_all(clsname);
  225. SwigType *rbname = SwigType_typedef_resolve_all(bname);
  226. Replaceall(bsmart, rclsname, rbname);
  227. Delete(rclsname);
  228. Delete(rbname);
  229. String *smartnamestr = SwigType_namestr(smart);
  230. String *bsmartnamestr = SwigType_namestr(bsmart);
  231. /* construct casting code */
  232. String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr);
  233. Delete(bsmartnamestr);
  234. Delete(smartnamestr);
  235. /* setup inheritance relationship between smart pointer templates */
  236. SwigType_inherit(smart, bsmart, 0, convcode);
  237. if (!GetFlag(bclass, "feature:smartptr"))
  238. Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name")));
  239. Delete(convcode);
  240. Delete(bsmart);
  241. Delete(smart);
  242. } else {
  243. Swig_error(Getfile(first), Getline(first), "Invalid type (%s) in 'smartptr' feature for class %s.\n", SwigType_namestr(smartptr), SwigType_namestr(clsname));
  244. }
  245. } else {
  246. if (GetFlag(bclass, "feature:smartptr"))
  247. Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name")));
  248. }
  249. if (!importmode) {
  250. String *btype = Copy(bname);
  251. SwigType_add_pointer(btype);
  252. SwigType_remember(btype);
  253. Delete(btype);
  254. }
  255. if (scopes) {
  256. SwigType_inherit_scope(scopes);
  257. }
  258. /* Set up inheritance in the symbol table */
  259. Symtab *st = Getattr(cls, "symtab");
  260. Symtab *bst = Getattr(bclass, "symtab");
  261. if (st == bst) {
  262. Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", SwigType_namestr(Getattr(cls, "name")));
  263. continue;
  264. }
  265. Symtab *s = Swig_symbol_current();
  266. Swig_symbol_setscope(st);
  267. Swig_symbol_inherit(bst);
  268. Swig_symbol_setscope(s);
  269. /* Recursively hit base classes */
  270. String *namestr = SwigType_namestr(Getattr(bclass, "name"));
  271. String *newcast = NewStringf("(%s *)%s", namestr, cast);
  272. Delete(namestr);
  273. cplus_inherit_types_impl(first, bclass, clsname, bases, baselist, ispublic, newcast);
  274. Delete(newcast);
  275. }
  276. }
  277. void append_list(List *lb, List *la) {
  278. if (la && lb) {
  279. for (Iterator bi = First(la); bi.item; bi = Next(bi)) {
  280. Append(lb, bi.item);
  281. }
  282. }
  283. }
  284. void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) {
  285. cplus_inherit_types_impl(first, cls, clsname, "bases", "baselist", 1, cast);
  286. cplus_inherit_types_impl(first, cls, clsname, "protectedbases", "protectedbaselist", 0, cast);
  287. cplus_inherit_types_impl(first, cls, clsname, "privatebases", "privatebaselist", 0, cast);
  288. if (!cls)
  289. cls = first;
  290. List *allbases = NewList();
  291. append_list(allbases, Getattr(cls, "bases"));
  292. append_list(allbases, Getattr(cls, "protectedbases"));
  293. append_list(allbases, Getattr(cls, "privatebases"));
  294. if (Len(allbases)) {
  295. Setattr(cls, "allbases", allbases);
  296. }
  297. Delete(allbases);
  298. }
  299. /* ------------------------------------------------------------
  300. * top()
  301. * ------------------------------------------------------------ */
  302. virtual int top(Node *n) {
  303. importmode = 0;
  304. module = Getattr(n, "module");
  305. inclass = 0;
  306. normalize = 0;
  307. nsname = 0;
  308. nssymname = 0;
  309. classhash = Getattr(n, "classes");
  310. emit_children(n);
  311. normalize_list();
  312. SwigType_set_scope(0);
  313. return SWIG_OK;
  314. }
  315. /* ------------------------------------------------------------
  316. * moduleDirective()
  317. * ------------------------------------------------------------ */
  318. virtual int moduleDirective(Node *n) {
  319. if (!module) {
  320. module = n;
  321. }
  322. return SWIG_OK;
  323. }
  324. /* ------------------------------------------------------------
  325. * importDirective()
  326. * ------------------------------------------------------------ */
  327. virtual int importDirective(Node *n) {
  328. String *oldmodule = module;
  329. int oldimport = importmode;
  330. importmode = 1;
  331. module = 0;
  332. emit_children(n);
  333. importmode = oldimport;
  334. module = oldmodule;
  335. return SWIG_OK;
  336. }
  337. /* ------------------------------------------------------------
  338. * includeDirective()
  339. * externDirective()
  340. * extendDirective()
  341. * ------------------------------------------------------------ */
  342. virtual int includeDirective(Node *n) {
  343. return emit_children(n);
  344. }
  345. virtual int externDeclaration(Node *n) {
  346. return emit_children(n);
  347. }
  348. virtual int extendDirective(Node *n) {
  349. return emit_children(n);
  350. }
  351. /* ------------------------------------------------------------
  352. * classDeclaration()
  353. * ------------------------------------------------------------ */
  354. virtual int classDeclaration(Node *n) {
  355. String *name = Getattr(n, "name");
  356. String *tdname = Getattr(n, "tdname");
  357. String *unnamed = Getattr(n, "unnamed");
  358. String *storage = Getattr(n, "storage");
  359. String *kind = Getattr(n, "kind");
  360. Node *oldinclass = inclass;
  361. List *olist = normalize;
  362. Symtab *symtab;
  363. String *nname = 0;
  364. String *fname = 0;
  365. String *scopename = 0;
  366. normalize = NewList();
  367. if (name) {
  368. if (SwigType_istemplate(name)) {
  369. // We need to fully resolve the name to make templates work correctly */
  370. Node *cn;
  371. fname = SwigType_typedef_resolve_all(name);
  372. if (Strcmp(fname, name) != 0 && (cn = Swig_symbol_clookup_local(fname, 0))) {
  373. if ((n == cn)
  374. || (Strcmp(nodeType(cn), "template") == 0)
  375. || (Getattr(cn, "feature:onlychildren") != 0)
  376. || (Getattr(n, "feature:onlychildren") != 0)) {
  377. Swig_symbol_cadd(fname, n);
  378. SwigType_typedef_class(fname);
  379. scopename = Copy(fname);
  380. } else {
  381. Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name));
  382. Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name")));
  383. scopename = 0;
  384. }
  385. } else {
  386. Swig_symbol_cadd(fname, n);
  387. SwigType_typedef_class(fname);
  388. scopename = Copy(fname);
  389. }
  390. } else {
  391. if ((CPlusPlus) || (unnamed)) {
  392. SwigType_typedef_class(name);
  393. } else {
  394. SwigType_typedef_class(NewStringf("%s %s", kind, name));
  395. }
  396. scopename = Copy(name);
  397. }
  398. } else {
  399. scopename = 0;
  400. }
  401. Setattr(n, "typepass:visit", "1");
  402. /* Need to set up a typedef if unnamed */
  403. if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
  404. SwigType_typedef(unnamed, tdname);
  405. }
  406. if (nsname) {
  407. nname = NewStringf("%s::%s", nsname, name);
  408. String *tdname = Getattr(n, "tdname");
  409. if (tdname) {
  410. tdname = NewStringf("%s::%s", nsname, tdname);
  411. Setattr(n, "tdname", tdname);
  412. }
  413. }
  414. if (nssymname) {
  415. if (GetFlag(n, "feature:nspace"))
  416. Setattr(n, "sym:nspace", nssymname);
  417. }
  418. SwigType_new_scope(scopename);
  419. SwigType_attach_symtab(Getattr(n, "symtab"));
  420. /* Inherit type definitions into the class */
  421. if (name) {
  422. cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name));
  423. }
  424. inclass = n;
  425. symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
  426. emit_children(n);
  427. Swig_symbol_setscope(symtab);
  428. Hash *ts = SwigType_pop_scope();
  429. Setattr(n, "typescope", ts);
  430. Delete(ts);
  431. Setattr(n, "module", module);
  432. /* Normalize deferred types */
  433. {
  434. normal_node *nn = new normal_node();
  435. nn->normallist = normalize;
  436. nn->symtab = Getattr(n, "symtab");
  437. nn->next = patch_list;
  438. nn->typescope = Getattr(n, "typescope");
  439. patch_list = nn;
  440. }
  441. normalize = olist;
  442. inclass = oldinclass;
  443. /* If in a namespace, patch the class name */
  444. if (nname) {
  445. Setattr(n, "name", nname);
  446. Delete(nname);
  447. }
  448. return SWIG_OK;
  449. }
  450. /* ------------------------------------------------------------
  451. * namespaceDeclaration()
  452. * ------------------------------------------------------------ */
  453. virtual int templateDeclaration(Node *n) {
  454. String *name = Getattr(n, "name");
  455. String *ttype = Getattr(n, "templatetype");
  456. if (Strcmp(ttype, "class") == 0) {
  457. String *rname = SwigType_typedef_resolve_all(name);
  458. SwigType_typedef_class(rname);
  459. Delete(rname);
  460. } else if (Strcmp(ttype, "classforward") == 0) {
  461. String *rname = SwigType_typedef_resolve_all(name);
  462. SwigType_typedef_class(rname);
  463. Delete(rname);
  464. /* SwigType_typedef_class(name); */
  465. }
  466. return SWIG_OK;
  467. }
  468. /* ------------------------------------------------------------
  469. * classforwardDeclaration()
  470. * ------------------------------------------------------------ */
  471. virtual int classforwardDeclaration(Node *n) {
  472. /* Temporary hack. Can't do inside a class because it breaks
  473. C nested structure wrapping */
  474. if ((!inclass) || (CPlusPlus)) {
  475. String *name = Getattr(n, "name");
  476. String *nname;
  477. SwigType_typedef_class(name);
  478. if (nsname) {
  479. nname = NewStringf("%s::%s", nsname, name);
  480. Setattr(n, "name", nname);
  481. }
  482. }
  483. return SWIG_OK;
  484. }
  485. /* ------------------------------------------------------------
  486. * namespaceDeclaration()
  487. * ------------------------------------------------------------ */
  488. virtual int namespaceDeclaration(Node *n) {
  489. Symtab *symtab;
  490. String *name = Getattr(n, "name");
  491. String *alias = Getattr(n, "alias");
  492. List *olist = normalize;
  493. normalize = NewList();
  494. if (alias) {
  495. Typetab *ts = Getattr(n, "typescope");
  496. if (!ts) {
  497. Node *ns;
  498. /* Create a empty scope for the alias */
  499. ns = Getattr(n, "namespace");
  500. if (ns) {
  501. SwigType_scope_alias(name, Getattr(ns, "typescope"));
  502. }
  503. ts = Getattr(ns, "typescope");
  504. Setattr(n, "typescope", ts);
  505. }
  506. /* Namespace alias */
  507. return SWIG_OK;
  508. } else {
  509. if (name) {
  510. Node *nn = Swig_symbol_clookup(name, n);
  511. Hash *ts = 0;
  512. if (nn)
  513. ts = Getattr(nn, "typescope");
  514. if (!ts) {
  515. SwigType_new_scope(name);
  516. SwigType_attach_symtab(Getattr(n, "symtab"));
  517. } else {
  518. SwigType_set_scope(ts);
  519. }
  520. }
  521. String *oldnsname = nsname;
  522. String *oldnssymname = nssymname;
  523. nsname = Swig_symbol_qualified(Getattr(n, "symtab"));
  524. nssymname = Swig_symbol_qualified_language_scopename(Getattr(n, "symtab"));
  525. symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
  526. emit_children(n);
  527. Swig_symbol_setscope(symtab);
  528. if (name) {
  529. Hash *ts = SwigType_pop_scope();
  530. Setattr(n, "typescope", ts);
  531. Delete(ts);
  532. }
  533. /* Normalize deferred types */
  534. {
  535. normal_node *nn = new normal_node();
  536. nn->normallist = normalize;
  537. nn->symtab = Getattr(n, "symtab");
  538. nn->next = patch_list;
  539. nn->typescope = Getattr(n, "typescope");
  540. patch_list = nn;
  541. }
  542. normalize = olist;
  543. Delete(nssymname);
  544. nssymname = oldnssymname;
  545. Delete(nsname);
  546. nsname = oldnsname;
  547. return SWIG_OK;
  548. }
  549. }
  550. /* ------------------------------------------------------------
  551. * cDeclaration()
  552. * ------------------------------------------------------------ */
  553. virtual int cDeclaration(Node *n) {
  554. if (NoExcept) {
  555. Delattr(n, "throws");
  556. }
  557. /* Normalize types. */
  558. SwigType *ty = Getattr(n, "type");
  559. normalize_type(ty);
  560. SwigType *decl = Getattr(n, "decl");
  561. if (decl) {
  562. normalize_type(decl);
  563. }
  564. normalize_parms(Getattr(n, "parms"));
  565. normalize_parms(Getattr(n, "throws"));
  566. if (GetFlag(n, "conversion_operator")) {
  567. /* The call to the operator in the generated wrapper must be fully qualified in order to compile */
  568. SwigType *name = Getattr(n, "name");
  569. SwigType *qualifiedname = Swig_symbol_string_qualify(name,0);
  570. Clear(name);
  571. Append(name, qualifiedname);
  572. Delete(qualifiedname);
  573. }
  574. if (checkAttribute(n, "storage", "typedef")) {
  575. String *name = Getattr(n, "name");
  576. ty = Getattr(n, "type");
  577. decl = Getattr(n, "decl");
  578. SwigType *t = Copy(ty);
  579. {
  580. /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */
  581. if (Swig_scopename_check(t) && strncmp(Char(t), "::", 2)) {
  582. String *base, *prefix, *qprefix;
  583. base = Swig_scopename_last(t);
  584. prefix = Swig_scopename_prefix(t);
  585. qprefix = SwigType_typedef_qualified(prefix);
  586. Delete(t);
  587. t = NewStringf("%s::%s", qprefix, base);
  588. Delete(base);
  589. Delete(prefix);
  590. Delete(qprefix);
  591. }
  592. }
  593. SwigType_push(t, decl);
  594. if (CPlusPlus) {
  595. Replaceall(t, "struct ", "");
  596. Replaceall(t, "union ", "");
  597. Replaceall(t, "class ", "");
  598. }
  599. SwigType_typedef(t, name);
  600. }
  601. /* If namespaces are active. We need to patch the name with a namespace prefix */
  602. if (nsname && !inclass) {
  603. String *name = Getattr(n, "name");
  604. if (name) {
  605. String *nname = NewStringf("%s::%s", nsname, name);
  606. Setattr(n, "name", nname);
  607. Delete(nname);
  608. }
  609. }
  610. clean_overloaded(n);
  611. return SWIG_OK;
  612. }
  613. /* ------------------------------------------------------------
  614. * constructorDeclaration()
  615. * ------------------------------------------------------------ */
  616. virtual int constructorDeclaration(Node *n) {
  617. if (NoExcept) {
  618. Delattr(n, "throws");
  619. }
  620. normalize_parms(Getattr(n, "parms"));
  621. normalize_parms(Getattr(n, "throws"));
  622. /* If in a namespace, patch the class name */
  623. if (nsname) {
  624. String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
  625. Setattr(n, "name", nname);
  626. }
  627. clean_overloaded(n);
  628. return SWIG_OK;
  629. }
  630. /* ------------------------------------------------------------
  631. * destructorDeclaration()
  632. * ------------------------------------------------------------ */
  633. virtual int destructorDeclaration(Node *n) {
  634. /* If in a namespace, patch the class name */
  635. if (nsname) {
  636. String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
  637. Setattr(n, "name", nname);
  638. }
  639. return SWIG_OK;
  640. }
  641. /* ------------------------------------------------------------
  642. * constantDirective()
  643. * ------------------------------------------------------------ */
  644. virtual int constantDirective(Node *n) {
  645. SwigType *ty = Getattr(n, "type");
  646. if (ty) {
  647. Setattr(n, "type", SwigType_typedef_qualified(ty));
  648. }
  649. return SWIG_OK;
  650. }
  651. /* ------------------------------------------------------------
  652. * enumDeclaration()
  653. * ------------------------------------------------------------ */
  654. virtual int enumDeclaration(Node *n) {
  655. String *name = Getattr(n, "name");
  656. if (name) {
  657. String *scope = 0;
  658. // Add a typedef to the type table so that we can use 'enum Name' as well as just 'Name'
  659. if (nsname || inclass) {
  660. // But first correct the name and tdname to contain the fully qualified scopename
  661. if (nsname && inclass) {
  662. scope = NewStringf("%s::%s", nsname, Getattr(inclass, "name"));
  663. } else if (nsname) {
  664. scope = NewStringf("%s", nsname);
  665. } else if (inclass) {
  666. scope = NewStringf("%s", Getattr(inclass, "name"));
  667. }
  668. String *nname = NewStringf("%s::%s", scope, name);
  669. Setattr(n, "name", nname);
  670. String *tdname = Getattr(n, "tdname");
  671. if (tdname) {
  672. tdname = NewStringf("%s::%s", scope, tdname);
  673. Setattr(n, "tdname", tdname);
  674. }
  675. SwigType *t = NewStringf("enum %s", nname);
  676. SwigType_typedef(t, name);
  677. } else {
  678. SwigType *t = NewStringf("enum %s", name);
  679. SwigType_typedef(t, name);
  680. }
  681. Delete(scope);
  682. }
  683. String *tdname = Getattr(n, "tdname");
  684. String *unnamed = Getattr(n, "unnamed");
  685. String *storage = Getattr(n, "storage");
  686. // Construct enumtype - for declaring an enum of this type with SwigType_ltype() etc
  687. String *enumtype = 0;
  688. if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
  689. enumtype = Copy(Getattr(n, "tdname"));
  690. } else if (name) {
  691. enumtype = NewStringf("%s%s", CPlusPlus ? "" : "enum ", Getattr(n, "name"));
  692. } else {
  693. // anonymous enums
  694. enumtype = Copy(Getattr(n, "type"));
  695. }
  696. Setattr(n, "enumtype", enumtype);
  697. if (nssymname) {
  698. if (GetFlag(n, "feature:nspace"))
  699. Setattr(n, "sym:nspace", nssymname);
  700. }
  701. // This block of code is for dealing with %ignore on an enum item where the target language
  702. // attempts to use the C enum value in the target language itself and expects the previous enum value
  703. // to be one more than the previous value... the previous enum item might not exist if it is ignored!
  704. // - It sets the first non-ignored enum item with the "firstenumitem" attribute.
  705. // - It adds an enumvalue attribute if the previous enum item is ignored
  706. {
  707. Node *c;
  708. int count = 0;
  709. String *previous = 0;
  710. bool previous_ignored = false;
  711. bool firstenumitem = false;
  712. for (c = firstChild(n); c; c = nextSibling(c)) {
  713. assert(strcmp(Char(nodeType(c)), "enumitem") == 0);
  714. bool reset;
  715. String *enumvalue = Getattr(c, "enumvalue");
  716. if (GetFlag(c, "feature:ignore") || !Getattr(c, "sym:name")) {
  717. reset = enumvalue ? true : false;
  718. previous_ignored = true;
  719. } else {
  720. if (!enumvalue && previous_ignored) {
  721. if (previous)
  722. Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1));
  723. else
  724. Setattr(c, "enumvalue", NewStringf("%d", count));
  725. SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source
  726. }
  727. if (!firstenumitem) {
  728. SetFlag(c, "firstenumitem");
  729. firstenumitem = true;
  730. }
  731. reset = true;
  732. previous_ignored = false;
  733. }
  734. if (reset) {
  735. previous = enumvalue ? enumvalue : Getattr(c, "name");
  736. count = 0;
  737. } else {
  738. count++;
  739. }
  740. }
  741. }
  742. emit_children(n);
  743. return SWIG_OK;
  744. }
  745. /* ------------------------------------------------------------
  746. * enumvalueDeclaration()
  747. * ------------------------------------------------------------ */
  748. virtual int enumvalueDeclaration(Node *n) {
  749. String *name = Getattr(n, "name");
  750. String *value = Getattr(n, "value");
  751. if (!value)
  752. value = name;
  753. if (Strcmp(value, name) == 0) {
  754. String *new_value;
  755. if ((nsname || inclass) && cparse_cplusplus) {
  756. new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
  757. } else {
  758. new_value = NewString(value);
  759. }
  760. if ((nsname || inclass) && !cparse_cplusplus) {
  761. String *cppvalue = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
  762. Setattr(n, "cppvalue", cppvalue); /* for target languages that always generate C++ code even when wrapping C code */
  763. }
  764. Setattr(n, "value", new_value);
  765. Delete(new_value);
  766. }
  767. Node *next = nextSibling(n);
  768. // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead)
  769. if (!GetFlag(n, "feature:ignore")) {
  770. if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set)
  771. Setattr(n, "enumvalueex", "0");
  772. }
  773. if (next && !Getattr(next, "enumvalue")) {
  774. Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name")));
  775. }
  776. }
  777. return SWIG_OK;
  778. }
  779. /* ------------------------------------------------------------
  780. * enumforwardDeclaration()
  781. * ------------------------------------------------------------ */
  782. virtual int enumforwardDeclaration(Node *n) {
  783. // Use enumDeclaration() to do all the hard work.
  784. // Note that no children can be emitted in a forward declaration as there aren't any.
  785. return enumDeclaration(n);
  786. }
  787. #ifdef DEBUG_OVERLOADED
  788. static void show_overloaded(Node *n) {
  789. Node *c = Getattr(n, "sym:overloaded");
  790. Node *checkoverloaded = c;
  791. Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c);
  792. while (c) {
  793. if (Getattr(c, "error")) {
  794. c = Getattr(c, "sym:nextSibling");
  795. continue;
  796. }
  797. if (Getattr(c, "sym:overloaded") != checkoverloaded) {
  798. Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded);
  799. Swig_print_node(c);
  800. exit (1);
  801. }
  802. String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl");
  803. Printf(stdout, " show_overloaded %s::%s(%s) [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c));
  804. if (!Getattr(c, "sym:overloaded")) {
  805. Printf(stdout, "sym:overloaded error.....%p\n", c);
  806. Swig_print_node(c);
  807. exit (1);
  808. }
  809. c = Getattr(c, "sym:nextSibling");
  810. }
  811. Printf(stdout, "-------------------- overloaded end %s -------------------------------\n", Getattr(n, "name"));
  812. }
  813. #endif
  814. /* ------------------------------------------------------------
  815. * usingDeclaration()
  816. * ------------------------------------------------------------ */
  817. virtual int usingDeclaration(Node *n) {
  818. if (Getattr(n, "namespace")) {
  819. /* using namespace id */
  820. /* For a namespace import. We set up inheritance in the type system */
  821. Node *ns = Getattr(n, "node");
  822. if (ns) {
  823. Typetab *ts = Getattr(ns, "typescope");
  824. if (ts) {
  825. SwigType_using_scope(ts);
  826. }
  827. }
  828. return SWIG_OK;
  829. } else {
  830. Node *ns;
  831. /* using id */
  832. Symtab *stab = Getattr(n, "sym:symtab");
  833. if (stab) {
  834. String *uname = Getattr(n, "uname");
  835. ns = Swig_symbol_clookup(uname, stab);
  836. if (!ns && SwigType_istemplate(uname)) {
  837. String *tmp = Swig_symbol_template_deftype(uname, 0);
  838. if (!Equal(tmp, uname)) {
  839. ns = Swig_symbol_clookup(tmp, stab);
  840. }
  841. Delete(tmp);
  842. }
  843. } else {
  844. ns = 0;
  845. }
  846. if (!ns) {
  847. if (is_public(n)) {
  848. Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname")));
  849. }
  850. } else {
  851. /* Only a single symbol is being used. There are only a few symbols that
  852. we actually care about. These are typedef, class declarations, and enum */
  853. String *ntype = nodeType(ns);
  854. if (Strcmp(ntype, "cdecl") == 0) {
  855. if (checkAttribute(ns, "storage", "typedef")) {
  856. /* A typedef declaration */
  857. String *uname = Getattr(n, "uname");
  858. SwigType_typedef_using(uname);
  859. } else {
  860. /* A normal C declaration. */
  861. if ((inclass) && (!GetFlag(n, "feature:ignore")) && (Getattr(n, "sym:name"))) {
  862. Node *c = ns;
  863. Node *unodes = 0, *last_unodes = 0;
  864. int ccount = 0;
  865. String *symname = Getattr(n, "sym:name");
  866. while (c) {
  867. if (Strcmp(nodeType(c), "cdecl") == 0) {
  868. if (!(checkAttribute(c, "storage", "static")
  869. || checkAttribute(c, "storage", "typedef")
  870. || checkAttribute(c, "storage", "friend")
  871. || (Getattr(c, "feature:extend") && !Getattr(c, "code"))
  872. || GetFlag(c, "feature:ignore"))) {
  873. /* Don't generate a method if the method is overridden in this class,
  874. * for example don't generate another m(bool) should there be a Base::m(bool) :
  875. * struct Derived : Base {
  876. * void m(bool);
  877. * using Base::m;
  878. * };
  879. */
  880. String *csymname = Getattr(c, "sym:name");
  881. if (!csymname || (Strcmp(csymname, symname) == 0)) {
  882. {
  883. String *decl = Getattr(c, "decl");
  884. Node *over = Getattr(n, "sym:overloaded");
  885. int match = 0;
  886. while (over) {
  887. String *odecl = Getattr(over, "decl");
  888. if (Cmp(decl, odecl) == 0) {
  889. match = 1;
  890. break;
  891. }
  892. over = Getattr(over, "sym:nextSibling");
  893. }
  894. if (match) {
  895. c = Getattr(c, "csym:nextSibling");
  896. continue;
  897. }
  898. }
  899. Node *nn = copyNode(c);
  900. Delattr(nn, "access"); // access might be different from the method in the base class
  901. Setattr(nn, "access", Getattr(n, "access"));
  902. if (!Getattr(nn, "sym:name"))
  903. Setattr(nn, "sym:name", symname);
  904. if (!GetFlag(nn, "feature:ignore")) {
  905. ParmList *parms = CopyParmList(Getattr(c, "parms"));
  906. int is_pointer = SwigType_ispointer_return(Getattr(nn, "decl"));
  907. int is_void = checkAttribute(nn, "type", "void") && !is_pointer;
  908. Setattr(nn, "parms", parms);
  909. Delete(parms);
  910. if (Getattr(n, "feature:extend")) {
  911. String *ucode = is_void ? NewStringf("{ self->%s(", Getattr(n, "uname")) : NewStringf("{ return self->%s(", Getattr(n, "uname"));
  912. for (ParmList *p = parms; p;) {
  913. Append(ucode, Getattr(p, "name"));
  914. p = nextSibling(p);
  915. if (p)
  916. Append(ucode, ",");
  917. }
  918. Append(ucode, "); }");
  919. Setattr(nn, "code", ucode);
  920. Delete(ucode);
  921. }
  922. ParmList *throw_parm_list = Getattr(c, "throws");
  923. if (throw_parm_list)
  924. Setattr(nn, "throws", CopyParmList(throw_parm_list));
  925. ccount++;
  926. if (!last_unodes) {
  927. last_unodes = nn;
  928. unodes = nn;
  929. } else {
  930. Setattr(nn, "previousSibling", last_unodes);
  931. Setattr(last_unodes, "nextSibling", nn);
  932. Setattr(nn, "sym:previousSibling", last_unodes);
  933. Setattr(last_unodes, "sym:nextSibling", nn);
  934. Setattr(nn, "sym:overloaded", unodes);
  935. Setattr(unodes, "sym:overloaded", unodes);
  936. last_unodes = nn;
  937. }
  938. } else {
  939. Delete(nn);
  940. }
  941. }
  942. }
  943. }
  944. c = Getattr(c, "csym:nextSibling");
  945. }
  946. if (unodes) {
  947. set_firstChild(n, unodes);
  948. if (ccount > 1) {
  949. if (!Getattr(n, "sym:overloaded")) {
  950. Setattr(n, "sym:overloaded", n);
  951. Setattr(n, "sym:overname", "_SWIG_0");
  952. }
  953. }
  954. }
  955. /* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the
  956. * list of overloaded methods we have just added in as child nodes to the "using" node.
  957. * The node will still exist, it is just the symbol table linked list of overloaded methods
  958. * which is hacked. */
  959. if (Getattr(n, "sym:overloaded"))
  960. {
  961. #ifdef DEBUG_OVERLOADED
  962. show_overloaded(n);
  963. #endif
  964. int cnt = 0;
  965. Node *debugnode = n;
  966. if (!firstChild(n)) {
  967. // Remove from overloaded list ('using' node does not actually end up adding in any methods)
  968. Node *ps = Getattr(n, "sym:previousSibling");
  969. Node *ns = Getattr(n, "sym:nextSibling");
  970. if (ps) {
  971. Setattr(ps, "sym:nextSibling", ns);
  972. }
  973. if (ns) {
  974. Setattr(ns, "sym:previousSibling", ps);
  975. }
  976. } else {
  977. // The 'using' node results in methods being added in - slot in the these methods here
  978. Node *ps = Getattr(n, "sym:previousSibling");
  979. Node *ns = Getattr(n, "sym:nextSibling");
  980. Node *fc = firstChild(n);
  981. Node *pp = fc;
  982. Node *firstoverloaded = Getattr(n, "sym:overloaded");
  983. if (firstoverloaded == n) {
  984. // This 'using' node we are cutting out was the first node in the overloaded list.
  985. // Change the first node in the list to its first sibling
  986. Delattr(firstoverloaded, "sym:overloaded");
  987. Node *nnn = Getattr(firstoverloaded, "sym:nextSibling");
  988. firstoverloaded = fc;
  989. while (nnn) {
  990. Setattr(nnn, "sym:overloaded", firstoverloaded);
  991. nnn = Getattr(nnn, "sym:nextSibling");
  992. }
  993. }
  994. while (pp) {
  995. Node *ppn = Getattr(pp, "sym:nextSibling");
  996. Setattr(pp, "sym:overloaded", firstoverloaded);
  997. Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++));
  998. if (ppn)
  999. pp = ppn;
  1000. else
  1001. break;
  1002. }
  1003. if (ps) {
  1004. Setattr(ps, "sym:nextSibling", fc);
  1005. Setattr(fc, "sym:previousSibling", ps);
  1006. }
  1007. if (ns) {
  1008. Setattr(ns, "sym:previousSibling", pp);
  1009. Setattr(pp, "sym:nextSibling", ns);
  1010. }
  1011. debugnode = firstoverloaded;
  1012. }
  1013. Delattr(n, "sym:previousSibling");
  1014. Delattr(n, "sym:nextSibling");
  1015. Delattr(n, "sym:overloaded");
  1016. Delattr(n, "sym:overname");
  1017. #ifdef DEBUG_OVERLOADED
  1018. show_overloaded(debugnode);
  1019. #endif
  1020. clean_overloaded(n); // Needed?
  1021. }
  1022. }
  1023. }
  1024. } else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {
  1025. /* We install the using class name as kind of a typedef back to the original class */
  1026. String *uname = Getattr(n, "uname");
  1027. /* Import into current type scope */
  1028. SwigType_typedef_using(uname);
  1029. } else if (Strcmp(ntype, "enum") == 0) {
  1030. SwigType_typedef_using(Getattr(n, "uname"));
  1031. }
  1032. }
  1033. }
  1034. return SWIG_OK;
  1035. }
  1036. /* ------------------------------------------------------------
  1037. * typemapDirective()
  1038. * ------------------------------------------------------------ */
  1039. virtual int typemapDirective(Node *n) {
  1040. if (inclass || nsname) {
  1041. Node *items = firstChild(n);
  1042. while (items) {
  1043. Parm *pattern = Getattr(items, "pattern");
  1044. Parm *parms = Getattr(items, "parms");
  1045. normalize_later(pattern);
  1046. normalize_later(parms);
  1047. items = nextSibling(items);
  1048. }
  1049. }
  1050. return SWIG_OK;
  1051. }
  1052. /* ------------------------------------------------------------
  1053. * typemapcopyDirective()
  1054. * ------------------------------------------------------------ */
  1055. virtual int typemapcopyDirective(Node *n) {
  1056. if (inclass || nsname) {
  1057. Node *items = firstChild(n);
  1058. ParmList *pattern = Getattr(n, "pattern");
  1059. normalize_later(pattern);
  1060. while (items) {
  1061. ParmList *npattern = Getattr(items, "pattern");
  1062. normalize_later(npattern);
  1063. items = nextSibling(items);
  1064. }
  1065. }
  1066. return SWIG_OK;
  1067. }
  1068. /* ------------------------------------------------------------
  1069. * applyDirective()
  1070. * ------------------------------------------------------------ */
  1071. virtual int applyDirective(Node *n) {
  1072. if (inclass || nsname) {
  1073. ParmList *pattern = Getattr(n, "pattern");
  1074. normalize_later(pattern);
  1075. Node *items = firstChild(n);
  1076. while (items) {
  1077. Parm *apattern = Getattr(items, "pattern");
  1078. normalize_later(apattern);
  1079. items = nextSibling(items);
  1080. }
  1081. }
  1082. return SWIG_OK;
  1083. }
  1084. /* ------------------------------------------------------------
  1085. * clearDirective()
  1086. * ------------------------------------------------------------ */
  1087. virtual int clearDirective(Node *n) {
  1088. if (inclass || nsname) {
  1089. Node *p;
  1090. for (p = firstChild(n); p; p = nextSibling(p)) {
  1091. ParmList *pattern = Getattr(p, "pattern");
  1092. normalize_later(pattern);
  1093. }
  1094. }
  1095. return SWIG_OK;
  1096. }
  1097. public:
  1098. static void pass(Node *n) {
  1099. TypePass t;
  1100. t.top(n);
  1101. }
  1102. };
  1103. void Swig_process_types(Node *n) {
  1104. if (!n)
  1105. return;
  1106. TypePass::pass(n);
  1107. }