PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/rel-1-3-26/SWIG/Source/CParse/templ.c

#
C | 645 lines | 509 code | 64 blank | 72 comment | 125 complexity | 687209f59e65cbe14db96bc2cb2c29d6 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * templ.c
  3. *
  4. * Expands a template into a specialized version.
  5. *
  6. * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  7. *
  8. * Copyright (C) 1999-2000. The University of Chicago
  9. * See the file LICENSE for information on usage and redistribution.
  10. * ----------------------------------------------------------------------------- */
  11. char cvsroot_templ_c[] = "$Header$";
  12. #include "swig.h"
  13. #include "cparse.h"
  14. static int template_debug = 0;
  15. static void add_parms(ParmList *p, List *patchlist, List *typelist) {
  16. while (p) {
  17. SwigType *ty = Getattr(p,"type");
  18. SwigType *val = Getattr(p,"value");
  19. Append(typelist,ty);
  20. Append(typelist,val);
  21. Append(patchlist,val);
  22. p = nextSibling(p);
  23. }
  24. }
  25. void Swig_cparse_debug_templates(int x) {
  26. template_debug = x;
  27. }
  28. /* -----------------------------------------------------------------------------
  29. * Swig_cparse_template_expand()
  30. *
  31. * Expands a template node into a specialized version. This is done by
  32. * patching typenames and other aspects of the node according to a list of
  33. * template parameters
  34. * ----------------------------------------------------------------------------- */
  35. static int
  36. cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) {
  37. static int expanded = 0;
  38. int ret;
  39. if (!n) return 0;
  40. if (Getattr(n,"error")) return 0;
  41. if (Strcmp(nodeType(n),"template") == 0) {
  42. /* Change the node type back to normal */
  43. if (!expanded) {
  44. expanded = 1;
  45. set_nodeType(n,Getattr(n,"templatetype"));
  46. ret = cparse_template_expand(n,tname, rname, templateargs, patchlist,typelist, cpatchlist);
  47. expanded = 0;
  48. return ret;
  49. } else {
  50. /* Called when template appears inside another template */
  51. /* Member templates */
  52. set_nodeType(n,Getattr(n,"templatetype"));
  53. ret = cparse_template_expand(n,tname, rname, templateargs, patchlist,typelist, cpatchlist);
  54. set_nodeType(n,"template");
  55. return ret;
  56. }
  57. } else if (Strcmp(nodeType(n),"cdecl") == 0) {
  58. /* A simple C declaration */
  59. SwigType *t, *v, *d;
  60. String *code;
  61. t = Getattr(n,"type");
  62. v = Getattr(n,"value");
  63. d = Getattr(n,"decl");
  64. code = Getattr(n,"code");
  65. Append(typelist,t);
  66. Append(typelist,d);
  67. Append(patchlist,v);
  68. Append(cpatchlist,code);
  69. if (Getattr(n,"conversion_operator")) {
  70. Append(cpatchlist, Getattr(n,"name"));
  71. if (Getattr(n,"sym:name")) {
  72. Append(cpatchlist, Getattr(n,"sym:name"));
  73. }
  74. }
  75. add_parms(Getattr(n,"parms"), cpatchlist, typelist);
  76. add_parms(Getattr(n,"throws"), cpatchlist, typelist);
  77. } else if (Strcmp(nodeType(n),"class") == 0) {
  78. /* Patch base classes */
  79. {
  80. char *baselists[] = {"baselist","protectedbaselist","privatebaselist"};
  81. int b = 0;
  82. for (b = 0; b < 3; ++b) {
  83. List *bases = Getattr(n,baselists[b]);
  84. if (bases) {
  85. int i;
  86. for (i = 0; i < Len(bases); i++) {
  87. String *name = Copy(Getitem(bases,i));
  88. Setitem(bases,i,name);
  89. Append(typelist,name);
  90. }
  91. }
  92. }
  93. }
  94. /* Patch children */
  95. {
  96. Node *cn = firstChild(n);
  97. while (cn) {
  98. cparse_template_expand(cn,tname, rname, templateargs, patchlist,typelist,cpatchlist);
  99. cn = nextSibling(cn);
  100. }
  101. }
  102. } else if (Strcmp(nodeType(n),"constructor") == 0) {
  103. String *name = Getattr(n,"name");
  104. if (!(Getattr(n,"templatetype"))) {
  105. String *symname;
  106. String *stripped_name = SwigType_templateprefix(name);
  107. if (Strstr(tname,stripped_name)) {
  108. Replaceid(name,stripped_name,tname);
  109. }
  110. Delete(stripped_name);
  111. symname = Getattr(n,"sym:name");
  112. if (symname) {
  113. stripped_name = SwigType_templateprefix(symname);
  114. if (Strstr(tname,stripped_name)) {
  115. Replaceid(symname,stripped_name,tname);
  116. }
  117. Delete(stripped_name);
  118. }
  119. if (Strstr(name,"<")) {
  120. Append(patchlist,Getattr(n,"name"));
  121. } else {
  122. Append(name,templateargs);
  123. }
  124. name = Getattr(n,"sym:name");
  125. if (name && (Strstr(name,"<"))) {
  126. Clear(name);
  127. Append(name,rname);
  128. } else {
  129. Replace(name,tname,rname, DOH_REPLACE_ANY);
  130. }
  131. Setattr(n,"sym:name",name);
  132. }
  133. Append(cpatchlist,Getattr(n,"code"));
  134. Append(typelist, Getattr(n,"decl"));
  135. add_parms(Getattr(n,"parms"), cpatchlist, typelist);
  136. add_parms(Getattr(n,"throws"), cpatchlist, typelist);
  137. } else if (Strcmp(nodeType(n),"destructor") == 0) {
  138. String *name = Getattr(n,"name");
  139. if (Strstr(name,"<")) {
  140. Append(patchlist,Getattr(n,"name"));
  141. } else {
  142. Append(name,templateargs);
  143. }
  144. name = Getattr(n,"sym:name");
  145. if (name && Strstr(name,"<")) {
  146. String *sn = Copy(tname);
  147. Setattr(n,"sym:name", sn);
  148. Delete(sn);
  149. } else {
  150. Replace(name,tname,rname, DOH_REPLACE_ANY);
  151. }
  152. Setattr(n,"sym:name",name);
  153. Append(cpatchlist,Getattr(n,"code"));
  154. } else if (Strcmp(nodeType(n),"using") == 0) {
  155. String *uname = Getattr(n,"uname");
  156. if (uname) {
  157. if (Strstr(uname,"<")) {
  158. Append(patchlist, uname);
  159. }
  160. }
  161. if (Getattr(n,"namespace")) {
  162. /* Namespace link. This is nasty. Is other namespace defined? */
  163. }
  164. } else {
  165. /* Look for obvious parameters */
  166. Node *cn;
  167. Append(cpatchlist,Getattr(n,"code"));
  168. Append(typelist, Getattr(n,"type"));
  169. Append(typelist, Getattr(n,"decl"));
  170. add_parms(Getattr(n,"parms"), cpatchlist, typelist);
  171. add_parms(Getattr(n,"kwargs"), cpatchlist, typelist);
  172. add_parms(Getattr(n,"pattern"), cpatchlist, typelist);
  173. add_parms(Getattr(n,"throws"), cpatchlist, typelist);
  174. cn = firstChild(n);
  175. while (cn) {
  176. cparse_template_expand(cn,tname, rname, templateargs, patchlist, typelist, cpatchlist);
  177. cn = nextSibling(cn);
  178. }
  179. }
  180. return 0;
  181. }
  182. static
  183. String *partial_arg(String *s, String *p) {
  184. char *c;
  185. String *prefix;
  186. String *newarg;
  187. /* Find the prefix on the partial argument */
  188. c = Strstr(p,"$");
  189. if (!c) {
  190. return NewString(s);
  191. }
  192. prefix = NewStringWithSize(Char(p),c-Char(p));
  193. newarg = NewString(s);
  194. Replace(newarg,prefix,"",DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
  195. Delete(prefix);
  196. return newarg;
  197. }
  198. int
  199. Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope) {
  200. List *patchlist, *cpatchlist, *typelist;
  201. String *templateargs;
  202. String *tname;
  203. String *iname;
  204. String *tbase;
  205. patchlist = NewList();
  206. cpatchlist = NewList();
  207. typelist = NewList();
  208. {
  209. String *tmp = NewString("");
  210. if (tparms) {
  211. SwigType_add_template(tmp,tparms);
  212. }
  213. templateargs = Copy(tmp);
  214. Delete(tmp);
  215. }
  216. tname = Copy(Getattr(n,"name"));
  217. tbase = Swig_scopename_last(tname);
  218. /* Look for partial specialization matching */
  219. if (Getattr(n,"partialargs")) {
  220. Parm *p, *tp;
  221. ParmList *ptargs = SwigType_function_parms(Getattr(n,"partialargs"));
  222. p = ptargs;
  223. tp = tparms;
  224. while (p && tp) {
  225. SwigType *ptype;
  226. SwigType *tptype;
  227. SwigType *partial_type;
  228. ptype = Getattr(p,"type");
  229. tptype = Getattr(tp,"type");
  230. if (ptype && tptype) {
  231. partial_type = partial_arg(tptype,ptype);
  232. /* Printf(stdout,"partial '%s' '%s' ---> '%s'\n", tptype, ptype, partial_type); */
  233. Setattr(tp,"type",partial_type);
  234. Delete(partial_type);
  235. }
  236. p = nextSibling(p);
  237. tp = nextSibling(tp);
  238. }
  239. assert(ParmList_len(ptargs) == ParmList_len(tparms));
  240. Delete(ptargs);
  241. }
  242. if (0) {
  243. Parm *p = tparms;
  244. while (p) {
  245. Printf(stdout,"tparm: '%s' '%s' '%s'\n", Getattr(p,"name"), Getattr(p,"type"), Getattr(p,"value"));
  246. p = nextSibling(p);
  247. }
  248. }
  249. /* Printf(stdout,"targs = '%s'\n", templateargs);
  250. Printf(stdout,"rname = '%s'\n", rname);
  251. Printf(stdout,"tname = '%s'\n", tname); */
  252. cparse_template_expand(n,tname, rname, templateargs, patchlist, typelist, cpatchlist);
  253. /* Set the name */
  254. {
  255. String *name = Getattr(n,"name");
  256. if (name) {
  257. Append(name,templateargs);
  258. }
  259. iname = name;
  260. }
  261. /* Patch all of the types */
  262. {
  263. Parm *tp = Getattr(n,"templateparms");
  264. Parm *p = tparms;
  265. /* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
  266. if (tp) {
  267. Symtab *tsdecl = Getattr(n,"sym:symtab");
  268. while (p && tp) {
  269. String *name, *value, *valuestr, *tydef, *tmp, *tmpr;
  270. int sz, i;
  271. String *dvalue = 0;
  272. name = Getattr(tp,"name");
  273. value = Getattr(p,"value");
  274. tydef = Getattr(p,"typedef");
  275. if (name) {
  276. if (!value) value = Getattr(p,"type");
  277. dvalue = Swig_symbol_type_qualify(value,tsdecl);
  278. if (SwigType_istemplate(dvalue)) {
  279. String *ty = Swig_symbol_template_deftype(dvalue, tscope);
  280. Delete(dvalue);
  281. dvalue = ty;
  282. }
  283. assert(dvalue);
  284. valuestr = SwigType_str(dvalue,0);
  285. /* Need to patch default arguments */
  286. {
  287. Parm *rp = nextSibling(p);
  288. while (rp) {
  289. String *rvalue = Getattr(rp,"value");
  290. if (rvalue) {
  291. Replace(rvalue,name,dvalue, DOH_REPLACE_ID);
  292. }
  293. rp = nextSibling(rp);
  294. }
  295. }
  296. sz = Len(patchlist);
  297. for (i = 0; i < sz; i++) {
  298. String *s = Getitem(patchlist,i);
  299. Replace(s,name,dvalue, DOH_REPLACE_ID);
  300. }
  301. sz = Len(typelist);
  302. for (i = 0; i < sz; i++) {
  303. String *s = Getitem(typelist,i);
  304. /* Replace(s,name,value, DOH_REPLACE_ID); */
  305. /* Printf(stdout,"name = '%s', value = '%s', tbase = '%s', iname='%s' s = '%s' --> ", name, dvalue, tbase, iname, s); */
  306. SwigType_typename_replace(s,name,dvalue);
  307. SwigType_typename_replace(s,tbase,iname);
  308. /* Printf(stdout,"'%s'\n", s);*/
  309. }
  310. if (!tydef) {
  311. tydef = dvalue;
  312. }
  313. tmp = NewStringf("#%s",name);
  314. tmpr = NewStringf("\"%s\"", valuestr);
  315. sz = Len(cpatchlist);
  316. for (i = 0; i < sz; i++) {
  317. String *s = Getitem(cpatchlist,i);
  318. Replace(s,tmp,tmpr, DOH_REPLACE_ID);
  319. /* Replace(s,name,tydef, DOH_REPLACE_ID); */
  320. Replace(s,name,valuestr, DOH_REPLACE_ID);
  321. }
  322. Delete(tmp);
  323. Delete(tmpr);
  324. Delete(valuestr);
  325. Delete(dvalue);
  326. }
  327. p = nextSibling(p);
  328. tp = nextSibling(tp);
  329. if (!p) p = tp;
  330. }
  331. } else {
  332. /* No template parameters at all. This could be a specialization */
  333. int i, sz;
  334. sz = Len(typelist);
  335. for (i = 0; i < sz; i++) {
  336. String *s = Getitem(typelist,i);
  337. SwigType_typename_replace(s,tbase,iname);
  338. }
  339. }
  340. }
  341. /* Patch bases */
  342. {
  343. List *bases = Getattr(n,"baselist");
  344. if (bases) {
  345. Iterator b;
  346. for (b = First(bases); b.item; b = Next(b)) {
  347. String *qn = Swig_symbol_type_qualify(b.item,tscope);
  348. Clear(b.item);
  349. Append(b.item,qn);
  350. Delete(qn);
  351. }
  352. }
  353. }
  354. Delete(patchlist);
  355. Delete(cpatchlist);
  356. Delete(typelist);
  357. Delete(tbase);
  358. Delete(templateargs);
  359. /* set_nodeType(n,"template");*/
  360. return 0;
  361. }
  362. /* -----------------------------------------------------------------------------
  363. * template_locate()
  364. *
  365. * Search for a template that matches name with given parameters.
  366. * ----------------------------------------------------------------------------- */
  367. static Node *
  368. template_locate(String *name, Parm *tparms, Symtab *tscope) {
  369. Node *n;
  370. String *tname, *rname = 0;
  371. Node *templ;
  372. List *mpartials = 0;
  373. Parm *p;
  374. Parm *parms;
  375. Parm *targs;
  376. tname = NewString(name);
  377. parms = CopyParmList(tparms);
  378. /* Search for generic template */
  379. templ = Swig_symbol_clookup(name,0);
  380. /* Add default values from generic template */
  381. if (templ) {
  382. Symtab *tsdecl = Getattr(templ,"sym:symtab");
  383. targs = Getattr(templ,"templateparms");
  384. Swig_symbol_template_defargs(parms, targs, tscope, tsdecl);
  385. }
  386. /* reduce the typedef */
  387. p = parms;
  388. while (p) {
  389. SwigType *ty = Getattr(p,"type");
  390. if (ty) {
  391. SwigType *nt = Swig_symbol_type_qualify(ty,tscope);
  392. Setattr(p,"type",nt);
  393. Delete(nt);
  394. }
  395. p = nextSibling(p);
  396. }
  397. SwigType_add_template(tname,parms);
  398. if (template_debug) {
  399. Printf(stdout,"\n%s:%d: template_debug: Searching for %s\n", cparse_file, cparse_line, tname);
  400. }
  401. /* Search for an exact specialization.
  402. Example: template<> class name<int> { ... } */
  403. {
  404. if (template_debug) {
  405. Printf(stdout," searching: '%s' (exact specialization)\n", tname);
  406. }
  407. n = Swig_symbol_clookup_local(tname,0);
  408. if (!n) {
  409. SwigType *rname = Swig_symbol_typedef_reduce(tname,tscope);
  410. if (Strcmp(rname,tname)) {
  411. if (template_debug) {
  412. Printf(stdout," searching: '%s' (exact specialization)\n", rname);
  413. }
  414. n = Swig_symbol_clookup_local(rname,0);
  415. }
  416. Delete(rname);
  417. }
  418. if (n) {
  419. Node *tn;
  420. if (Strcmp(nodeType(n),"template") == 0) goto success;
  421. tn = Getattr(n,"template");
  422. if (tn) {
  423. n = tn;
  424. goto success; /* Previously wrapped by a template return that */
  425. }
  426. Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
  427. Delete(tname);
  428. Delete(parms);
  429. return 0; /* Found a match, but it's not a template of any kind. */
  430. }
  431. }
  432. /* Search for partial specialization.
  433. Example: template<typename T> class name<T *> { ... } */
  434. /* Generate reduced template name (stripped of extraneous pointers, etc.) */
  435. rname = NewStringf("%s<(",name);
  436. p = parms;
  437. while (p) {
  438. String *t;
  439. t = Getattr(p,"type");
  440. if (!t) t = Getattr(p,"value");
  441. if (t) {
  442. String *ty = Swig_symbol_typedef_reduce(t,tscope);
  443. String *tb = SwigType_base(ty);
  444. String *td = SwigType_default(ty);
  445. Replaceid(td,"enum SWIGTYPE",tb);
  446. Replaceid(td,"SWIGTYPE",tb);
  447. Printf(rname,"%s",td);
  448. Delete(tb);
  449. Delete(ty);
  450. Delete(td);
  451. }
  452. p = nextSibling(p);
  453. if (p) {
  454. Printf(rname,",");
  455. }
  456. }
  457. Printf(rname,")>");
  458. mpartials = NewList();
  459. if (templ) {
  460. /* First, we search using an exact type prototype */
  461. Parm *p;
  462. char tmp[32];
  463. int i;
  464. List *partials;
  465. String *ss;
  466. Iterator pi;
  467. partials = Getattr(templ,"partials");
  468. if (partials) {
  469. for (pi = First(partials); pi.item; pi = Next(pi)) {
  470. ss = Copy(pi.item);
  471. p = parms;
  472. i = 1;
  473. while (p) {
  474. String *t,*tn;
  475. sprintf(tmp,"$%d",i);
  476. t = Getattr(p,"type");
  477. if (!t) t = Getattr(p,"value");
  478. if (t) {
  479. String *ty = Swig_symbol_typedef_reduce(t,tscope);
  480. tn = SwigType_base(ty);
  481. Replaceid(ss,tmp,tn);
  482. Delete(tn);
  483. Delete(ty);
  484. }
  485. i++;
  486. p = nextSibling(p);
  487. }
  488. if (template_debug) {
  489. Printf(stdout," searching: '%s' (partial specialization - %s)\n", ss, pi.item);
  490. }
  491. if ((Strcmp(ss,tname) == 0) || (Strcmp(ss,rname) == 0)) {
  492. Append(mpartials,pi.item);
  493. }
  494. Delete(ss);
  495. }
  496. }
  497. }
  498. if (template_debug) {
  499. Printf(stdout," Matched partials: %s\n", mpartials);
  500. }
  501. if (Len(mpartials)) {
  502. String *s = Getitem(mpartials,0);
  503. n = Swig_symbol_clookup_local(s,0);
  504. if (Len(mpartials) > 1) {
  505. if (n) {
  506. Swig_warning(WARN_PARSE_TEMPLATE_AMBIG,cparse_file,cparse_line,
  507. "Instantiation of template '%s' is ambiguous,\n",
  508. SwigType_namestr(tname));
  509. Swig_warning(WARN_PARSE_TEMPLATE_AMBIG,Getfile(n),Getline(n),
  510. " instantiation '%s' is used.\n",
  511. SwigType_namestr(Getattr(n,"name")));
  512. }
  513. }
  514. }
  515. if (!n) {
  516. n = templ;
  517. }
  518. if (!n) {
  519. Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
  520. } else if (n && (Strcmp(nodeType(n),"template") != 0)) {
  521. Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
  522. n = 0;
  523. }
  524. success:
  525. Delete(tname);
  526. Delete(rname);
  527. Delete(mpartials);
  528. if ((template_debug) && (n)) {
  529. Printf(stdout,"Node: %p\n", n);
  530. Swig_print_node(n);
  531. }
  532. Delete(parms);
  533. return n;
  534. }
  535. /* -----------------------------------------------------------------------------
  536. * Swig_cparse_template_locate()
  537. *
  538. * Search for a template that matches name with given parameters.
  539. * For templated classes finds the specialized template should there be one.
  540. * For templated functions finds the unspecialized template even if a specialized
  541. * template exists.
  542. * ----------------------------------------------------------------------------- */
  543. Node *
  544. Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) {
  545. Node *n = 0;
  546. n = template_locate(name, tparms, tscope); /* this function does what we want for templated classes */
  547. if (n) {
  548. int isclass = 0;
  549. assert(Strcmp(nodeType(n),"template") == 0);
  550. isclass = (Strcmp(Getattr(n,"templatetype"),"class") == 0);
  551. if (!isclass) {
  552. /* If not a templated class we must have a templated function.
  553. The template found is not necessarily the one we want when dealing with templated
  554. functions. We don't want any specialized templated functions as they won't have
  555. the default parameters. Lets look for the unspecialized template. Also make sure
  556. the number of template parameters is correct as it is possible to overload a
  557. templated function with different numbers of template parameters. */
  558. if (template_debug) {
  559. Printf(stdout," Not a templated class, seeking most appropriate templated function\n");
  560. }
  561. n = Swig_symbol_clookup_local(name,0);
  562. while (n) {
  563. Parm *tparmsfound = Getattr(n,"templateparms");
  564. if (ParmList_len(tparms) == ParmList_len(tparmsfound)) {
  565. /* successful match */
  566. break;
  567. }
  568. /* repeat until we find a match with correct number of templated parameters */
  569. n = Getattr(n,"sym:nextSibling");
  570. }
  571. if (!n) {
  572. Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
  573. }
  574. if ((template_debug) && (n)) {
  575. Printf(stdout,"Templated function found: %p\n", n);
  576. Swig_print_node(n);
  577. }
  578. }
  579. }
  580. return n;
  581. }