PageRenderTime 79ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Swig/wrapfunc.c

#
C | 522 lines | 407 code | 38 blank | 77 comment | 194 complexity | f6fe51a560dd762dc0515990589f2711 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. * wrapfunc.c
  10. *
  11. * This file defines a object for creating wrapper functions. Primarily
  12. * this is used for convenience since it allows pieces of a wrapper function
  13. * to be created in a piecemeal manner.
  14. * ----------------------------------------------------------------------------- */
  15. char cvsroot_wrapfunc_c[] = "$Id: wrapfunc.c 11876 2010-02-27 23:53:33Z wsfulton $";
  16. #include "swig.h"
  17. #include <ctype.h>
  18. static int Compact_mode = 0; /* set to 0 on default */
  19. static int Max_line_size = 128;
  20. /* -----------------------------------------------------------------------------
  21. * NewWrapper()
  22. *
  23. * Create a new wrapper function object.
  24. * ----------------------------------------------------------------------------- */
  25. Wrapper *NewWrapper(void) {
  26. Wrapper *w;
  27. w = (Wrapper *) malloc(sizeof(Wrapper));
  28. w->localh = NewHash();
  29. w->locals = NewStringEmpty();
  30. w->code = NewStringEmpty();
  31. w->def = NewStringEmpty();
  32. return w;
  33. }
  34. /* -----------------------------------------------------------------------------
  35. * DelWrapper()
  36. *
  37. * Delete a wrapper function object.
  38. * ----------------------------------------------------------------------------- */
  39. void DelWrapper(Wrapper *w) {
  40. Delete(w->localh);
  41. Delete(w->locals);
  42. Delete(w->code);
  43. Delete(w->def);
  44. free(w);
  45. }
  46. /* -----------------------------------------------------------------------------
  47. * Wrapper_compact_print_mode_set()
  48. *
  49. * Set compact_mode.
  50. * ----------------------------------------------------------------------------- */
  51. void Wrapper_compact_print_mode_set(int flag) {
  52. Compact_mode = flag;
  53. }
  54. /* -----------------------------------------------------------------------------
  55. * Wrapper_pretty_print()
  56. *
  57. * Formats a wrapper function and fixes up the indentation.
  58. * ----------------------------------------------------------------------------- */
  59. void Wrapper_pretty_print(String *str, File *f) {
  60. String *ts;
  61. int level = 0;
  62. int c, i;
  63. int empty = 1;
  64. int indent = 2;
  65. int plevel = 0;
  66. int label = 0;
  67. ts = NewStringEmpty();
  68. Seek(str, 0, SEEK_SET);
  69. while ((c = Getc(str)) != EOF) {
  70. if (c == '\"') {
  71. Putc(c, ts);
  72. while ((c = Getc(str)) != EOF) {
  73. if (c == '\\') {
  74. Putc(c, ts);
  75. c = Getc(str);
  76. }
  77. Putc(c, ts);
  78. if (c == '\"')
  79. break;
  80. }
  81. empty = 0;
  82. } else if (c == '\'') {
  83. Putc(c, ts);
  84. while ((c = Getc(str)) != EOF) {
  85. if (c == '\\') {
  86. Putc(c, ts);
  87. c = Getc(str);
  88. }
  89. Putc(c, ts);
  90. if (c == '\'')
  91. break;
  92. }
  93. empty = 0;
  94. } else if (c == ':') {
  95. Putc(c, ts);
  96. if ((c = Getc(str)) == '\n') {
  97. if (!empty && !strchr(Char(ts), '?'))
  98. label = 1;
  99. }
  100. Ungetc(c, str);
  101. } else if (c == '(') {
  102. Putc(c, ts);
  103. plevel += indent;
  104. empty = 0;
  105. } else if (c == ')') {
  106. Putc(c, ts);
  107. plevel -= indent;
  108. empty = 0;
  109. } else if (c == '{') {
  110. Putc(c, ts);
  111. Putc('\n', ts);
  112. for (i = 0; i < level; i++)
  113. Putc(' ', f);
  114. Printf(f, "%s", ts);
  115. Clear(ts);
  116. level += indent;
  117. while ((c = Getc(str)) != EOF) {
  118. if (!isspace(c)) {
  119. Ungetc(c, str);
  120. break;
  121. }
  122. }
  123. empty = 0;
  124. } else if (c == '}') {
  125. if (!empty) {
  126. Putc('\n', ts);
  127. for (i = 0; i < level; i++)
  128. Putc(' ', f);
  129. Printf(f, "%s", ts);
  130. Clear(ts);
  131. }
  132. level -= indent;
  133. Putc(c, ts);
  134. empty = 0;
  135. } else if (c == '\n') {
  136. Putc(c, ts);
  137. empty = 0;
  138. if (!empty) {
  139. int slevel = level;
  140. if (label && (slevel >= indent))
  141. slevel -= indent;
  142. if ((Char(ts))[0] != '#') {
  143. for (i = 0; i < slevel; i++)
  144. Putc(' ', f);
  145. }
  146. Printf(f, "%s", ts);
  147. for (i = 0; i < plevel; i++)
  148. Putc(' ', f);
  149. }
  150. Clear(ts);
  151. label = 0;
  152. empty = 1;
  153. } else if (c == '/') {
  154. empty = 0;
  155. Putc(c, ts);
  156. c = Getc(str);
  157. if (c != EOF) {
  158. Putc(c, ts);
  159. if (c == '/') { /* C++ comment */
  160. while ((c = Getc(str)) != EOF) {
  161. if (c == '\n') {
  162. Ungetc(c, str);
  163. break;
  164. }
  165. Putc(c, ts);
  166. }
  167. } else if (c == '*') { /* C comment */
  168. int endstar = 0;
  169. while ((c = Getc(str)) != EOF) {
  170. if (endstar && c == '/') { /* end of C comment */
  171. Putc(c, ts);
  172. break;
  173. }
  174. endstar = (c == '*');
  175. Putc(c, ts);
  176. if (c == '\n') { /* multi-line C comment. Could be improved slightly. */
  177. for (i = 0; i < level; i++)
  178. Putc(' ', ts);
  179. }
  180. }
  181. }
  182. }
  183. } else {
  184. if (!empty || !isspace(c)) {
  185. Putc(c, ts);
  186. empty = 0;
  187. }
  188. }
  189. }
  190. if (!empty)
  191. Printf(f, "%s", ts);
  192. Delete(ts);
  193. Printf(f, "\n");
  194. }
  195. /* -----------------------------------------------------------------------------
  196. * Wrapper_compact_print()
  197. *
  198. * Formats a wrapper function and fixes up the indentation.
  199. * Print out in compact format, with Compact enabled.
  200. * ----------------------------------------------------------------------------- */
  201. void Wrapper_compact_print(String *str, File *f) {
  202. String *ts, *tf; /*temp string & temp file */
  203. int level = 0;
  204. int c, i;
  205. int empty = 1;
  206. int indent = 2;
  207. ts = NewStringEmpty();
  208. tf = NewStringEmpty();
  209. Seek(str, 0, SEEK_SET);
  210. while ((c = Getc(str)) != EOF) {
  211. if (c == '\"') { /* string 1 */
  212. empty = 0;
  213. Putc(c, ts);
  214. while ((c = Getc(str)) != EOF) {
  215. if (c == '\\') {
  216. Putc(c, ts);
  217. c = Getc(str);
  218. }
  219. Putc(c, ts);
  220. if (c == '\"')
  221. break;
  222. }
  223. } else if (c == '\'') { /* string 2 */
  224. empty = 0;
  225. Putc(c, ts);
  226. while ((c = Getc(str)) != EOF) {
  227. if (c == '\\') {
  228. Putc(c, ts);
  229. c = Getc(str);
  230. }
  231. Putc(c, ts);
  232. if (c == '\'')
  233. break;
  234. }
  235. } else if (c == '{') { /* start of {...} */
  236. empty = 0;
  237. Putc(c, ts);
  238. if (Len(tf) == 0) {
  239. for (i = 0; i < level; i++)
  240. Putc(' ', tf);
  241. } else if ((Len(tf) + Len(ts)) < Max_line_size) {
  242. Putc(' ', tf);
  243. } else {
  244. Putc('\n', tf);
  245. Printf(f, "%s", tf);
  246. Clear(tf);
  247. for (i = 0; i < level; i++)
  248. Putc(' ', tf);
  249. }
  250. Append(tf, ts);
  251. Clear(ts);
  252. level += indent;
  253. while ((c = Getc(str)) != EOF) {
  254. if (!isspace(c)) {
  255. Ungetc(c, str);
  256. break;
  257. }
  258. }
  259. } else if (c == '}') { /* end of {...} */
  260. empty = 0;
  261. if (Len(tf) == 0) {
  262. for (i = 0; i < level; i++)
  263. Putc(' ', tf);
  264. } else if ((Len(tf) + Len(ts)) < Max_line_size) {
  265. Putc(' ', tf);
  266. } else {
  267. Putc('\n', tf);
  268. Printf(f, "%s", tf);
  269. Clear(tf);
  270. for (i = 0; i < level; i++)
  271. Putc(' ', tf);
  272. }
  273. Append(tf, ts);
  274. Putc(c, tf);
  275. Clear(ts);
  276. level -= indent;
  277. } else if (c == '\n') { /* line end */
  278. while ((c = Getc(str)) != EOF) {
  279. if (!isspace(c))
  280. break;
  281. }
  282. if (c == '#') {
  283. Putc('\n', ts);
  284. } else if (c == '}') {
  285. Putc(' ', ts);
  286. } else if ((c != EOF) || (Len(ts) != 0)) {
  287. if (Len(tf) == 0) {
  288. for (i = 0; i < level; i++)
  289. Putc(' ', tf);
  290. } else if ((Len(tf) + Len(ts)) < Max_line_size) {
  291. Putc(' ', tf);
  292. } else {
  293. Putc('\n', tf);
  294. Printf(f, "%s", tf);
  295. Clear(tf);
  296. for (i = 0; i < level; i++)
  297. Putc(' ', tf);
  298. }
  299. Append(tf, ts);
  300. Clear(ts);
  301. }
  302. Ungetc(c, str);
  303. empty = 1;
  304. } else if (c == '/') { /* comment */
  305. empty = 0;
  306. c = Getc(str);
  307. if (c != EOF) {
  308. if (c == '/') { /* C++ comment */
  309. while ((c = Getc(str)) != EOF) {
  310. if (c == '\n') {
  311. Ungetc(c, str);
  312. break;
  313. }
  314. }
  315. } else if (c == '*') { /* C comment */
  316. int endstar = 0;
  317. while ((c = Getc(str)) != EOF) {
  318. if (endstar && c == '/') { /* end of C comment */
  319. break;
  320. }
  321. endstar = (c == '*');
  322. }
  323. } else {
  324. Putc('/', ts);
  325. Putc(c, ts);
  326. }
  327. }
  328. } else if (c == '#') { /* Preprocessor line */
  329. Putc('#', ts);
  330. while ((c = Getc(str)) != EOF) {
  331. Putc(c, ts);
  332. if (c == '\\') { /* Continued line of the same PP */
  333. c = Getc(str);
  334. if (c == '\n')
  335. Putc(c, ts);
  336. else
  337. Ungetc(c, str);
  338. } else if (c == '\n')
  339. break;
  340. }
  341. if (!empty) {
  342. Append(tf, "\n");
  343. }
  344. Append(tf, ts);
  345. Printf(f, "%s", tf);
  346. Clear(tf);
  347. Clear(ts);
  348. for (i = 0; i < level; i++)
  349. Putc(' ', tf);
  350. empty = 1;
  351. } else {
  352. if (!empty || !isspace(c)) {
  353. Putc(c, ts);
  354. empty = 0;
  355. }
  356. }
  357. }
  358. if (!empty) {
  359. Append(tf, ts);
  360. }
  361. if (Len(tf) != 0)
  362. Printf(f, "%s", tf);
  363. Delete(ts);
  364. Delete(tf);
  365. Printf(f, "\n");
  366. }
  367. /* -----------------------------------------------------------------------------
  368. * Wrapper_print()
  369. *
  370. * Print out a wrapper function. Does pretty or compact printing as well.
  371. * ----------------------------------------------------------------------------- */
  372. void Wrapper_print(Wrapper *w, File *f) {
  373. String *str;
  374. str = NewStringEmpty();
  375. Printf(str, "%s\n", w->def);
  376. Printf(str, "%s\n", w->locals);
  377. Printf(str, "%s\n", w->code);
  378. if (Compact_mode == 1)
  379. Wrapper_compact_print(str, f);
  380. else
  381. Wrapper_pretty_print(str, f);
  382. Delete(str);
  383. }
  384. /* -----------------------------------------------------------------------------
  385. * Wrapper_add_local()
  386. *
  387. * Adds a new local variable declaration to a function. Returns -1 if already
  388. * present (which may or may not be okay to the caller).
  389. * ----------------------------------------------------------------------------- */
  390. int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
  391. /* See if the local has already been declared */
  392. if (Getattr(w->localh, name)) {
  393. return -1;
  394. }
  395. Setattr(w->localh, name, decl);
  396. Printf(w->locals, "%s;\n", decl);
  397. return 0;
  398. }
  399. /* -----------------------------------------------------------------------------
  400. * Wrapper_add_localv()
  401. *
  402. * Same as add_local(), but allows a NULL terminated list of strings to be
  403. * used as a replacement for decl. This saves the caller the trouble of having
  404. * to manually construct the 'decl' string before calling.
  405. * ----------------------------------------------------------------------------- */
  406. int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
  407. va_list ap;
  408. int ret;
  409. String *decl;
  410. DOH *obj;
  411. decl = NewStringEmpty();
  412. va_start(ap, name);
  413. obj = va_arg(ap, void *);
  414. while (obj) {
  415. Append(decl, obj);
  416. Putc(' ', decl);
  417. obj = va_arg(ap, void *);
  418. }
  419. va_end(ap);
  420. ret = Wrapper_add_local(w, name, decl);
  421. Delete(decl);
  422. return ret;
  423. }
  424. /* -----------------------------------------------------------------------------
  425. * Wrapper_check_local()
  426. *
  427. * Check to see if a local name has already been declared
  428. * ----------------------------------------------------------------------------- */
  429. int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
  430. if (Getattr(w->localh, name)) {
  431. return 1;
  432. }
  433. return 0;
  434. }
  435. /* -----------------------------------------------------------------------------
  436. * Wrapper_new_local()
  437. *
  438. * Adds a new local variable with a guarantee that a unique local name will be
  439. * used. Returns the name that was actually selected.
  440. * ----------------------------------------------------------------------------- */
  441. char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
  442. int i;
  443. String *nname = NewString(name);
  444. String *ndecl = NewString(decl);
  445. char *ret;
  446. i = 0;
  447. while (Wrapper_check_local(w, nname)) {
  448. Clear(nname);
  449. Printf(nname, "%s%d", name, i);
  450. i++;
  451. }
  452. Replace(ndecl, name, nname, DOH_REPLACE_ID);
  453. Setattr(w->localh, nname, ndecl);
  454. Printf(w->locals, "%s;\n", ndecl);
  455. ret = Char(nname);
  456. Delete(nname);
  457. Delete(ndecl);
  458. return ret; /* Note: nname should still exists in the w->localh hash */
  459. }
  460. /* -----------------------------------------------------------------------------
  461. * Wrapper_new_localv()
  462. *
  463. * Same as add_local(), but allows a NULL terminated list of strings to be
  464. * used as a replacement for decl. This saves the caller the trouble of having
  465. * to manually construct the 'decl' string before calling.
  466. * ----------------------------------------------------------------------------- */
  467. char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
  468. va_list ap;
  469. char *ret;
  470. String *decl;
  471. DOH *obj;
  472. decl = NewStringEmpty();
  473. va_start(ap, name);
  474. obj = va_arg(ap, void *);
  475. while (obj) {
  476. Append(decl, obj);
  477. Putc(' ', decl);
  478. obj = va_arg(ap, void *);
  479. }
  480. va_end(ap);
  481. ret = Wrapper_new_local(w, name, decl);
  482. Delete(decl);
  483. return ret;
  484. }