/tags/rel-1-3-30rc1-afterbeautify/SWIG/Source/Preprocessor/cpp.c

# · C · 1855 lines · 1545 code · 131 blank · 179 comment · 563 complexity · de4286f867cd7de676c9059695722186 MD5 · raw file

  1. /* -----------------------------------------------------------------------------
  2. * See the LICENSE file for information on copyright, usage and redistribution
  3. * of SWIG, and the README file for authors - http://www.swig.org/release.html.
  4. *
  5. * cpp.c
  6. *
  7. * An implementation of a C preprocessor plus some support for additional
  8. * SWIG directives.
  9. *
  10. * - SWIG directives such as %include, %extern, and %import are handled
  11. * - A new macro %define ... %enddef can be used for multiline macros
  12. * - No preprocessing is performed in %{ ... %} blocks
  13. * - Lines beginning with %# are stripped down to #... and passed through.
  14. * ----------------------------------------------------------------------------- */
  15. char cvsroot_cpp_c[] = "$Header$";
  16. #include "swig.h"
  17. #include "preprocessor.h"
  18. #include <ctype.h>
  19. static Hash *cpp = 0; /* C preprocessor data */
  20. static int include_all = 0; /* Follow all includes */
  21. static int ignore_missing = 0;
  22. static int import_all = 0; /* Follow all includes, but as %import statements */
  23. static int imported_depth = 0; /* Depth of %imported files */
  24. static int single_include = 1; /* Only include each file once */
  25. static Hash *included_files = 0;
  26. static List *dependencies = 0;
  27. static SwigScanner *id_scan = 0;
  28. static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */
  29. /* Test a character to see if it starts an identifier */
  30. #define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$'))
  31. /* Test a character to see if it valid in an identifier (after the first letter) */
  32. #define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$'))
  33. /* Skip whitespace */
  34. static void skip_whitespace(String *s, String *out) {
  35. int c;
  36. while ((c = StringGetc(s)) != EOF) {
  37. if (!isspace(c)) {
  38. StringUngetc(c, s);
  39. break;
  40. } else if (out)
  41. StringPutc(c, out);
  42. }
  43. }
  44. /* Skip to a specified character taking line breaks into account */
  45. static int skip_tochar(String *s, int ch, String *out) {
  46. int c;
  47. while ((c = StringGetc(s)) != EOF) {
  48. if (out)
  49. StringPutc(c, out);
  50. if (c == ch)
  51. break;
  52. if (c == '\\') {
  53. c = StringGetc(s);
  54. if ((c != EOF) && (out))
  55. StringPutc(c, out);
  56. }
  57. }
  58. if (c == EOF)
  59. return -1;
  60. return 0;
  61. }
  62. static void copy_location(const DOH *s1, DOH *s2) {
  63. Setfile(s2, Getfile((DOH *) s1));
  64. Setline(s2, Getline((DOH *) s1));
  65. }
  66. static String *cpp_include(String_or_char *fn, int sysfile) {
  67. String *s = sysfile ? Swig_include_sys(fn) : Swig_include(fn);
  68. if (s && single_include) {
  69. String *file = Getfile(s);
  70. if (Getattr(included_files, file)) {
  71. Delete(s);
  72. return 0;
  73. }
  74. Setattr(included_files, file, file);
  75. }
  76. if (!s) {
  77. Seek(fn, 0, SEEK_SET);
  78. if (ignore_missing) {
  79. Swig_warning(WARN_PP_MISSING_FILE, Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
  80. } else {
  81. Swig_error(Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
  82. }
  83. } else {
  84. String *lf;
  85. Seek(s, 0, SEEK_SET);
  86. if (!dependencies) {
  87. dependencies = NewList();
  88. }
  89. lf = Copy(Swig_last_file());
  90. Append(dependencies, lf);
  91. Delete(lf);
  92. }
  93. return s;
  94. }
  95. List *Preprocessor_depend(void) {
  96. return dependencies;
  97. }
  98. /* -----------------------------------------------------------------------------
  99. * void Preprocessor_cpp_init() - Initialize the preprocessor
  100. * ----------------------------------------------------------------------------- */
  101. static String *kpp_args = 0;
  102. static String *kpp_define = 0;
  103. static String *kpp_defined = 0;
  104. static String *kpp_elif = 0;
  105. static String *kpp_else = 0;
  106. static String *kpp_endif = 0;
  107. static String *kpp_expanded = 0;
  108. static String *kpp_if = 0;
  109. static String *kpp_ifdef = 0;
  110. static String *kpp_ifndef = 0;
  111. static String *kpp_name = 0;
  112. static String *kpp_swigmacro = 0;
  113. static String *kpp_symbols = 0;
  114. static String *kpp_undef = 0;
  115. static String *kpp_value = 0;
  116. static String *kpp_varargs = 0;
  117. static String *kpp_error = 0;
  118. static String *kpp_warning = 0;
  119. static String *kpp_line = 0;
  120. static String *kpp_include = 0;
  121. static String *kpp_pragma = 0;
  122. static String *kpp_level = 0;
  123. static String *kpp_dline = 0;
  124. static String *kpp_ddefine = 0;
  125. static String *kpp_dinclude = 0;
  126. static String *kpp_dimport = 0;
  127. static String *kpp_dextern = 0;
  128. static String *kpp_LINE = 0;
  129. static String *kpp_FILE = 0;
  130. void Preprocessor_init(void) {
  131. Hash *s;
  132. kpp_args = NewString("args");
  133. kpp_define = NewString("define");
  134. kpp_defined = NewString("defined");
  135. kpp_else = NewString("else");
  136. kpp_elif = NewString("elif");
  137. kpp_endif = NewString("endif");
  138. kpp_expanded = NewString("*expanded*");
  139. kpp_if = NewString("if");
  140. kpp_ifdef = NewString("ifdef");
  141. kpp_ifndef = NewString("ifndef");
  142. kpp_name = NewString("name");
  143. kpp_swigmacro = NewString("swigmacro");
  144. kpp_symbols = NewString("symbols");
  145. kpp_undef = NewString("undef");
  146. kpp_value = NewString("value");
  147. kpp_error = NewString("error");
  148. kpp_warning = NewString("warning");
  149. kpp_pragma = NewString("pragma");
  150. kpp_level = NewString("level");
  151. kpp_line = NewString("line");
  152. kpp_include = NewString("include");
  153. kpp_varargs = NewString("varargs");
  154. kpp_dinclude = NewString("%include");
  155. kpp_dimport = NewString("%import");
  156. kpp_dextern = NewString("%extern");
  157. kpp_ddefine = NewString("%define");
  158. kpp_dline = NewString("%line");
  159. kpp_LINE = NewString("__LINE__");
  160. kpp_FILE = NewString("__FILE__");
  161. cpp = NewHash();
  162. s = NewHash();
  163. Setattr(cpp, kpp_symbols, s);
  164. Delete(s);
  165. Preprocessor_expr_init(); /* Initialize the expression evaluator */
  166. included_files = NewHash();
  167. id_scan = NewSwigScanner();;
  168. }
  169. void Preprocessor_delete(void) {
  170. Delete(kpp_args);
  171. Delete(kpp_define);
  172. Delete(kpp_defined);
  173. Delete(kpp_else);
  174. Delete(kpp_elif);
  175. Delete(kpp_endif);
  176. Delete(kpp_expanded);
  177. Delete(kpp_if);
  178. Delete(kpp_ifdef);
  179. Delete(kpp_ifndef);
  180. Delete(kpp_name);
  181. Delete(kpp_swigmacro);
  182. Delete(kpp_symbols);
  183. Delete(kpp_undef);
  184. Delete(kpp_value);
  185. Delete(kpp_error);
  186. Delete(kpp_warning);
  187. Delete(kpp_pragma);
  188. Delete(kpp_level);
  189. Delete(kpp_line);
  190. Delete(kpp_include);
  191. Delete(kpp_varargs);
  192. Delete(kpp_dinclude);
  193. Delete(kpp_dimport);
  194. Delete(kpp_dextern);
  195. Delete(kpp_ddefine);
  196. Delete(kpp_dline);
  197. Delete(kpp_LINE);
  198. Delete(kpp_FILE);
  199. Delete(cpp);
  200. Delete(included_files);
  201. Preprocessor_expr_delete();
  202. DelSwigScanner(id_scan);
  203. Delete(dependencies);
  204. Delete(Swig_add_directory(0));
  205. }
  206. /* -----------------------------------------------------------------------------
  207. * void Preprocessor_include_all() - Instruct preprocessor to include all files
  208. * ----------------------------------------------------------------------------- */
  209. void Preprocessor_include_all(int a) {
  210. include_all = a;
  211. }
  212. void Preprocessor_import_all(int a) {
  213. import_all = a;
  214. }
  215. void Preprocessor_ignore_missing(int a) {
  216. ignore_missing = a;
  217. }
  218. void Preprocessor_error_as_warning(int a) {
  219. error_as_warning = a;
  220. }
  221. /* -----------------------------------------------------------------------------
  222. * Preprocessor_define()
  223. *
  224. * Defines a new C preprocessor symbol. swigmacro specifies whether or not the macro has
  225. * SWIG macro semantics.
  226. * ----------------------------------------------------------------------------- */
  227. String_or_char *Macro_vararg_name(String_or_char *str, String_or_char *line) {
  228. String_or_char *argname, *varargname;
  229. char *s, *dots;
  230. argname = Copy(str);
  231. s = Char(argname);
  232. dots = strchr(s, '.');
  233. if (!dots) {
  234. Delete(argname);
  235. return NULL;
  236. }
  237. if (strcmp(dots, "...") != 0) {
  238. Swig_error(Getfile(line), Getline(line), "Illegal macro argument name '%s'\n", str);
  239. Delete(argname);
  240. return NULL;
  241. }
  242. if (dots == s) {
  243. varargname = NewString("__VA_ARGS__");
  244. } else {
  245. *dots = '\0';
  246. varargname = NewString(s);
  247. }
  248. Delete(argname);
  249. return varargname;
  250. }
  251. Hash *Preprocessor_define(const String_or_char *_str, int swigmacro) {
  252. String *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0;
  253. Hash *macro = 0, *symbols = 0, *m1;
  254. List *arglist = 0;
  255. int c, line;
  256. int varargs = 0;
  257. String_or_char *str = (String_or_char *) _str;
  258. assert(cpp);
  259. assert(str);
  260. /* First make sure that string is actually a string */
  261. if (DohCheck(str)) {
  262. s = Copy(str);
  263. copy_location(str, s);
  264. str = s;
  265. } else {
  266. str = NewString((char *) str);
  267. }
  268. Seek(str, 0, SEEK_SET);
  269. line = Getline(str);
  270. file = Getfile(str);
  271. /* Skip over any leading whitespace */
  272. skip_whitespace(str, 0);
  273. /* Now look for a macro name */
  274. macroname = NewStringEmpty();
  275. while ((c = StringGetc(str)) != EOF) {
  276. if (c == '(') {
  277. argstr = NewStringEmpty();
  278. copy_location(str, argstr);
  279. /* It is a macro. Go extract its argument string */
  280. while ((c = StringGetc(str)) != EOF) {
  281. if (c == ')')
  282. break;
  283. else
  284. StringPutc(c, argstr);
  285. }
  286. if (c != ')') {
  287. Swig_error(Getfile(str), Getline(str), "Missing \')\' in macro parameters\n");
  288. goto macro_error;
  289. }
  290. break;
  291. } else if (isidchar(c) || (c == '%')) {
  292. StringPutc(c, macroname);
  293. } else if (isspace(c)) {
  294. break;
  295. } else if (c == '\\') {
  296. c = StringGetc(str);
  297. if (c != '\n') {
  298. StringUngetc(c, str);
  299. StringUngetc('\\', str);
  300. break;
  301. }
  302. } else {
  303. /*Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n");
  304. goto macro_error; */
  305. StringUngetc(c, str);
  306. break;
  307. }
  308. }
  309. if (!swigmacro)
  310. skip_whitespace(str, 0);
  311. macrovalue = NewStringEmpty();
  312. while ((c = StringGetc(str)) != EOF) {
  313. StringPutc(c, macrovalue);
  314. }
  315. /* If there are any macro arguments, convert into a list */
  316. if (argstr) {
  317. String *argname, *varargname;
  318. arglist = NewList();
  319. Seek(argstr, 0, SEEK_SET);
  320. argname = NewStringEmpty();
  321. while ((c = StringGetc(argstr)) != EOF) {
  322. if (c == ',') {
  323. varargname = Macro_vararg_name(argname, str);
  324. if (varargname) {
  325. Delete(varargname);
  326. Swig_error(Getfile(str), Getline(str), "Variable-length macro argument must be last parameter\n");
  327. } else {
  328. Append(arglist, argname);
  329. }
  330. Delete(argname);
  331. argname = NewStringEmpty();
  332. } else if (isidchar(c) || (c == '.')) {
  333. StringPutc(c, argname);
  334. } else if (!(isspace(c) || (c == '\\'))) {
  335. Delete(argname);
  336. Swig_error(Getfile(str), Getline(str), "Illegal character in macro argument name\n");
  337. goto macro_error;
  338. }
  339. }
  340. if (Len(argname)) {
  341. /* Check for varargs */
  342. varargname = Macro_vararg_name(argname, str);
  343. if (varargname) {
  344. Append(arglist, varargname);
  345. Delete(varargname);
  346. varargs = 1;
  347. } else {
  348. Append(arglist, argname);
  349. }
  350. }
  351. Delete(argname);
  352. }
  353. if (!swigmacro) {
  354. Replace(macrovalue, "\\\n", " ", DOH_REPLACE_NOQUOTE);
  355. }
  356. /* Look for special # substitutions. We only consider # that appears
  357. outside of quotes and comments */
  358. {
  359. int state = 0;
  360. char *cc = Char(macrovalue);
  361. while (*cc) {
  362. switch (state) {
  363. case 0:
  364. if (*cc == '#')
  365. *cc = '\001';
  366. else if (*cc == '/')
  367. state = 10;
  368. else if (*cc == '\'')
  369. state = 20;
  370. else if (*cc == '\"')
  371. state = 30;
  372. break;
  373. case 10:
  374. if (*cc == '*')
  375. state = 11;
  376. else if (*cc == '/')
  377. state = 15;
  378. else {
  379. state = 0;
  380. cc--;
  381. }
  382. break;
  383. case 11:
  384. if (*cc == '*')
  385. state = 12;
  386. break;
  387. case 12:
  388. if (*cc == '/')
  389. state = 0;
  390. else if (*cc != '*')
  391. state = 11;
  392. break;
  393. case 15:
  394. if (*cc == '\n')
  395. state = 0;
  396. break;
  397. case 20:
  398. if (*cc == '\'')
  399. state = 0;
  400. if (*cc == '\\')
  401. state = 21;
  402. break;
  403. case 21:
  404. state = 20;
  405. break;
  406. case 30:
  407. if (*cc == '\"')
  408. state = 0;
  409. if (*cc == '\\')
  410. state = 31;
  411. break;
  412. case 31:
  413. state = 30;
  414. break;
  415. default:
  416. break;
  417. }
  418. cc++;
  419. }
  420. }
  421. /* Get rid of whitespace surrounding # */
  422. /* Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); */
  423. while (strstr(Char(macrovalue), "\001 ")) {
  424. Replace(macrovalue, "\001 ", "\001", DOH_REPLACE_ANY);
  425. }
  426. while (strstr(Char(macrovalue), " \001")) {
  427. Replace(macrovalue, " \001", "\001", DOH_REPLACE_ANY);
  428. }
  429. /* Replace '##' with a special token */
  430. Replace(macrovalue, "\001\001", "\002", DOH_REPLACE_ANY);
  431. /* Replace '#@' with a special token */
  432. Replace(macrovalue, "\001@", "\004", DOH_REPLACE_ANY);
  433. /* Replace '##@' with a special token */
  434. Replace(macrovalue, "\002@", "\005", DOH_REPLACE_ANY);
  435. /* Go create the macro */
  436. macro = NewHash();
  437. Setattr(macro, kpp_name, macroname);
  438. if (arglist) {
  439. Setattr(macro, kpp_args, arglist);
  440. Delete(arglist);
  441. if (varargs) {
  442. Setattr(macro, kpp_varargs, "1");
  443. }
  444. }
  445. Setattr(macro, kpp_value, macrovalue);
  446. Setline(macro, line);
  447. Setfile(macro, file);
  448. if (swigmacro) {
  449. Setattr(macro, kpp_swigmacro, "1");
  450. }
  451. symbols = HashGetAttr(cpp, kpp_symbols);
  452. if ((m1 = HashGetAttr(symbols, macroname))) {
  453. if (!HashCheckAttr(m1, kpp_value, macrovalue)) {
  454. Swig_error(Getfile(str), Getline(str), "Macro '%s' redefined,\n", macroname);
  455. Swig_error(Getfile(m1), Getline(m1), "previous definition of '%s'.\n", macroname);
  456. goto macro_error;
  457. }
  458. } else {
  459. Setattr(symbols, macroname, macro);
  460. Delete(macro);
  461. }
  462. Delete(macroname);
  463. Delete(macrovalue);
  464. Delete(str);
  465. Delete(argstr);
  466. return macro;
  467. macro_error:
  468. Delete(str);
  469. Delete(argstr);
  470. Delete(arglist);
  471. Delete(macroname);
  472. Delete(macrovalue);
  473. return 0;
  474. }
  475. /* -----------------------------------------------------------------------------
  476. * Preprocessor_undef()
  477. *
  478. * Undefines a macro.
  479. * ----------------------------------------------------------------------------- */
  480. void Preprocessor_undef(const String_or_char *str) {
  481. Hash *symbols;
  482. assert(cpp);
  483. symbols = HashGetAttr(cpp, kpp_symbols);
  484. Delattr(symbols, str);
  485. }
  486. /* -----------------------------------------------------------------------------
  487. * find_args()
  488. *
  489. * Isolates macro arguments and returns them in a list. For each argument,
  490. * leading and trailing whitespace is stripped (ala K&R, pg. 230).
  491. * ----------------------------------------------------------------------------- */
  492. static List *find_args(String *s) {
  493. List *args;
  494. String *str;
  495. int c, level;
  496. long pos;
  497. /* Create a new list */
  498. args = NewList();
  499. copy_location(s, args);
  500. /* First look for a '(' */
  501. pos = Tell(s);
  502. skip_whitespace(s, 0);
  503. /* Now see if the next character is a '(' */
  504. c = StringGetc(s);
  505. if (c != '(') {
  506. /* Not a macro, bail out now! */
  507. Seek(s, pos, SEEK_SET);
  508. Delete(args);
  509. return 0;
  510. }
  511. c = StringGetc(s);
  512. /* Okay. This appears to be a macro so we will start isolating arguments */
  513. while (c != EOF) {
  514. if (isspace(c)) {
  515. skip_whitespace(s, 0); /* Skip leading whitespace */
  516. c = StringGetc(s);
  517. }
  518. str = NewStringEmpty();
  519. copy_location(s, str);
  520. level = 0;
  521. while (c != EOF) {
  522. if (c == '\"') {
  523. StringPutc(c, str);
  524. skip_tochar(s, '\"', str);
  525. c = StringGetc(s);
  526. continue;
  527. } else if (c == '\'') {
  528. StringPutc(c, str);
  529. skip_tochar(s, '\'', str);
  530. c = StringGetc(s);
  531. continue;
  532. }
  533. if ((c == ',') && (level == 0))
  534. break;
  535. if ((c == ')') && (level == 0))
  536. break;
  537. StringPutc(c, str);
  538. if (c == '(')
  539. level++;
  540. if (c == ')')
  541. level--;
  542. c = StringGetc(s);
  543. }
  544. if (level > 0) {
  545. goto unterm;
  546. }
  547. Chop(str);
  548. if (Len(args) || Len(str))
  549. Append(args, str);
  550. Delete(str);
  551. /* if (Len(str) && (c != ')'))
  552. Append(args,str); */
  553. if (c == ')')
  554. return args;
  555. c = StringGetc(s);
  556. }
  557. unterm:
  558. Swig_error(Getfile(args), Getline(args), "Unterminated macro call.\n");
  559. return args;
  560. }
  561. /* -----------------------------------------------------------------------------
  562. * DOH *get_filename(DOH *str)
  563. *
  564. * Read a filename from str. A filename can be enclose in quotes, angle brackets,
  565. * or bare.
  566. * ----------------------------------------------------------------------------- */
  567. static String *get_filename(String *str, int *sysfile) {
  568. String *fn;
  569. int c;
  570. skip_whitespace(str, 0);
  571. fn = NewStringEmpty();
  572. copy_location(str, fn);
  573. c = StringGetc(str);
  574. *sysfile = 0;
  575. if (c == '\"') {
  576. while (((c = StringGetc(str)) != EOF) && (c != '\"'))
  577. StringPutc(c, fn);
  578. } else if (c == '<') {
  579. *sysfile = 1;
  580. while (((c = StringGetc(str)) != EOF) && (c != '>'))
  581. StringPutc(c, fn);
  582. } else {
  583. StringPutc(c, fn);
  584. while (((c = StringGetc(str)) != EOF) && (!isspace(c)))
  585. StringPutc(c, fn);
  586. if (isspace(c))
  587. StringUngetc(c, str);
  588. }
  589. #if defined(_WIN32) || defined(MACSWIG)
  590. /* accept Unix path separator on non-Unix systems */
  591. Replaceall(fn, "/", SWIG_FILE_DELIMETER);
  592. #endif
  593. #if defined(__CYGWIN__)
  594. /* accept Windows path separator in addition to Unix path separator */
  595. Replaceall(fn, "\\", SWIG_FILE_DELIMETER);
  596. #endif
  597. Seek(fn, 0, SEEK_SET);
  598. return fn;
  599. }
  600. static String *get_options(String *str) {
  601. int c;
  602. skip_whitespace(str, 0);
  603. c = StringGetc(str);
  604. if (c == '(') {
  605. String *opt;
  606. int level = 1;
  607. opt = NewString("(");
  608. while (((c = StringGetc(str)) != EOF)) {
  609. StringPutc(c, opt);
  610. if (c == ')') {
  611. level--;
  612. if (!level)
  613. return opt;
  614. }
  615. if (c == '(')
  616. level++;
  617. }
  618. Delete(opt);
  619. return 0;
  620. } else {
  621. StringUngetc(c, str);
  622. return 0;
  623. }
  624. }
  625. /* -----------------------------------------------------------------------------
  626. * expand_macro()
  627. *
  628. * Perform macro expansion and return a new string. Returns NULL if some sort
  629. * of error occurred.
  630. * ----------------------------------------------------------------------------- */
  631. static String *expand_macro(String *name, List *args) {
  632. String *ns;
  633. DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e;
  634. DOH *Preprocessor_replace(DOH *);
  635. int i, l;
  636. int isvarargs = 0;
  637. symbols = HashGetAttr(cpp, kpp_symbols);
  638. if (!symbols)
  639. return 0;
  640. /* See if the name is actually defined */
  641. macro = HashGetAttr(symbols, name);
  642. if (!macro)
  643. return 0;
  644. if (HashGetAttr(macro, kpp_expanded)) {
  645. ns = NewStringEmpty();
  646. StringAppend(ns, name);
  647. if (args) {
  648. int lenargs = Len(args);
  649. if (lenargs)
  650. StringPutc('(', ns);
  651. for (i = 0; i < lenargs; i++) {
  652. StringAppend(ns, Getitem(args, i));
  653. if (i < (lenargs - 1))
  654. StringPutc(',', ns);
  655. }
  656. if (i)
  657. StringPutc(')', ns);
  658. }
  659. return ns;
  660. }
  661. /* Get macro arguments and value */
  662. mvalue = HashGetAttr(macro, kpp_value);
  663. assert(mvalue);
  664. margs = HashGetAttr(macro, kpp_args);
  665. if (args && HashGetAttr(macro, kpp_varargs)) {
  666. isvarargs = 1;
  667. /* Variable length argument macro. We need to collect all of the extra arguments into a single argument */
  668. if (Len(args) >= (Len(margs) - 1)) {
  669. int i;
  670. int vi, na;
  671. String *vararg = NewStringEmpty();
  672. vi = Len(margs) - 1;
  673. na = Len(args);
  674. for (i = vi; i < na; i++) {
  675. StringAppend(vararg, Getitem(args, i));
  676. if ((i + 1) < na) {
  677. StringAppend(vararg, ",");
  678. }
  679. }
  680. /* Remove arguments */
  681. for (i = vi; i < na; i++) {
  682. Delitem(args, vi);
  683. }
  684. Append(args, vararg);
  685. Delete(vararg);
  686. }
  687. }
  688. /* If there are arguments, see if they match what we were given */
  689. if (args && (margs) && (Len(margs) != Len(args))) {
  690. if (Len(margs) > (1 + isvarargs))
  691. Swig_error(Getfile(args), Getline(args), "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
  692. else if (Len(margs) == (1 + isvarargs))
  693. Swig_error(Getfile(args), Getline(args), "Macro '%s' expects 1 argument\n", name);
  694. else
  695. Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name);
  696. return 0;
  697. }
  698. /* If the macro expects arguments, but none were supplied, we leave it in place */
  699. if (!args && (margs) && Len(margs) > 0) {
  700. return NewString(name);
  701. }
  702. /* Copy the macro value */
  703. ns = Copy(mvalue);
  704. copy_location(mvalue, ns);
  705. /* Tag the macro as being expanded. This is to avoid recursion in
  706. macro expansion */
  707. temp = NewStringEmpty();
  708. tempa = NewStringEmpty();
  709. if (args && margs) {
  710. l = Len(margs);
  711. for (i = 0; i < l; i++) {
  712. DOH *arg, *aname;
  713. String *reparg;
  714. arg = Getitem(args, i); /* Get an argument value */
  715. reparg = Preprocessor_replace(arg);
  716. aname = Getitem(margs, i); /* Get macro argument name */
  717. if (strstr(StringChar(ns), "\001")) {
  718. /* Try to replace a quoted version of the argument */
  719. Clear(temp);
  720. Clear(tempa);
  721. Printf(temp, "\001%s", aname);
  722. Printf(tempa, "\"%s\"", arg);
  723. Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
  724. }
  725. if (strstr(StringChar(ns), "\002")) {
  726. /* Look for concatenation tokens */
  727. Clear(temp);
  728. Clear(tempa);
  729. Printf(temp, "\002%s", aname);
  730. StringAppend(tempa, "\002\003");
  731. Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
  732. Clear(temp);
  733. Clear(tempa);
  734. Printf(temp, "%s\002", aname);
  735. StringAppend(tempa, "\003\002");
  736. Replace(ns, temp, tempa, DOH_REPLACE_ID_BEGIN);
  737. }
  738. /* Non-standard macro expansion. The value `x` is replaced by a quoted
  739. version of the argument except that if the argument is already quoted
  740. nothing happens */
  741. if (strchr(StringChar(ns), '`')) {
  742. String *rep;
  743. char *c;
  744. Clear(temp);
  745. Printf(temp, "`%s`", aname);
  746. c = Char(arg);
  747. if (*c == '\"') {
  748. rep = arg;
  749. } else {
  750. Clear(tempa);
  751. Printf(tempa, "\"%s\"", arg);
  752. rep = tempa;
  753. }
  754. Replace(ns, temp, rep, DOH_REPLACE_ANY);
  755. }
  756. /* Non-standard mangle expansions.
  757. The #@Name is replaced by mangle_arg(Name). */
  758. if (strstr(StringChar(ns), "\004")) {
  759. String *marg = Swig_string_mangle(arg);
  760. Clear(temp);
  761. Printf(temp, "\004%s", aname);
  762. Replace(ns, temp, marg, DOH_REPLACE_ID_END);
  763. Delete(marg);
  764. }
  765. if (strstr(StringChar(ns), "\005")) {
  766. String *marg = Swig_string_mangle(arg);
  767. Clear(temp);
  768. Clear(tempa);
  769. Printf(temp, "\005%s", aname);
  770. Printf(tempa, "\"%s\"", marg);
  771. Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
  772. Delete(marg);
  773. }
  774. if (isvarargs && i == l - 1 && Len(arg) == 0) {
  775. /* Zero length varargs macro argument. We search for commas that might appear before and nuke them */
  776. char *a, *s, *t, *name;
  777. int namelen;
  778. s = StringChar(ns);
  779. name = Char(aname);
  780. namelen = Len(aname);
  781. a = strstr(s, name);
  782. while (a) {
  783. char ca = a[namelen + 1];
  784. if (!isidchar((int) ca)) {
  785. /* Matched the entire vararg name, not just a prefix */
  786. t = a - 1;
  787. if (*t == '\002') {
  788. t--;
  789. while (t >= s) {
  790. if (isspace((int) *t))
  791. t--;
  792. else if (*t == ',') {
  793. *t = ' ';
  794. } else
  795. break;
  796. }
  797. }
  798. }
  799. a = strstr(a + namelen, name);
  800. }
  801. }
  802. /* Replace(ns, aname, arg, DOH_REPLACE_ID); */
  803. Replace(ns, aname, reparg, DOH_REPLACE_ID); /* Replace expanded args */
  804. Replace(ns, "\003", arg, DOH_REPLACE_ANY); /* Replace unexpanded arg */
  805. Delete(reparg);
  806. }
  807. }
  808. Replace(ns, "\002", "", DOH_REPLACE_ANY); /* Get rid of concatenation tokens */
  809. Replace(ns, "\001", "#", DOH_REPLACE_ANY); /* Put # back (non-standard C) */
  810. Replace(ns, "\004", "#@", DOH_REPLACE_ANY); /* Put # back (non-standard C) */
  811. /* Expand this macro even further */
  812. Setattr(macro, kpp_expanded, "1");
  813. e = Preprocessor_replace(ns);
  814. Delattr(macro, kpp_expanded);
  815. Delete(ns);
  816. if (HashGetAttr(macro, kpp_swigmacro)) {
  817. String *g;
  818. String *f = NewStringEmpty();
  819. Seek(e, 0, SEEK_SET);
  820. copy_location(macro, e);
  821. g = Preprocessor_parse(e);
  822. #if 0
  823. /* Drop the macro in place, but with a marker around it */
  824. Printf(f, "/*@%s,%d,%s@*/%s/*@@*/", Getfile(macro), Getline(macro), name, g);
  825. #else
  826. /* Use simplified around markers to properly count lines in cscanner.c */
  827. if (strchr(Char(g), '\n')) {
  828. Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g);
  829. } else {
  830. StringAppend(f, g);
  831. }
  832. #endif
  833. Delete(g);
  834. Delete(e);
  835. e = f;
  836. }
  837. Delete(temp);
  838. Delete(tempa);
  839. return e;
  840. }
  841. /* -----------------------------------------------------------------------------
  842. * evaluate_args()
  843. *
  844. * Evaluate the arguments of a macro
  845. * ----------------------------------------------------------------------------- */
  846. List *evaluate_args(List *x) {
  847. Iterator i;
  848. String *Preprocessor_replace(String *);
  849. List *nl = NewList();
  850. for (i = First(x); i.item; i = Next(i)) {
  851. Append(nl, Preprocessor_replace(i.item));
  852. }
  853. return nl;
  854. }
  855. /* -----------------------------------------------------------------------------
  856. * DOH *Preprocessor_replace(DOH *s)
  857. *
  858. * Performs a macro substitution on a string s. Returns a new string with
  859. * substitutions applied. This function works by walking down s and looking
  860. * for identifiers. When found, a check is made to see if they are macros
  861. * which are then expanded.
  862. * ----------------------------------------------------------------------------- */
  863. /* #define SWIG_PUT_BUFF */
  864. DOH *Preprocessor_replace(DOH *s) {
  865. DOH *ns, *symbols, *m;
  866. int c, i, state = 0;
  867. String *id = NewStringEmpty();
  868. assert(cpp);
  869. symbols = HashGetAttr(cpp, kpp_symbols);
  870. ns = NewStringEmpty();
  871. copy_location(s, ns);
  872. Seek(s, 0, SEEK_SET);
  873. /* Try to locate identifiers in s and replace them with macro replacements */
  874. while ((c = StringGetc(s)) != EOF) {
  875. switch (state) {
  876. case 0:
  877. if (isidentifier(c) || (c == '%')) {
  878. Clear(id);
  879. StringPutc(c, id);
  880. state = 1;
  881. } else if (c == '\"') {
  882. StringPutc(c, ns);
  883. skip_tochar(s, '\"', ns);
  884. } else if (c == '\'') {
  885. StringPutc(c, ns);
  886. skip_tochar(s, '\'', ns);
  887. } else if (c == '/') {
  888. StringPutc(c, ns);
  889. state = 10;
  890. } else {
  891. StringPutc(c, ns);
  892. }
  893. break;
  894. case 1: /* An identifier */
  895. if (isidchar(c)) {
  896. StringPutc(c, id);
  897. state = 1;
  898. } else {
  899. /* We found the end of a valid identifier */
  900. StringUngetc(c, s);
  901. /* See if this is the special "defined" macro */
  902. if (StringEqual(kpp_defined, id)) {
  903. int lenargs = 0;
  904. DOH *args = 0;
  905. /* See whether or not a paranthesis has been used */
  906. skip_whitespace(s, 0);
  907. c = StringGetc(s);
  908. if (c == '(') {
  909. StringUngetc(c, s);
  910. args = find_args(s);
  911. } else if (isidchar(c)) {
  912. DOH *arg = NewStringEmpty();
  913. args = NewList();
  914. StringPutc(c, arg);
  915. while (((c = StringGetc(s)) != EOF)) {
  916. if (!isidchar(c)) {
  917. StringUngetc(c, s);
  918. break;
  919. }
  920. StringPutc(c, arg);
  921. }
  922. if (Len(arg))
  923. Append(args, arg);
  924. Delete(arg);
  925. } else {
  926. Seek(s, -1, SEEK_CUR);
  927. }
  928. lenargs = Len(args);
  929. if ((!args) || (!lenargs)) {
  930. /* This is not a defined() macro. */
  931. StringAppend(ns, id);
  932. state = 0;
  933. break;
  934. }
  935. for (i = 0; i < lenargs; i++) {
  936. DOH *o = Getitem(args, i);
  937. if (!HashGetAttr(symbols, o)) {
  938. break;
  939. }
  940. }
  941. if (i < lenargs)
  942. StringPutc('0', ns);
  943. else
  944. StringPutc('1', ns);
  945. Delete(args);
  946. state = 0;
  947. break;
  948. }
  949. if (StringEqual(kpp_LINE, id)) {
  950. Printf(ns, "%d", Getline(s));
  951. state = 0;
  952. break;
  953. }
  954. if (StringEqual(kpp_FILE, id)) {
  955. String *fn = Copy(Getfile(s));
  956. Replaceall(fn, "\\", "\\\\");
  957. Printf(ns, "\"%s\"", fn);
  958. Delete(fn);
  959. state = 0;
  960. break;
  961. }
  962. /* See if the macro is defined in the preprocessor symbol table */
  963. if ((m = HashGetAttr(symbols, id))) {
  964. DOH *args = 0;
  965. DOH *e;
  966. /* See if the macro expects arguments */
  967. if (HashGetAttr(m, kpp_args)) {
  968. /* Yep. We need to go find the arguments and do a substitution */
  969. args = find_args(s);
  970. if (!Len(args)) {
  971. Delete(args);
  972. args = 0;
  973. }
  974. } else {
  975. args = 0;
  976. }
  977. e = expand_macro(id, args);
  978. if (e) {
  979. StringAppend(ns, e);
  980. }
  981. Delete(e);
  982. Delete(args);
  983. } else {
  984. StringAppend(ns, id);
  985. }
  986. state = 0;
  987. }
  988. break;
  989. case 10:
  990. if (c == '/')
  991. state = 11;
  992. else if (c == '*')
  993. state = 12;
  994. else {
  995. StringUngetc(c, s);
  996. state = 0;
  997. break;
  998. }
  999. StringPutc(c, ns);
  1000. break;
  1001. case 11:
  1002. StringPutc(c, ns);
  1003. if (c == '\n')
  1004. state = 0;
  1005. break;
  1006. case 12:
  1007. StringPutc(c, ns);
  1008. if (c == '*')
  1009. state = 13;
  1010. break;
  1011. case 13:
  1012. StringPutc(c, ns);
  1013. if (c == '/')
  1014. state = 0;
  1015. else if (c != '*')
  1016. state = 12;
  1017. break;
  1018. default:
  1019. state = 0;
  1020. break;
  1021. }
  1022. }
  1023. /* Identifier at the end */
  1024. if (state == 1) {
  1025. /* See if this is the special "defined" macro */
  1026. if (StringEqual(kpp_defined, id)) {
  1027. Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
  1028. } else if ((m = HashGetAttr(symbols, id))) {
  1029. DOH *e;
  1030. /* Yes. There is a macro here */
  1031. /* See if the macro expects arguments */
  1032. /* if (Getattr(m,"args")) {
  1033. Swig_error(Getfile(id),Getline(id),"Macro arguments expected.\n");
  1034. } */
  1035. e = expand_macro(id, 0);
  1036. StringAppend(ns, e);
  1037. Delete(e);
  1038. } else {
  1039. StringAppend(ns, id);
  1040. }
  1041. }
  1042. Delete(id);
  1043. return ns;
  1044. }
  1045. /* -----------------------------------------------------------------------------
  1046. * int checkpp_id(DOH *s)
  1047. *
  1048. * Checks the string s to see if it contains any unresolved identifiers. This
  1049. * function contains the heuristic that determines whether or not a macro
  1050. * definition passes through the preprocessor as a constant declaration.
  1051. * ----------------------------------------------------------------------------- */
  1052. static int checkpp_id(DOH *s) {
  1053. int c;
  1054. int hastok = 0;
  1055. SwigScanner *scan = id_scan;
  1056. Seek(s, 0, SEEK_SET);
  1057. SwigScanner_clear(scan);
  1058. s = Copy(s);
  1059. Seek(s, SEEK_SET, 0);
  1060. SwigScanner_push(scan, s);
  1061. while ((c = SwigScanner_token(scan))) {
  1062. hastok = 1;
  1063. if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE))
  1064. return 1;
  1065. }
  1066. if (!hastok)
  1067. return 1;
  1068. return 0;
  1069. }
  1070. /* addline(). Utility function for adding lines to a chunk */
  1071. static void addline(DOH *s1, DOH *s2, int allow) {
  1072. if (allow) {
  1073. StringAppend(s1, s2);
  1074. } else {
  1075. char *c = Char(s2);
  1076. while (*c) {
  1077. if (*c == '\n')
  1078. StringPutc('\n', s1);
  1079. c++;
  1080. }
  1081. }
  1082. }
  1083. static void add_chunk(DOH *ns, DOH *chunk, int allow) {
  1084. DOH *echunk;
  1085. Seek(chunk, 0, SEEK_SET);
  1086. if (allow) {
  1087. echunk = Preprocessor_replace(chunk);
  1088. addline(ns, echunk, allow);
  1089. Delete(echunk);
  1090. } else {
  1091. addline(ns, chunk, 0);
  1092. }
  1093. Clear(chunk);
  1094. }
  1095. /*
  1096. push/pop_imported(): helper functions for defining and undefining
  1097. SWIGIMPORTED (when %importing a file).
  1098. */
  1099. static void push_imported() {
  1100. if (imported_depth == 0) {
  1101. Preprocessor_define("SWIGIMPORTED 1", 0);
  1102. }
  1103. ++imported_depth;
  1104. }
  1105. static void pop_imported() {
  1106. --imported_depth;
  1107. if (imported_depth == 0) {
  1108. Preprocessor_undef("SWIGIMPORTED");
  1109. }
  1110. }
  1111. /* -----------------------------------------------------------------------------
  1112. * Preprocessor_parse()
  1113. *
  1114. * Parses the string s. Returns a new string containing the preprocessed version.
  1115. *
  1116. * Parsing rules :
  1117. * 1. Lines starting with # are C preprocessor directives
  1118. * 2. Macro expansion inside strings is not allowed
  1119. * 3. All code inside false conditionals is changed to blank lines
  1120. * 4. Code in %{, %} is not parsed because it may need to be
  1121. * included inline (with all preprocessor directives included).
  1122. * ----------------------------------------------------------------------------- */
  1123. String *Preprocessor_parse(String *s) {
  1124. String *ns; /* New string containing the preprocessed text */
  1125. String *chunk, *decl;
  1126. Hash *symbols;
  1127. String *id = 0, *value = 0, *comment = 0;
  1128. int i, state, e, c;
  1129. int start_line = 0;
  1130. int allow = 1;
  1131. int level = 0;
  1132. int dlevel = 0;
  1133. int mask = 0;
  1134. int start_level = 0;
  1135. int cpp_lines = 0;
  1136. int cond_lines[256];
  1137. /* Blow away all carriage returns */
  1138. Replace(s, "\015", "", DOH_REPLACE_ANY);
  1139. ns = NewStringEmpty(); /* Return result */
  1140. decl = NewStringEmpty();
  1141. id = NewStringEmpty();
  1142. value = NewStringEmpty();
  1143. comment = NewStringEmpty();
  1144. chunk = NewStringEmpty();
  1145. copy_location(s, chunk);
  1146. copy_location(s, ns);
  1147. symbols = HashGetAttr(cpp, kpp_symbols);
  1148. state = 0;
  1149. while ((c = StringGetc(s)) != EOF) {
  1150. switch (state) {
  1151. case 0: /* Initial state - in first column */
  1152. /* Look for C preprocessor directives. Otherwise, go directly to state 1 */
  1153. if (c == '#') {
  1154. add_chunk(ns, chunk, allow);
  1155. copy_location(s, chunk);
  1156. cpp_lines = 1;
  1157. state = 40;
  1158. } else if (isspace(c)) {
  1159. StringPutc(c, chunk);
  1160. skip_whitespace(s, chunk);
  1161. } else {
  1162. state = 1;
  1163. StringUngetc(c, s);
  1164. }
  1165. break;
  1166. case 1: /* Non-preprocessor directive */
  1167. /* Look for SWIG directives */
  1168. if (c == '%') {
  1169. state = 100;
  1170. break;
  1171. }
  1172. StringPutc(c, chunk);
  1173. if (c == '\n')
  1174. state = 0;
  1175. else if (c == '\"') {
  1176. start_line = Getline(s);
  1177. if (skip_tochar(s, '\"', chunk) < 0) {
  1178. Swig_error(Getfile(s), -1, "Unterminated string constant starting at line %d\n", start_line);
  1179. }
  1180. } else if (c == '\'') {
  1181. start_line = Getline(s);
  1182. if (skip_tochar(s, '\'', chunk) < 0) {
  1183. Swig_error(Getfile(s), -1, "Unterminated character constant starting at line %d\n", start_line);
  1184. }
  1185. } else if (c == '/')
  1186. state = 30; /* Comment */
  1187. break;
  1188. case 30: /* Possibly a comment string of some sort */
  1189. start_line = Getline(s);
  1190. StringPutc(c, chunk);
  1191. if (c == '/')
  1192. state = 31;
  1193. else if (c == '*')
  1194. state = 32;
  1195. else
  1196. state = 1;
  1197. break;
  1198. case 31:
  1199. StringPutc(c, chunk);
  1200. if (c == '\n')
  1201. state = 0;
  1202. break;
  1203. case 32:
  1204. StringPutc(c, chunk);
  1205. if (c == '*')
  1206. state = 33;
  1207. break;
  1208. case 33:
  1209. StringPutc(c, chunk);
  1210. if (c == '/')
  1211. state = 1;
  1212. else if (c != '*')
  1213. state = 32;
  1214. break;
  1215. case 40: /* Start of a C preprocessor directive */
  1216. if (c == '\n') {
  1217. StringPutc('\n', chunk);
  1218. state = 0;
  1219. } else if (isspace(c)) {
  1220. state = 40;
  1221. } else {
  1222. /* Got the start of a preprocessor directive */
  1223. StringUngetc(c, s);
  1224. Clear(id);
  1225. copy_location(s, id);
  1226. state = 41;
  1227. }
  1228. break;
  1229. case 41: /* Build up the name of the preprocessor directive */
  1230. if ((isspace(c) || (!isalpha(c)))) {
  1231. Clear(value);
  1232. Clear(comment);
  1233. if (c == '\n') {
  1234. StringUngetc(c, s);
  1235. state = 50;
  1236. } else {
  1237. state = 42;
  1238. if (!isspace(c)) {
  1239. StringUngetc(c, s);
  1240. }
  1241. }
  1242. copy_location(s, value);
  1243. break;
  1244. }
  1245. StringPutc(c, id);
  1246. break;
  1247. case 42: /* Strip any leading space before preprocessor value */
  1248. if (isspace(c)) {
  1249. if (c == '\n') {
  1250. StringUngetc(c, s);
  1251. state = 50;
  1252. }
  1253. break;
  1254. }
  1255. state = 43;
  1256. /* no break intended here */
  1257. case 43:
  1258. /* Get preprocessor value */
  1259. if (c == '\n') {
  1260. StringUngetc(c, s);
  1261. state = 50;
  1262. } else if (c == '/') {
  1263. state = 45;
  1264. } else if (c == '\"') {
  1265. StringPutc(c, value);
  1266. skip_tochar(s, '\"', value);
  1267. } else if (c == '\'') {
  1268. StringPutc(c, value);
  1269. skip_tochar(s, '\'', value);
  1270. } else {
  1271. StringPutc(c, value);
  1272. if (c == '\\')
  1273. state = 44;
  1274. }
  1275. break;
  1276. case 44:
  1277. if (c == '\n') {
  1278. StringPutc(c, value);
  1279. cpp_lines++;
  1280. } else {
  1281. StringUngetc(c, s);
  1282. }
  1283. state = 43;
  1284. break;
  1285. /* States 45-48 are used to remove, but retain comments from macro values. The comments
  1286. will be placed in the output in an alternative form */
  1287. case 45:
  1288. if (c == '/')
  1289. state = 46;
  1290. else if (c == '*')
  1291. state = 47;
  1292. else if (c == '\n') {
  1293. StringPutc('/', value);
  1294. StringUngetc(c, s);
  1295. cpp_lines++;
  1296. state = 50;
  1297. } else {
  1298. StringPutc('/', value);
  1299. StringPutc(c, value);
  1300. state = 43;
  1301. }
  1302. break;
  1303. case 46:
  1304. if (c == '\n') {
  1305. StringUngetc(c, s);
  1306. cpp_lines++;
  1307. state = 50;
  1308. } else
  1309. StringPutc(c, comment);
  1310. break;
  1311. case 47:
  1312. if (c == '*')
  1313. state = 48;
  1314. else
  1315. StringPutc(c, comment);
  1316. break;
  1317. case 48:
  1318. if (c == '/')
  1319. state = 43;
  1320. else if (c == '*')
  1321. StringPutc(c, comment);
  1322. else {
  1323. StringPutc('*', comment);
  1324. StringPutc(c, comment);
  1325. state = 47;
  1326. }
  1327. break;
  1328. case 50:
  1329. /* Check for various preprocessor directives */
  1330. Chop(value);
  1331. if (StringEqual(id, kpp_define)) {
  1332. if (allow) {
  1333. DOH *m, *v, *v1;
  1334. Seek(value, 0, SEEK_SET);
  1335. m = Preprocessor_define(value, 0);
  1336. if ((m) && !(HashGetAttr(m, kpp_args))) {
  1337. v = Copy(HashGetAttr(m, kpp_value));
  1338. if (Len(v)) {
  1339. Swig_error_silent(1);
  1340. v1 = Preprocessor_replace(v);
  1341. Swig_error_silent(0);
  1342. /* Printf(stdout,"checking '%s'\n", v1); */
  1343. if (!checkpp_id(v1)) {
  1344. if (Len(comment) == 0)
  1345. Printf(ns, "%%constant %s = %s;\n", HashGetAttr(m, kpp_name), v1);
  1346. else
  1347. Printf(ns, "%%constant %s = %s; /*%s*/\n", HashGetAttr(m, kpp_name), v1, comment);
  1348. cpp_lines--;
  1349. }
  1350. Delete(v1);
  1351. }
  1352. Delete(v);
  1353. }
  1354. }
  1355. } else if (StringEqual(id, kpp_undef)) {
  1356. if (allow)
  1357. Preprocessor_undef(value);
  1358. } else if (StringEqual(id, kpp_ifdef)) {
  1359. cond_lines[level] = Getline(id);
  1360. level++;
  1361. if (allow) {
  1362. start_level = level;
  1363. /* See if the identifier is in the hash table */
  1364. if (!HashGetAttr(symbols, value))
  1365. allow = 0;
  1366. mask = 1;
  1367. }
  1368. } else if (StringEqual(id, kpp_ifndef)) {
  1369. cond_lines[level] = Getline(id);
  1370. level++;
  1371. if (allow) {
  1372. start_level = level;
  1373. /* See if the identifier is in the hash table */
  1374. if (HashGetAttr(symbols, value))
  1375. allow = 0;
  1376. mask = 1;
  1377. }
  1378. } else if (StringEqual(id, kpp_else)) {
  1379. if (level <= 0) {
  1380. Swig_error(Getfile(s), Getline(id), "Misplaced #else.\n");
  1381. } else {
  1382. cond_lines[level - 1] = Getline(id);
  1383. if (allow) {
  1384. allow = 0;
  1385. mask = 0;
  1386. } else if (level == start_level) {
  1387. allow = 1 * mask;
  1388. }
  1389. }
  1390. } else if (StringEqual(id, kpp_endif)) {
  1391. level--;
  1392. if (level < 0) {
  1393. Swig_error(Getfile(id), Getline(id), "Extraneous #endif.\n");
  1394. level = 0;
  1395. } else {
  1396. if (level < start_level) {
  1397. allow = 1;
  1398. start_level--;
  1399. }
  1400. }
  1401. } else if (StringEqual(id, kpp_if)) {
  1402. cond_lines[level] = Getline(id);
  1403. level++;
  1404. if (allow) {
  1405. int val;
  1406. String *sval = Preprocessor_replace(value);
  1407. start_level = level;
  1408. Seek(sval, 0, SEEK_SET);
  1409. /* Printf(stdout,"Evaluating '%s'\n", sval); */
  1410. val = Preprocessor_expr(sval, &e);
  1411. if (e) {
  1412. char *msg = Preprocessor_expr_error();
  1413. Seek(value, 0, SEEK_SET);
  1414. Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value);
  1415. if (msg)
  1416. Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
  1417. allow = 0;
  1418. } else {
  1419. if (val == 0)
  1420. allow = 0;
  1421. }
  1422. mask = 1;
  1423. }
  1424. } else if (StringEqual(id, kpp_elif)) {
  1425. if (level == 0) {
  1426. Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
  1427. } else {
  1428. cond_lines[level - 1] = Getline(id);
  1429. if (allow) {
  1430. allow = 0;
  1431. mask = 0;
  1432. } else if (level == start_level) {
  1433. int val;
  1434. String *sval = Preprocessor_replace(value);
  1435. Seek(sval, 0, SEEK_SET);
  1436. val = Preprocessor_expr(sval, &e);
  1437. if (e) {
  1438. char *msg = Preprocessor_expr_error();
  1439. Seek(value, 0, SEEK_SET);
  1440. Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value);
  1441. if (msg)
  1442. Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg);
  1443. allow = 0;
  1444. } else {
  1445. if (val)
  1446. allow = 1 * mask;
  1447. else
  1448. allow = 0;
  1449. }
  1450. }
  1451. }
  1452. } else if (StringEqual(id, kpp_warning)) {
  1453. if (allow) {
  1454. Swig_warning(WARN_PP_CPP_WARNING, Getfile(s), Getline(id), "CPP #warning, %s\n", value);
  1455. }
  1456. } else if (StringEqual(id, kpp_error)) {
  1457. if (allow) {
  1458. if (error_as_warning) {
  1459. Swig_warning(WARN_PP_CPP_ERROR, Getfile(s), Getline(id), "CPP #error \"%s\".\n", value);
  1460. } else {
  1461. Swig_error(Getfile(s), Getline(id), "CPP #error \"%s\". Use the -cpperraswarn option to continue swig processing.\n", value);
  1462. }
  1463. }
  1464. } else if (StringEqual(id, kpp_line)) {
  1465. } else if (StringEqual(id, kpp_include)) {
  1466. if (((include_all) || (import_all)) && (allow)) {
  1467. String *s1, *s2, *fn;
  1468. char *dirname;
  1469. int sysfile = 0;
  1470. if (include_all && import_all) {
  1471. Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall");
  1472. import_all = 0;
  1473. }
  1474. Seek(value, 0, SEEK_SET);
  1475. fn = get_filename(value, &sysfile);
  1476. s1 = cpp_include(fn, sysfile);
  1477. if (s1) {
  1478. if (include_all)
  1479. Printf(ns, "%%includefile \"%s\" [\n", Swig_last_file());
  1480. else if (import_all) {
  1481. Printf(ns, "%%importfile \"%s\" [\n", Swig_last_file());
  1482. push_imported();
  1483. }
  1484. /* See if the filename has a directory component */
  1485. dirname = Swig_file_dirname(Swig_last_file());
  1486. if (sysfile || !strlen(dirname))
  1487. dirname = 0;
  1488. if (dirname) {
  1489. dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimeter */
  1490. Swig_push_directory(dirname);
  1491. }
  1492. s2 = Preprocessor_parse(s1);
  1493. addline(ns, s2, allow);
  1494. StringAppend(ns, "\n]");
  1495. if (dirname) {
  1496. Swig_pop_directory();
  1497. }
  1498. if (import_all) {
  1499. pop_imported();
  1500. }
  1501. Delete(s2);
  1502. }
  1503. Delete(s1);
  1504. Delete(fn);
  1505. }
  1506. } else if (StringEqual(id, kpp_pragma)) {
  1507. if (Strncmp(value, "SWIG ", 5) == 0) {
  1508. char *c = Char(value) + 5;
  1509. while (*c && (isspace((int) *c)))
  1510. c++;
  1511. if (*c) {
  1512. if (strncmp(c, "nowarn=", 7) == 0) {
  1513. String *val = NewString(c + 7);
  1514. String *nowarn = Preprocessor_replace(val);
  1515. Swig_warnfilter(nowarn, 1);
  1516. Delete(nowarn);
  1517. Delete(val);
  1518. } else if (strncmp(c, "cpperraswarn=", 7) == 0) {
  1519. error_as_warning = atoi(c + 13);
  1520. }
  1521. }
  1522. }
  1523. } else if (StringEqual(id, kpp_level)) {
  1524. Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level);
  1525. }
  1526. for (i = 0; i < cpp_lines; i++)
  1527. StringPutc('\n', ns);
  1528. state = 0;
  1529. break;
  1530. /* Swig directives */
  1531. case 100:
  1532. /* %{,%} block */
  1533. if (c == '{') {
  1534. start_line = Getline(s);
  1535. add_chunk(ns, chunk, allow);
  1536. copy_location(s, chunk);
  1537. StringPutc('%', chunk);
  1538. StringPutc(c, chunk);
  1539. state = 105;
  1540. }
  1541. /* %#cpp - an embedded C preprocessor directive (we strip off the %) */
  1542. else if (c == '#') {
  1543. add_chunk(ns, chunk, allow);
  1544. StringPutc(c, chunk);
  1545. state = 107;
  1546. } else if (isidentifier(c)) {
  1547. Clear(decl);
  1548. StringPutc('%', decl);
  1549. StringPutc(c, decl);
  1550. state = 110;
  1551. } else {
  1552. StringPutc('%', chunk);
  1553. StringPutc(c, chunk);
  1554. state = 1;
  1555. }
  1556. break;
  1557. case 105:
  1558. StringPutc(c, chunk);
  1559. if (c == '%')
  1560. state = 106;
  1561. break;
  1562. case 106:
  1563. StringPutc(c, chunk);
  1564. if (c == '}') {
  1565. state = 1;
  1566. addline(ns, chunk, allow);
  1567. Clear(chunk);
  1568. copy_location(s, chunk);
  1569. } else {
  1570. state = 105;
  1571. }
  1572. break;
  1573. case 107:
  1574. StringPutc(c, chunk);
  1575. if (c == '\n') {
  1576. addline(ns, chunk, allow);
  1577. Clear(chunk);
  1578. state = 0;
  1579. } else if (c == '\\') {
  1580. state = 108;
  1581. }
  1582. break;
  1583. case 108:
  1584. StringPutc(c, chunk);
  1585. state = 107;
  1586. break;
  1587. case 110:
  1588. if (!isidchar(c)) {
  1589. StringUngetc(c, s);
  1590. /* Look for common Swig directives */
  1591. if (StringEqual(decl, kpp_dinclude) || StringEqual(decl, kpp_dimport) || StringEqual(decl, kpp_dextern)) {
  1592. /* Got some kind of file inclusion directive */
  1593. if (allow) {
  1594. DOH *s1, *s2, *fn, *opt;
  1595. int sysfile = 0;
  1596. if (StringEqual(decl, kpp_dextern)) {
  1597. Swig_warning(WARN_DEPRECATED_EXTERN, Getfile(s), Getline(s), "%%extern is deprecated. Use %%import instead.\n");
  1598. Clear(decl);
  1599. StringAppend(decl, "%%import");
  1600. }
  1601. opt = get_options(s);
  1602. fn = get_filename(s, &sysfile);
  1603. s1 = cpp_include(fn, sysfile);
  1604. if (s1) {
  1605. char *dirname;
  1606. add_chunk(ns, chunk, allow);
  1607. copy_location(s, chunk);
  1608. Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_last_file());
  1609. if (StringEqual(decl, kpp_dimport)) {
  1610. push_imported();
  1611. }
  1612. dirname = Swig_file_dirname(Swig_last_file());
  1613. if (sysfile || !strlen(dirname))
  1614. dirname = 0;
  1615. if (dirname) {
  1616. dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimeter */
  1617. Swig_push_directory(dirname);
  1618. }
  1619. s2 = Preprocessor_parse(s1);
  1620. if (dirname) {
  1621. Swig_pop_directory();
  1622. }
  1623. if (StringEqual(decl, kpp_dimport)) {
  1624. pop_imported();
  1625. }
  1626. addline(ns, s2, allow);
  1627. StringAppend(ns, "\n]");
  1628. Delete(s2);
  1629. Delete(s1);
  1630. }
  1631. Delete(fn);
  1632. }
  1633. state = 1;
  1634. } else if (StringEqual(decl, kpp_dline)) {
  1635. /* Got a line directive */
  1636. state = 1;
  1637. } else if (StringEqual(decl, kpp_ddefine)) {
  1638. /* Got a define directive */
  1639. dlevel++;
  1640. add_chunk(ns, chunk, allow);
  1641. copy_location(s, chunk);
  1642. Clear(value);
  1643. copy_location(s, value);
  1644. state = 150;
  1645. } else {
  1646. StringAppend(chunk, decl);
  1647. state = 1;
  1648. }
  1649. } else {
  1650. StringPutc(c, decl);
  1651. }
  1652. break;
  1653. /* Searching for the end of a %define statement */
  1654. case 150:
  1655. StringPutc(c, value);
  1656. if (c == '%') {
  1657. const char *ed = "enddef";
  1658. const char *df = "define";
  1659. char statement[7];
  1660. int i = 0;
  1661. for (i = 0; i < 6;) {
  1662. c = StringGetc(s);
  1663. StringPutc(c, value);
  1664. statement[i++] = c;
  1665. if (strncmp(statement, ed, i) && strncmp(statement, df, i))
  1666. break;
  1667. }
  1668. c = StringGetc(s);
  1669. StringUngetc(c, s);
  1670. if ((i == 6) && (isspace(c))) {
  1671. if (strncmp(statement, df, i) == 0) {
  1672. ++dlevel;
  1673. } else {
  1674. if (strncmp(statement, ed, i) == 0) {
  1675. --dlevel;
  1676. if (!dlevel) {
  1677. /* Got the macro */
  1678. for (i = 0; i < 7; i++) {
  1679. Delitem(value, DOH_END);
  1680. }
  1681. if (allow) {
  1682. Seek(value, 0, SEEK_SET);
  1683. Preprocessor_define(value, 1);
  1684. }
  1685. /* StringPutc('\n',ns); */
  1686. addline(ns, value, 0);
  1687. state = 0;
  1688. }
  1689. }
  1690. }
  1691. }
  1692. }
  1693. break;
  1694. default:
  1695. Printf(stderr, "cpp: Invalid parser state %d\n", state);
  1696. abort();
  1697. break;
  1698. }
  1699. }
  1700. while (level > 0) {
  1701. Swig_error(Getfile(s), -1, "Missing #endif for conditional starting on line %d\n", cond_lines[level - 1]);
  1702. level--;
  1703. }
  1704. if (state == 150) {
  1705. Seek(value, 0, SEEK_SET);
  1706. Swig_error(Getfile(s), -1, "Missing %%enddef for macro starting on line %d\n", Getline(value));
  1707. }
  1708. if ((state >= 105) && (state < 107)) {
  1709. Swig_error(Getfile(s), -1, "Unterminated %%{ ... %%} block starting on line %d\n", start_line);
  1710. }
  1711. if ((state >= 30) && (state < 40)) {
  1712. Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
  1713. }
  1714. add_chunk(ns, chunk, allow);
  1715. copy_location(s, chunk);
  1716. /* DelScope(scp); */
  1717. Delete(decl);
  1718. Delete(id);
  1719. Delete(value);
  1720. Delete(comment);
  1721. Delete(chunk);
  1722. /* fprintf(stderr,"cpp: %d\n", Len(Getattr(cpp,"symbols"))); */
  1723. return ns;
  1724. }