/tags/rel-1-3-15/SWIG/Source/Swig/scanner.c

# · C · 814 lines · 614 code · 77 blank · 123 comment · 462 complexity · e5ec7b5c0053b3654ce1f94156f6d800 MD5 · raw file

  1. /* -----------------------------------------------------------------------------
  2. * scanner.c
  3. *
  4. * This file implements a general purpose C/C++ compatible lexical scanner.
  5. * This scanner isn't intended to be plugged directly into a parser built
  6. * with yacc. Rather, it contains a lot of generic code that could be used
  7. * to easily construct yacc-compatible scanners.
  8. *
  9. * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  10. *
  11. * Copyright (C) 1999-2000. The University of Chicago
  12. * See the file LICENSE for information on usage and redistribution.
  13. * ----------------------------------------------------------------------------- */
  14. static char cvsroot[] = "$Header$";
  15. #include "swig.h"
  16. #include <ctype.h>
  17. struct SwigScanner {
  18. String *text; /* Current token value */
  19. List *scanobjs; /* Objects being scanned */
  20. String *str; /* Current object being scanned */
  21. char *idstart; /* Optional identifier start characters */
  22. int nexttoken; /* Next token to be returned */
  23. int start_line; /* Starting line of certain declarations */
  24. int string_start;
  25. int line;
  26. int yylen; /* Length of text pushed into text */
  27. String *file;
  28. };
  29. /* -----------------------------------------------------------------------------
  30. * NewSwigScanner()
  31. *
  32. * Create a new scanner object
  33. * ----------------------------------------------------------------------------- */
  34. SwigScanner *
  35. NewSwigScanner() {
  36. SwigScanner *s;
  37. s = (SwigScanner *) malloc(sizeof(SwigScanner));
  38. s->line = 1;
  39. s->file = 0;
  40. s->nexttoken = -1;
  41. s->start_line = 1;
  42. s->string_start = 0;
  43. s->yylen = 0;
  44. s->idstart = "";
  45. s->scanobjs = NewList();
  46. s->text = NewString("");
  47. s->str = 0;
  48. return s;
  49. }
  50. /* -----------------------------------------------------------------------------
  51. * DelSwigScanner()
  52. *
  53. * Delete a scanner object.
  54. * ----------------------------------------------------------------------------- */
  55. void
  56. DelSwigScanner(SwigScanner *s) {
  57. assert(s);
  58. Delete(s->scanobjs);
  59. Delete(s->text);
  60. Delete(s->file);
  61. free(s);
  62. }
  63. /* -----------------------------------------------------------------------------
  64. * SwigScanner_clear()
  65. *
  66. * Clear the contents of a scanner object.
  67. * ----------------------------------------------------------------------------- */
  68. void
  69. SwigScanner_clear(SwigScanner *s) {
  70. assert(s);
  71. Delete(s->str);
  72. Clear(s->text);
  73. Clear(s->scanobjs);
  74. s->line = 1;
  75. s->nexttoken = -1;
  76. s->start_line = 0;
  77. s->string_start = 0;
  78. s->yylen = 0;
  79. }
  80. /* -----------------------------------------------------------------------------
  81. * SwigScanner_push()
  82. *
  83. * Push some new text into the scanner. The scanner will start parsing this text
  84. * immediately before returning to the old text.
  85. * ----------------------------------------------------------------------------- */
  86. void
  87. SwigScanner_push(SwigScanner *s, String *txt) {
  88. assert(s && txt);
  89. Push(s->scanobjs,txt);
  90. if (s->str) Delete(s->str);
  91. s->str = txt;
  92. DohIncref(s->str);
  93. s->line = Getline(txt);
  94. }
  95. /* -----------------------------------------------------------------------------
  96. * SwigScanner_pushtoken()
  97. *
  98. * Push a token into the scanner. This token will be returned on the next
  99. * call to SwigScanner_token().
  100. * ----------------------------------------------------------------------------- */
  101. void
  102. SwigScanner_pushtoken(SwigScanner *s, int nt) {
  103. assert(s);
  104. assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
  105. s->nexttoken = nt;
  106. }
  107. /* -----------------------------------------------------------------------------
  108. * SwigScanner_set_location()
  109. *
  110. * Set the file and line number location of the scanner.
  111. * ----------------------------------------------------------------------------- */
  112. void
  113. SwigScanner_set_location(SwigScanner *s, String *file, int line) {
  114. Setline(s->str,line);
  115. Setfile(s->str,file);
  116. }
  117. /* -----------------------------------------------------------------------------
  118. * SwigScanner_get_file()
  119. *
  120. * Get the current file.
  121. * ----------------------------------------------------------------------------- */
  122. String *
  123. SwigScanner_get_file(SwigScanner *s) {
  124. return Getfile(s->str);
  125. }
  126. /* -----------------------------------------------------------------------------
  127. * SwigScanner_get_line()
  128. *
  129. * Get the current line number
  130. * ----------------------------------------------------------------------------- */
  131. int
  132. SwigScanner_get_line(SwigScanner *s) {
  133. return Getline(s->str);
  134. }
  135. /* -----------------------------------------------------------------------------
  136. * SwigScanner_idstart()
  137. *
  138. * Change the set of additional characters that can be used to start an identifier.
  139. * ----------------------------------------------------------------------------- */
  140. void
  141. SwigScanner_idstart(SwigScanner *s, char *id) {
  142. s->idstart = Swig_copy_string(id);
  143. }
  144. /* -----------------------------------------------------------------------------
  145. * nextchar()
  146. *
  147. * Returns the next character from the scanner or 0 if end of the string.
  148. * ----------------------------------------------------------------------------- */
  149. static char
  150. nextchar(SwigScanner *s)
  151. {
  152. char c[2] = {0,0};
  153. int nc;
  154. if (!s->str) return 0;
  155. while ((nc = Getc(s->str)) == EOF) {
  156. Delete(s->str);
  157. s->str = 0;
  158. Delitem(s->scanobjs,0);
  159. if (Len(s->scanobjs) == 0) return 0;
  160. s->str = Getitem(s->scanobjs,0);
  161. if (s->str) {
  162. s->line = Getline(s->str);
  163. DohIncref(s->str);
  164. }
  165. }
  166. if (nc == '\n') s->line++;
  167. c[0] = (char) nc;
  168. c[1] = 0;
  169. Append(s->text,c);
  170. return c[0];
  171. }
  172. /* -----------------------------------------------------------------------------
  173. * retract()
  174. *
  175. * Retract n characters
  176. * ----------------------------------------------------------------------------- */
  177. static void
  178. retract(SwigScanner *s, int n) {
  179. int i, l;
  180. char *str;
  181. str = Char(s->text);
  182. l = Len(s->text);
  183. assert(n <= l);
  184. for (i = 0; i < n; i++) {
  185. if (str[l-1] == '\n') {
  186. s->line--;
  187. }
  188. /* // Ungetc(str[l-1],s->str); */
  189. Seek(s->str,-1, SEEK_CUR);
  190. Delitem(s->text,DOH_END);
  191. }
  192. }
  193. /* -----------------------------------------------------------------------------
  194. * look()
  195. *
  196. * Return the raw value of the next token.
  197. * ----------------------------------------------------------------------------- */
  198. static int
  199. look(SwigScanner *s) {
  200. int state;
  201. char c = 0;
  202. state = 0;
  203. Clear(s->text);
  204. Setline(s->text, Getline(s->str));
  205. Setfile(s->text, Getfile(s->str));
  206. while(1) {
  207. switch(state) {
  208. case 0 :
  209. if((c = nextchar(s)) == 0) return(0);
  210. /* Process delimeters */
  211. if (c == '\n') {
  212. return SWIG_TOKEN_ENDLINE;
  213. } else if (!isspace(c)) {
  214. retract(s,1);
  215. state = 1000;
  216. Clear(s->text);
  217. Setline(s->text, Getline(s->str));
  218. Setfile(s->text, Getfile(s->str));
  219. }
  220. break;
  221. case 1000:
  222. if ((c = nextchar(s)) == 0) return (0);
  223. if (c == '%') state = 4; /* Possibly a SWIG directive */
  224. /* Look for possible identifiers */
  225. else if ((isalpha(c)) || (c == '_') || (strchr(s->idstart,c))) state = 7;
  226. /* Look for single character symbols */
  227. else if (c == '(') return SWIG_TOKEN_LPAREN;
  228. else if (c == ')') return SWIG_TOKEN_RPAREN;
  229. else if (c == ';') return SWIG_TOKEN_SEMI;
  230. else if (c == ',') return SWIG_TOKEN_COMMA;
  231. else if (c == '*') return SWIG_TOKEN_STAR;
  232. else if (c == '}') return SWIG_TOKEN_RBRACE;
  233. else if (c == '{') return SWIG_TOKEN_LBRACE;
  234. else if (c == '=') state = 33;
  235. else if (c == '+') return SWIG_TOKEN_PLUS;
  236. else if (c == '-') return SWIG_TOKEN_MINUS;
  237. else if (c == '&') state = 31;
  238. else if (c == '|') state = 32;
  239. else if (c == '^') return SWIG_TOKEN_XOR;
  240. else if (c == '<') state = 60;
  241. else if (c == '>') state = 61;
  242. else if (c == '~') return SWIG_TOKEN_NOT;
  243. else if (c == '!') state = 3;
  244. else if (c == '\\') return SWIG_TOKEN_BACKSLASH;
  245. else if (c == '[') return SWIG_TOKEN_LBRACKET;
  246. else if (c == ']') return SWIG_TOKEN_RBRACKET;
  247. else if (c == '@') return SWIG_TOKEN_AT;
  248. else if (c == '$') return SWIG_TOKEN_DOLLAR;
  249. else if (c == '#') return SWIG_TOKEN_POUND;
  250. /* Look for multi-character sequences */
  251. else if (c == '/') state = 1; /* Comment (maybe) */
  252. else if (c == '\"') {
  253. state = 2; /* Possibly a string */
  254. s->string_start = s->line;
  255. }
  256. else if (c == ':') state = 5; /* maybe double colon */
  257. else if (c == '0') state = 83; /* An octal or hex value */
  258. else if (c == '\'') {
  259. s->string_start = s->line;
  260. state = 9; /* A character constant */
  261. }
  262. else if (c == '`') {
  263. s->string_start = s->line;
  264. state = 900;
  265. }
  266. else if (c == '.') state = 100; /* Maybe a number, maybe just a period */
  267. else if (isdigit(c)) state = 8; /* A numerical value */
  268. else state = 99; /* An error */
  269. break;
  270. case 1: /* Comment block */
  271. if ((c = nextchar(s)) == 0) return(0);
  272. if (c == '/') {
  273. state = 10; /* C++ style comment */
  274. Clear(s->text);
  275. Setline(s->text, Getline(s->str));
  276. Setfile(s->text, Getfile(s->str));
  277. Append(s->text," ");
  278. } else if (c == '*') {
  279. state = 11; /* C style comment */
  280. Clear(s->text);
  281. Setline(s->text, Getline(s->str));
  282. Setfile(s->text, Getfile(s->str));
  283. Append(s->text," ");
  284. } else {
  285. retract(s,1);
  286. return SWIG_TOKEN_SLASH;
  287. }
  288. break;
  289. case 10: /* C++ style comment */
  290. if ((c = nextchar(s)) == 0) {
  291. /* add_error(0,"Unterminated comment",comment_start); */
  292. return 0;
  293. }
  294. if (c == '\n') {
  295. return SWIG_TOKEN_ENDLINE;
  296. } else {
  297. state = 10;
  298. }
  299. break;
  300. case 11: /* C style comment block */
  301. if ((c = nextchar(s)) == 0) {
  302. /* add_error(0,"Unterminated comment",comment_start); */
  303. return 0;
  304. }
  305. if (c == '*') {
  306. state = 12;
  307. } else {
  308. state = 11;
  309. }
  310. break;
  311. case 12: /* Still in C style comment */
  312. if ((c = nextchar(s)) == 0) {
  313. /* add_error(0,"Unterminated comment",comment_start); */
  314. return 0;
  315. }
  316. if (c == '*') {
  317. state = 12;
  318. } else if (c == '/') {
  319. Clear(s->text);
  320. state = 0;
  321. } else {
  322. state = 11;
  323. }
  324. break;
  325. case 2: /* Processing a string */
  326. if ((c = nextchar(s)) == 0) {
  327. /* add_error(0,"Unterminated string", string_start); */
  328. return 0;
  329. }
  330. if (c == '\"') {
  331. return SWIG_TOKEN_STRING;
  332. } else if (c == '\\') {
  333. state = 21; /* Possibly an escape sequence. */
  334. break;
  335. } else state = 2;
  336. break;
  337. case 21: /* An escape sequence. get next character, then go
  338. back to processing strings */
  339. if ((c = nextchar(s)) == 0) return 0;
  340. state = 2;
  341. break;
  342. case 3: /* Maybe a not equals */
  343. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LNOT;
  344. else if (c == '=') return SWIG_TOKEN_NOTEQUAL;
  345. else {
  346. retract(s,1);
  347. return SWIG_TOKEN_LNOT;
  348. }
  349. break;
  350. case 31: /* AND or Logical AND */
  351. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_AND;
  352. else if (c == '&') return SWIG_TOKEN_LAND;
  353. else {
  354. retract(s,1);
  355. return SWIG_TOKEN_AND;
  356. }
  357. break;
  358. case 32: /* OR or Logical OR */
  359. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_OR;
  360. else if (c == '|') return SWIG_TOKEN_LOR;
  361. else {
  362. retract(s,1);
  363. return SWIG_TOKEN_OR;
  364. }
  365. break;
  366. case 33: /* EQUAL or EQUALTO */
  367. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_EQUAL;
  368. else if (c == '=') return SWIG_TOKEN_EQUALTO;
  369. else {
  370. retract(s,1);
  371. return SWIG_TOKEN_EQUAL;
  372. }
  373. break;
  374. case 4: /* A wrapper generator directive (maybe) */
  375. if (( c= nextchar(s)) == 0) return SWIG_TOKEN_PERCENT;
  376. if (c == '{') {
  377. state = 40; /* Include block */
  378. Clear(s->text);
  379. Setline(s->text, Getline(s->str));
  380. Setfile(s->text, Getfile(s->str));
  381. s->start_line = s->line;
  382. }
  383. else if (strchr(s->idstart,'%') && ((isalpha(c)) || (c == '_'))) state = 7;
  384. else {
  385. retract(s,1);
  386. return SWIG_TOKEN_PERCENT;
  387. }
  388. break;
  389. case 40: /* Process an include block */
  390. if ((c = nextchar(s)) == 0) {
  391. /* add_error(0,"Unterminated code block.", start_line); */
  392. return 0;
  393. }
  394. if (c == '%') state = 41;
  395. break;
  396. case 41: /* Still processing include block */
  397. if ((c = nextchar(s)) == 0) {
  398. /* add_error(0,"Unterminated code block.", start_line); */
  399. return 0;
  400. }
  401. if (c == '}') {
  402. Delitem(s->text,DOH_END);
  403. Delitem(s->text,DOH_END);
  404. return SWIG_TOKEN_CODEBLOCK;
  405. } else {
  406. state = 40;
  407. }
  408. break;
  409. case 5: /* Maybe a double colon */
  410. if (( c = nextchar(s)) == 0) return SWIG_TOKEN_COLON;
  411. if ( c == ':') return SWIG_TOKEN_DCOLON;
  412. else {
  413. retract(s,1);
  414. return SWIG_TOKEN_COLON;
  415. }
  416. break;
  417. case 60: /* shift operators */
  418. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LESSTHAN;
  419. if (c == '<') return SWIG_TOKEN_LSHIFT;
  420. else if (c == '=') return SWIG_TOKEN_LTEQUAL;
  421. else {
  422. retract(s,1);
  423. return SWIG_TOKEN_LESSTHAN;
  424. }
  425. break;
  426. case 61:
  427. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_GREATERTHAN;
  428. if (c == '>') return SWIG_TOKEN_RSHIFT;
  429. else if (c == '=') return SWIG_TOKEN_GTEQUAL;
  430. else {
  431. retract(s,1);
  432. return SWIG_TOKEN_GREATERTHAN;
  433. }
  434. break;
  435. case 7: /* Identifier */
  436. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_ID;
  437. if (isalnum(c) || (c == '_') || (c == '$')) {
  438. state = 7;
  439. } else {
  440. retract(s,1);
  441. return SWIG_TOKEN_ID;
  442. }
  443. break;
  444. case 8: /* A numerical digit */
  445. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_INT;
  446. if (c == '.') {state = 81;}
  447. else if ((c == 'e') || (c == 'E')) {state = 86;}
  448. else if ((c == 'f') || (c == 'F')) {
  449. Delitem(s->text,DOH_END);
  450. return SWIG_TOKEN_FLOAT;
  451. } else if (isdigit(c)) { state = 8;}
  452. else if ((c == 'l') || (c == 'L')) {
  453. state = 87;
  454. } else if ((c == 'u') || (c == 'U')) {
  455. state = 88;
  456. } else {
  457. retract(s,1);
  458. return SWIG_TOKEN_INT;
  459. }
  460. break;
  461. case 81: /* A floating pointer number of some sort */
  462. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_DOUBLE;
  463. if (isdigit(c)) state = 81;
  464. else if ((c == 'e') || (c == 'E')) state = 82;
  465. else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) {
  466. Delitem(s->text,DOH_END);
  467. return SWIG_TOKEN_FLOAT;
  468. } else {
  469. retract(s,1);
  470. return(SWIG_TOKEN_DOUBLE);
  471. }
  472. break;
  473. case 82:
  474. if ((c = nextchar(s)) == 0) {
  475. retract(s,1);
  476. return SWIG_TOKEN_INT;
  477. }
  478. if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86;
  479. else {
  480. retract(s,2);
  481. return(SWIG_TOKEN_INT);
  482. }
  483. break;
  484. case 83:
  485. /* Might be a hexidecimal or octal number */
  486. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_INT;
  487. if (isdigit(c)) state = 84;
  488. else if ((c == 'x') || (c == 'X')) state = 85;
  489. else if (c == '.') state = 81;
  490. else if ((c == 'l') || (c == 'L')) {
  491. state = 87;
  492. } else if ((c == 'u') || (c == 'U')) {
  493. state = 88;
  494. } else {
  495. retract(s,1);
  496. return SWIG_TOKEN_INT;
  497. }
  498. break;
  499. case 84:
  500. /* This is an octal number */
  501. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_INT;
  502. if (isdigit(c)) state = 84;
  503. else if ((c == 'l') || (c == 'L')) {
  504. state = 87;
  505. } else if ((c == 'u') || (c == 'U')) {
  506. state = 88;
  507. } else {
  508. retract(s,1);
  509. return SWIG_TOKEN_INT;
  510. }
  511. break;
  512. case 85:
  513. /* This is an hex number */
  514. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_INT;
  515. if ((isdigit(c)) || (c=='a') || (c=='b') || (c=='c') ||
  516. (c=='d') || (c=='e') || (c=='f') || (c=='A') ||
  517. (c=='B') || (c=='C') || (c=='D') || (c=='E') ||
  518. (c=='F'))
  519. state = 85;
  520. else if ((c == 'l') || (c == 'L')) {
  521. state = 87;
  522. } else if ((c == 'u') || (c == 'U')) {
  523. state = 88;
  524. } else {
  525. retract(s,1);
  526. return SWIG_TOKEN_INT;
  527. }
  528. break;
  529. case 86:
  530. /* Rest of floating point number */
  531. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_DOUBLE;
  532. if (isdigit(c)) state = 86;
  533. else if ((c == 'f') || (c == 'F')) {
  534. Delitem(s->text,DOH_END);
  535. return SWIG_TOKEN_FLOAT;
  536. } else if ((c == 'l') || (c == 'L')) {
  537. Delitem(s->text,DOH_END);
  538. return SWIG_TOKEN_DOUBLE;
  539. } else {
  540. retract(s,1);
  541. return SWIG_TOKEN_DOUBLE;
  542. }
  543. break;
  544. case 87 :
  545. /* A long integer of some sort */
  546. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LONG;
  547. if ((c == 'u') || (c == 'U')) {
  548. return SWIG_TOKEN_ULONG;
  549. } else if ((c == 'l') || (c == 'L')) {
  550. state = 870;
  551. } else {
  552. retract(s,1);
  553. return SWIG_TOKEN_LONG;
  554. }
  555. break;
  556. /* A long long integer */
  557. case 870:
  558. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_LONGLONG;
  559. if ((c == 'u') || (c == 'U')) {
  560. return SWIG_TOKEN_ULONGLONG;
  561. } else {
  562. retract(s,1);
  563. return SWIG_TOKEN_LONGLONG;
  564. }
  565. /* An unsigned number */
  566. case 88:
  567. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_UINT;
  568. if ((c == 'l') || (c == 'L')) {
  569. state = 880;
  570. } else {
  571. retract(s,1);
  572. return SWIG_TOKEN_UINT;
  573. }
  574. break;
  575. /* Possibly an unsigned long long or unsigned long */
  576. case 880:
  577. if ((c = nextchar(s)) == 0) return SWIG_TOKEN_ULONG;
  578. if ((c == 'l') || (c == 'L')) return SWIG_TOKEN_ULONGLONG;
  579. else {
  580. retract(s,1);
  581. return SWIG_TOKEN_ULONG;
  582. }
  583. /* A character constant */
  584. case 9:
  585. if ((c = nextchar(s)) == 0) {
  586. /* add_error(0,"Unterminated character constant", string_start); */
  587. return 0;
  588. }
  589. if (c == '\'') {
  590. return(SWIG_TOKEN_CHAR);
  591. } else if (c == '\\') state = 91;
  592. break;
  593. case 91:
  594. if ((c = nextchar(s)) == 0) {
  595. /* add_error(0,"Unterminated character constant", string_start); */
  596. return 0;
  597. }
  598. state = 9;
  599. break;
  600. /* A period or maybe a floating point number */
  601. case 100:
  602. if ((c = nextchar(s)) == 0) return (0);
  603. if (isdigit(c)) state = 81;
  604. else {
  605. retract(s,1);
  606. return SWIG_TOKEN_PERIOD;
  607. }
  608. break;
  609. /* An illegal character */
  610. /* Reverse string */
  611. case 900:
  612. if ((c = nextchar(s)) == 0) {
  613. /* add_error(0,"Unterminated character constant", string_start); */
  614. return 0;
  615. }
  616. if (c == '`') {
  617. return(SWIG_TOKEN_RSTRING);
  618. }
  619. break;
  620. default:
  621. return SWIG_TOKEN_ILLEGAL;
  622. }
  623. }
  624. }
  625. /* -----------------------------------------------------------------------------
  626. * SwigScanner_token()
  627. *
  628. * Real entry point to return the next token. Returns 0 if at end of input.
  629. * ----------------------------------------------------------------------------- */
  630. int
  631. SwigScanner_token(SwigScanner *s) {
  632. int t;
  633. Clear(s->text);
  634. if (s->nexttoken >= 0) {
  635. t = s->nexttoken;
  636. s->nexttoken = -1;
  637. return t;
  638. }
  639. t = look(s);
  640. return t;
  641. }
  642. /* -----------------------------------------------------------------------------
  643. * SwigScanner_text()
  644. *
  645. * Return the lexene associated with the last returned token.
  646. * ----------------------------------------------------------------------------- */
  647. String *
  648. SwigScanner_text(SwigScanner *s) {
  649. return s->text;
  650. }
  651. /* -----------------------------------------------------------------------------
  652. * SwigScanner_skip_line()
  653. *
  654. * Skips to the end of a line
  655. * ----------------------------------------------------------------------------- */
  656. void
  657. SwigScanner_skip_line(SwigScanner *s) {
  658. char c;
  659. int done = 0;
  660. Clear(s->text);
  661. Setfile(s->text,Getfile(s->str));
  662. Setline(s->text,Getline(s->str));
  663. while (!done) {
  664. if ((c = nextchar(s)) == 0) return;
  665. if (c == '\\') c = nextchar(s);
  666. else if (c == '\n') done = 1;
  667. }
  668. return;
  669. }
  670. /* -----------------------------------------------------------------------------
  671. * SwigScanner_skip_balanced()
  672. *
  673. * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
  674. * (...). Ignores symbols inside comments or strings.
  675. * ----------------------------------------------------------------------------- */
  676. int
  677. SwigScanner_skip_balanced(SwigScanner *s, int startchar, int endchar) {
  678. char c;
  679. int num_levels = 1;
  680. int l;
  681. int state = 0;
  682. char temp[2] = {0,0};
  683. l = s->line;
  684. temp[0] = (char) startchar;
  685. Clear(s->text);
  686. Setfile(s->text,Getfile(s->str));
  687. Setline(s->text,Getline(s->str));
  688. Append(s->text,temp);
  689. while (num_levels > 0) {
  690. if ((c = nextchar(s)) == 0) {
  691. return -1;
  692. }
  693. switch(state) {
  694. case 0:
  695. if (c == startchar) num_levels++;
  696. else if (c == endchar) num_levels--;
  697. else if (c == '/') state = 10;
  698. else if (c == '\"') state = 20;
  699. else if (c == '\'') state = 30;
  700. break;
  701. case 10:
  702. if (c == '/') state = 11;
  703. else if (c == '*') state = 12;
  704. else state = 0;
  705. break;
  706. case 11:
  707. if (c == '\n') state = 0;
  708. else state = 11;
  709. break;
  710. case 12:
  711. if (c == '*') state = 13;
  712. break;
  713. case 13:
  714. if (c == '*') state = 13;
  715. else if (c == '/') state = 0;
  716. else state = 12;
  717. break;
  718. case 20:
  719. if (c == '\"') state = 0;
  720. else if (c == '\\') state = 21;
  721. break;
  722. case 21:
  723. state = 20;
  724. break;
  725. case 30:
  726. if (c == '\'') state = 0;
  727. else if (c == '\\') state = 31;
  728. break;
  729. case 31:
  730. state = 30;
  731. break;
  732. default:
  733. break;
  734. }
  735. }
  736. return 0;
  737. }