PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Swig/scanner.c

#
C | 1383 lines | 1130 code | 95 blank | 158 comment | 501 complexity | 4c72784d9cc24a0ccf27b26bd6651ee1 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. * scanner.c
  10. *
  11. * This file implements a general purpose C/C++ compatible lexical scanner.
  12. * This scanner isn't intended to be plugged directly into a parser built
  13. * with yacc. Rather, it contains a lot of generic code that could be used
  14. * to easily construct yacc-compatible scanners.
  15. * ----------------------------------------------------------------------------- */
  16. char cvsroot_scanner_c[] = "$Id: scanner.c 12536 2011-03-14 07:22:08Z wsfulton $";
  17. #include "swig.h"
  18. #include <ctype.h>
  19. extern String *cparse_file;
  20. extern int cparse_line;
  21. extern int cparse_cplusplus;
  22. extern int cparse_start_line;
  23. struct Scanner {
  24. String *text; /* Current token value */
  25. List *scanobjs; /* Objects being scanned */
  26. String *str; /* Current object being scanned */
  27. char *idstart; /* Optional identifier start characters */
  28. int nexttoken; /* Next token to be returned */
  29. int start_line; /* Starting line of certain declarations */
  30. int line;
  31. int yylen; /* Length of text pushed into text */
  32. String *file;
  33. String *error; /* Last error message (if any) */
  34. int error_line; /* Error line number */
  35. int freeze_line; /* Suspend line number updates */
  36. };
  37. typedef struct Locator {
  38. String *filename;
  39. int line_number;
  40. struct Locator *next;
  41. } Locator;
  42. static int follow_locators = 0;
  43. /* -----------------------------------------------------------------------------
  44. * NewScanner()
  45. *
  46. * Create a new scanner object
  47. * ----------------------------------------------------------------------------- */
  48. Scanner *NewScanner(void) {
  49. Scanner *s;
  50. s = (Scanner *) malloc(sizeof(Scanner));
  51. s->line = 1;
  52. s->file = 0;
  53. s->nexttoken = -1;
  54. s->start_line = 1;
  55. s->yylen = 0;
  56. s->idstart = NULL;
  57. s->scanobjs = NewList();
  58. s->text = NewStringEmpty();
  59. s->str = 0;
  60. s->error = 0;
  61. s->freeze_line = 0;
  62. return s;
  63. }
  64. /* -----------------------------------------------------------------------------
  65. * DelScanner()
  66. *
  67. * Delete a scanner object.
  68. * ----------------------------------------------------------------------------- */
  69. void DelScanner(Scanner * s) {
  70. assert(s);
  71. Delete(s->scanobjs);
  72. Delete(s->text);
  73. Delete(s->file);
  74. Delete(s->error);
  75. Delete(s->str);
  76. free(s->idstart);
  77. free(s);
  78. }
  79. /* -----------------------------------------------------------------------------
  80. * Scanner_clear()
  81. *
  82. * Clear the contents of a scanner object.
  83. * ----------------------------------------------------------------------------- */
  84. void Scanner_clear(Scanner * s) {
  85. assert(s);
  86. Delete(s->str);
  87. Clear(s->text);
  88. Clear(s->scanobjs);
  89. Delete(s->error);
  90. s->str = 0;
  91. s->error = 0;
  92. s->line = 1;
  93. s->nexttoken = -1;
  94. s->start_line = 0;
  95. s->yylen = 0;
  96. }
  97. /* -----------------------------------------------------------------------------
  98. * Scanner_push()
  99. *
  100. * Push some new text into the scanner. The scanner will start parsing this text
  101. * immediately before returning to the old text.
  102. * ----------------------------------------------------------------------------- */
  103. void Scanner_push(Scanner * s, String *txt) {
  104. assert(s && txt);
  105. Push(s->scanobjs, txt);
  106. if (s->str) {
  107. Setline(s->str,s->line);
  108. Delete(s->str);
  109. }
  110. s->str = txt;
  111. DohIncref(s->str);
  112. s->line = Getline(txt);
  113. }
  114. /* -----------------------------------------------------------------------------
  115. * Scanner_pushtoken()
  116. *
  117. * Push a token into the scanner. This token will be returned on the next
  118. * call to Scanner_token().
  119. * ----------------------------------------------------------------------------- */
  120. void Scanner_pushtoken(Scanner * s, int nt, const_String_or_char_ptr val) {
  121. assert(s);
  122. assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
  123. s->nexttoken = nt;
  124. if ( Char(val) != Char(s->text) ) {
  125. Clear(s->text);
  126. Append(s->text,val);
  127. }
  128. }
  129. /* -----------------------------------------------------------------------------
  130. * Scanner_set_location()
  131. *
  132. * Set the file and line number location of the scanner.
  133. * ----------------------------------------------------------------------------- */
  134. void Scanner_set_location(Scanner * s, String *file, int line) {
  135. Setline(s->str, line);
  136. Setfile(s->str, file);
  137. s->line = line;
  138. }
  139. /* -----------------------------------------------------------------------------
  140. * Scanner_file()
  141. *
  142. * Get the current file.
  143. * ----------------------------------------------------------------------------- */
  144. String *Scanner_file(Scanner * s) {
  145. return Getfile(s->str);
  146. }
  147. /* -----------------------------------------------------------------------------
  148. * Scanner_line()
  149. *
  150. * Get the current line number
  151. * ----------------------------------------------------------------------------- */
  152. int Scanner_line(Scanner * s) {
  153. return s->line;
  154. }
  155. /* -----------------------------------------------------------------------------
  156. * Scanner_start_line()
  157. *
  158. * Get the line number on which the current token starts
  159. * ----------------------------------------------------------------------------- */
  160. int Scanner_start_line(Scanner * s) {
  161. return s->start_line;
  162. }
  163. /* -----------------------------------------------------------------------------
  164. * Scanner_idstart()
  165. *
  166. * Change the set of additional characters that can be used to start an identifier.
  167. * ----------------------------------------------------------------------------- */
  168. void Scanner_idstart(Scanner * s, const char *id) {
  169. free(s->idstart);
  170. s->idstart = Swig_copy_string(id);
  171. }
  172. /* -----------------------------------------------------------------------------
  173. * nextchar()
  174. *
  175. * Returns the next character from the scanner or 0 if end of the string.
  176. * ----------------------------------------------------------------------------- */
  177. static char nextchar(Scanner * s) {
  178. int nc;
  179. if (!s->str)
  180. return 0;
  181. while ((nc = Getc(s->str)) == EOF) {
  182. Delete(s->str);
  183. s->str = 0;
  184. Delitem(s->scanobjs, 0);
  185. if (Len(s->scanobjs) == 0)
  186. return 0;
  187. s->str = Getitem(s->scanobjs, 0);
  188. if (s->str) {
  189. s->line = Getline(s->str);
  190. DohIncref(s->str);
  191. }
  192. }
  193. if ((nc == '\n') && (!s->freeze_line))
  194. s->line++;
  195. Putc(nc,s->text);
  196. return (char)nc;
  197. }
  198. /* -----------------------------------------------------------------------------
  199. * set_error()
  200. *
  201. * Sets error information on the scanner.
  202. * ----------------------------------------------------------------------------- */
  203. static void set_error(Scanner *s, int line, const_String_or_char_ptr msg) {
  204. s->error_line = line;
  205. s->error = NewString(msg);
  206. }
  207. /* -----------------------------------------------------------------------------
  208. * Scanner_errmsg()
  209. * Scanner_errline()
  210. *
  211. * Returns error information (if any)
  212. * ----------------------------------------------------------------------------- */
  213. String *Scanner_errmsg(Scanner *s) {
  214. return s->error;
  215. }
  216. int
  217. Scanner_errline(Scanner *s) {
  218. return s->error_line;
  219. }
  220. /* -----------------------------------------------------------------------------
  221. * freeze_line()
  222. *
  223. * Freezes the current line number.
  224. * ----------------------------------------------------------------------------- */
  225. static void freeze_line(Scanner *s, int val) {
  226. s->freeze_line = val;
  227. }
  228. /* -----------------------------------------------------------------------------
  229. * retract()
  230. *
  231. * Retract n characters
  232. * ----------------------------------------------------------------------------- */
  233. static void retract(Scanner * s, int n) {
  234. int i, l;
  235. char *str;
  236. str = Char(s->text);
  237. l = Len(s->text);
  238. assert(n <= l);
  239. for (i = 0; i < n; i++) {
  240. if (str[l - 1] == '\n') {
  241. if (!s->freeze_line) s->line--;
  242. }
  243. Seek(s->str, -1, SEEK_CUR);
  244. Delitem(s->text, DOH_END);
  245. }
  246. }
  247. /* -----------------------------------------------------------------------------
  248. * get_escape()
  249. *
  250. * Get escape sequence. Called when a backslash is found in a string
  251. * ----------------------------------------------------------------------------- */
  252. static void get_escape(Scanner *s) {
  253. int result = 0;
  254. int state = 0;
  255. int c;
  256. while (1) {
  257. c = nextchar(s);
  258. if (c == 0)
  259. break;
  260. switch (state) {
  261. case 0:
  262. if (c == 'n') {
  263. Delitem(s->text, DOH_END);
  264. Append(s->text,"\n");
  265. return;
  266. }
  267. if (c == 'r') {
  268. Delitem(s->text, DOH_END);
  269. Append(s->text,"\r");
  270. return;
  271. }
  272. if (c == 't') {
  273. Delitem(s->text, DOH_END);
  274. Append(s->text,"\t");
  275. return;
  276. }
  277. if (c == 'a') {
  278. Delitem(s->text, DOH_END);
  279. Append(s->text,"\a");
  280. return;
  281. }
  282. if (c == 'b') {
  283. Delitem(s->text, DOH_END);
  284. Append(s->text,"\b");
  285. return;
  286. }
  287. if (c == 'f') {
  288. Delitem(s->text, DOH_END);
  289. Append(s->text,"\f");
  290. return;
  291. }
  292. if (c == '\\') {
  293. Delitem(s->text, DOH_END);
  294. Append(s->text,"\\");
  295. return;
  296. }
  297. if (c == 'v') {
  298. Delitem(s->text, DOH_END);
  299. Append(s->text,"\v");
  300. return;
  301. }
  302. if (c == 'e') {
  303. Delitem(s->text, DOH_END);
  304. Append(s->text,"\033");
  305. return;
  306. }
  307. if (c == '\'') {
  308. Delitem(s->text, DOH_END);
  309. Append(s->text,"\'");
  310. return;
  311. }
  312. if (c == '\"') {
  313. Delitem(s->text, DOH_END);
  314. Append(s->text,"\"");
  315. return;
  316. }
  317. if (c == '\n') {
  318. Delitem(s->text, DOH_END);
  319. return;
  320. }
  321. if (isdigit(c)) {
  322. state = 10;
  323. result = (c - '0');
  324. Delitem(s->text, DOH_END);
  325. } else if (c == 'x') {
  326. state = 20;
  327. Delitem(s->text, DOH_END);
  328. } else {
  329. char tmp[3];
  330. tmp[0] = '\\';
  331. tmp[1] = (char)c;
  332. tmp[2] = 0;
  333. Delitem(s->text, DOH_END);
  334. Append(s->text, tmp);
  335. return;
  336. }
  337. break;
  338. case 10:
  339. if (!isdigit(c)) {
  340. retract(s,1);
  341. Putc((char)result,s->text);
  342. return;
  343. }
  344. result = (result << 3) + (c - '0');
  345. Delitem(s->text, DOH_END);
  346. break;
  347. case 20:
  348. if (!isxdigit(c)) {
  349. retract(s,1);
  350. Putc((char)result, s->text);
  351. return;
  352. }
  353. if (isdigit(c))
  354. result = (result << 4) + (c - '0');
  355. else
  356. result = (result << 4) + (10 + tolower(c) - 'a');
  357. Delitem(s->text, DOH_END);
  358. break;
  359. }
  360. }
  361. return;
  362. }
  363. /* -----------------------------------------------------------------------------
  364. * look()
  365. *
  366. * Return the raw value of the next token.
  367. * ----------------------------------------------------------------------------- */
  368. static int look(Scanner * s) {
  369. int state;
  370. int c = 0;
  371. state = 0;
  372. Clear(s->text);
  373. s->start_line = s->line;
  374. Setfile(s->text, Getfile(s->str));
  375. while (1) {
  376. switch (state) {
  377. case 0:
  378. if ((c = nextchar(s)) == 0)
  379. return (0);
  380. /* Process delimiters */
  381. if (c == '\n') {
  382. return SWIG_TOKEN_ENDLINE;
  383. } else if (!isspace(c)) {
  384. retract(s, 1);
  385. state = 1000;
  386. Clear(s->text);
  387. Setline(s->text, s->line);
  388. Setfile(s->text, Getfile(s->str));
  389. }
  390. break;
  391. case 1000:
  392. if ((c = nextchar(s)) == 0)
  393. return (0);
  394. if (c == '%')
  395. state = 4; /* Possibly a SWIG directive */
  396. /* Look for possible identifiers */
  397. else if ((isalpha(c)) || (c == '_') ||
  398. (s->idstart && strchr(s->idstart, c)))
  399. state = 7;
  400. /* Look for single character symbols */
  401. else if (c == '(')
  402. return SWIG_TOKEN_LPAREN;
  403. else if (c == ')')
  404. return SWIG_TOKEN_RPAREN;
  405. else if (c == ';')
  406. return SWIG_TOKEN_SEMI;
  407. else if (c == ',')
  408. return SWIG_TOKEN_COMMA;
  409. else if (c == '*')
  410. state = 220;
  411. else if (c == '}')
  412. return SWIG_TOKEN_RBRACE;
  413. else if (c == '{')
  414. return SWIG_TOKEN_LBRACE;
  415. else if (c == '=')
  416. state = 33;
  417. else if (c == '+')
  418. state = 200;
  419. else if (c == '-')
  420. state = 210;
  421. else if (c == '&')
  422. state = 31;
  423. else if (c == '|')
  424. state = 32;
  425. else if (c == '^')
  426. state = 230;
  427. else if (c == '<')
  428. state = 60;
  429. else if (c == '>')
  430. state = 61;
  431. else if (c == '~')
  432. return SWIG_TOKEN_NOT;
  433. else if (c == '!')
  434. state = 3;
  435. else if (c == '\\')
  436. return SWIG_TOKEN_BACKSLASH;
  437. else if (c == '[')
  438. return SWIG_TOKEN_LBRACKET;
  439. else if (c == ']')
  440. return SWIG_TOKEN_RBRACKET;
  441. else if (c == '@')
  442. return SWIG_TOKEN_AT;
  443. else if (c == '$')
  444. state = 75;
  445. else if (c == '#')
  446. return SWIG_TOKEN_POUND;
  447. else if (c == '?')
  448. return SWIG_TOKEN_QUESTION;
  449. /* Look for multi-character sequences */
  450. else if (c == '/') {
  451. state = 1; /* Comment (maybe) */
  452. s->start_line = s->line;
  453. }
  454. else if (c == '\"') {
  455. state = 2; /* Possibly a string */
  456. s->start_line = s->line;
  457. Clear(s->text);
  458. }
  459. else if (c == ':')
  460. state = 5; /* maybe double colon */
  461. else if (c == '0')
  462. state = 83; /* An octal or hex value */
  463. else if (c == '\'') {
  464. s->start_line = s->line;
  465. Clear(s->text);
  466. state = 9; /* A character constant */
  467. } else if (c == '`') {
  468. s->start_line = s->line;
  469. Clear(s->text);
  470. state = 900;
  471. }
  472. else if (c == '.')
  473. state = 100; /* Maybe a number, maybe just a period */
  474. else if (isdigit(c))
  475. state = 8; /* A numerical value */
  476. else
  477. state = 99; /* An error */
  478. break;
  479. case 1: /* Comment block */
  480. if ((c = nextchar(s)) == 0)
  481. return (0);
  482. if (c == '/') {
  483. state = 10; /* C++ style comment */
  484. Clear(s->text);
  485. Setline(s->text, Getline(s->str));
  486. Setfile(s->text, Getfile(s->str));
  487. Append(s->text, "//");
  488. } else if (c == '*') {
  489. state = 11; /* C style comment */
  490. Clear(s->text);
  491. Setline(s->text, Getline(s->str));
  492. Setfile(s->text, Getfile(s->str));
  493. Append(s->text, "/*");
  494. } else if (c == '=') {
  495. return SWIG_TOKEN_DIVEQUAL;
  496. } else {
  497. retract(s, 1);
  498. return SWIG_TOKEN_SLASH;
  499. }
  500. break;
  501. case 10: /* C++ style comment */
  502. if ((c = nextchar(s)) == 0) {
  503. Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
  504. return SWIG_TOKEN_ERROR;
  505. }
  506. if (c == '\n') {
  507. retract(s,1);
  508. return SWIG_TOKEN_COMMENT;
  509. } else {
  510. state = 10;
  511. }
  512. break;
  513. case 11: /* C style comment block */
  514. if ((c = nextchar(s)) == 0) {
  515. Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
  516. return SWIG_TOKEN_ERROR;
  517. }
  518. if (c == '*') {
  519. state = 12;
  520. } else {
  521. state = 11;
  522. }
  523. break;
  524. case 12: /* Still in C style comment */
  525. if ((c = nextchar(s)) == 0) {
  526. Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
  527. return SWIG_TOKEN_ERROR;
  528. }
  529. if (c == '*') {
  530. state = 12;
  531. } else if (c == '/') {
  532. return SWIG_TOKEN_COMMENT;
  533. } else {
  534. state = 11;
  535. }
  536. break;
  537. case 2: /* Processing a string */
  538. if ((c = nextchar(s)) == 0) {
  539. Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
  540. return SWIG_TOKEN_ERROR;
  541. }
  542. if (c == '\"') {
  543. Delitem(s->text, DOH_END);
  544. return SWIG_TOKEN_STRING;
  545. } else if (c == '\\') {
  546. Delitem(s->text, DOH_END);
  547. get_escape(s);
  548. } else
  549. state = 2;
  550. break;
  551. case 3: /* Maybe a not equals */
  552. if ((c = nextchar(s)) == 0)
  553. return SWIG_TOKEN_LNOT;
  554. else if (c == '=')
  555. return SWIG_TOKEN_NOTEQUAL;
  556. else {
  557. retract(s, 1);
  558. return SWIG_TOKEN_LNOT;
  559. }
  560. break;
  561. case 31: /* AND or Logical AND or ANDEQUAL */
  562. if ((c = nextchar(s)) == 0)
  563. return SWIG_TOKEN_AND;
  564. else if (c == '&')
  565. return SWIG_TOKEN_LAND;
  566. else if (c == '=')
  567. return SWIG_TOKEN_ANDEQUAL;
  568. else {
  569. retract(s, 1);
  570. return SWIG_TOKEN_AND;
  571. }
  572. break;
  573. case 32: /* OR or Logical OR */
  574. if ((c = nextchar(s)) == 0)
  575. return SWIG_TOKEN_OR;
  576. else if (c == '|')
  577. return SWIG_TOKEN_LOR;
  578. else if (c == '=')
  579. return SWIG_TOKEN_OREQUAL;
  580. else {
  581. retract(s, 1);
  582. return SWIG_TOKEN_OR;
  583. }
  584. break;
  585. case 33: /* EQUAL or EQUALTO */
  586. if ((c = nextchar(s)) == 0)
  587. return SWIG_TOKEN_EQUAL;
  588. else if (c == '=')
  589. return SWIG_TOKEN_EQUALTO;
  590. else {
  591. retract(s, 1);
  592. return SWIG_TOKEN_EQUAL;
  593. }
  594. break;
  595. case 4: /* A wrapper generator directive (maybe) */
  596. if ((c = nextchar(s)) == 0)
  597. return SWIG_TOKEN_PERCENT;
  598. if (c == '{') {
  599. state = 40; /* Include block */
  600. Clear(s->text);
  601. Setline(s->text, Getline(s->str));
  602. Setfile(s->text, Getfile(s->str));
  603. s->start_line = s->line;
  604. } else if (s->idstart && strchr(s->idstart, '%') &&
  605. ((isalpha(c)) || (c == '_'))) {
  606. state = 7;
  607. } else if (c == '=') {
  608. return SWIG_TOKEN_MODEQUAL;
  609. } else {
  610. retract(s, 1);
  611. return SWIG_TOKEN_PERCENT;
  612. }
  613. break;
  614. case 40: /* Process an include block */
  615. if ((c = nextchar(s)) == 0) {
  616. Swig_error(cparse_file, cparse_start_line, "Unterminated block\n");
  617. return SWIG_TOKEN_ERROR;
  618. }
  619. if (c == '%')
  620. state = 41;
  621. break;
  622. case 41: /* Still processing include block */
  623. if ((c = nextchar(s)) == 0) {
  624. set_error(s,s->start_line,"Unterminated code block");
  625. return 0;
  626. }
  627. if (c == '}') {
  628. Delitem(s->text, DOH_END);
  629. Delitem(s->text, DOH_END);
  630. Seek(s->text,0,SEEK_SET);
  631. return SWIG_TOKEN_CODEBLOCK;
  632. } else {
  633. state = 40;
  634. }
  635. break;
  636. case 5: /* Maybe a double colon */
  637. if ((c = nextchar(s)) == 0)
  638. return SWIG_TOKEN_COLON;
  639. if (c == ':')
  640. state = 50;
  641. else {
  642. retract(s, 1);
  643. return SWIG_TOKEN_COLON;
  644. }
  645. break;
  646. case 50: /* DCOLON, DCOLONSTAR */
  647. if ((c = nextchar(s)) == 0)
  648. return SWIG_TOKEN_DCOLON;
  649. else if (c == '*')
  650. return SWIG_TOKEN_DCOLONSTAR;
  651. else {
  652. retract(s, 1);
  653. return SWIG_TOKEN_DCOLON;
  654. }
  655. break;
  656. case 60: /* shift operators */
  657. if ((c = nextchar(s)) == 0)
  658. return SWIG_TOKEN_LESSTHAN;
  659. if (c == '<')
  660. state = 240;
  661. else if (c == '=')
  662. return SWIG_TOKEN_LTEQUAL;
  663. else {
  664. retract(s, 1);
  665. return SWIG_TOKEN_LESSTHAN;
  666. }
  667. break;
  668. case 61:
  669. if ((c = nextchar(s)) == 0)
  670. return SWIG_TOKEN_GREATERTHAN;
  671. if (c == '>')
  672. state = 250;
  673. else if (c == '=')
  674. return SWIG_TOKEN_GTEQUAL;
  675. else {
  676. retract(s, 1);
  677. return SWIG_TOKEN_GREATERTHAN;
  678. }
  679. break;
  680. case 7: /* Identifier */
  681. if ((c = nextchar(s)) == 0)
  682. state = 71;
  683. else if (isalnum(c) || (c == '_') || (c == '$')) {
  684. state = 7;
  685. } else {
  686. retract(s, 1);
  687. state = 71;
  688. }
  689. break;
  690. case 71: /* Identifier or true/false */
  691. if (cparse_cplusplus) {
  692. if (Strcmp(s->text, "true") == 0)
  693. return SWIG_TOKEN_BOOL;
  694. else if (Strcmp(s->text, "false") == 0)
  695. return SWIG_TOKEN_BOOL;
  696. }
  697. return SWIG_TOKEN_ID;
  698. break;
  699. case 75: /* Special identifier $ */
  700. if ((c = nextchar(s)) == 0)
  701. return SWIG_TOKEN_DOLLAR;
  702. if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
  703. state = 7;
  704. } else {
  705. retract(s,1);
  706. if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR;
  707. state = 71;
  708. }
  709. break;
  710. case 8: /* A numerical digit */
  711. if ((c = nextchar(s)) == 0)
  712. return SWIG_TOKEN_INT;
  713. if (c == '.') {
  714. state = 81;
  715. } else if ((c == 'e') || (c == 'E')) {
  716. state = 82;
  717. } else if ((c == 'f') || (c == 'F')) {
  718. Delitem(s->text, DOH_END);
  719. return SWIG_TOKEN_FLOAT;
  720. } else if (isdigit(c)) {
  721. state = 8;
  722. } else if ((c == 'l') || (c == 'L')) {
  723. state = 87;
  724. } else if ((c == 'u') || (c == 'U')) {
  725. state = 88;
  726. } else {
  727. retract(s, 1);
  728. return SWIG_TOKEN_INT;
  729. }
  730. break;
  731. case 81: /* A floating pointer number of some sort */
  732. if ((c = nextchar(s)) == 0)
  733. return SWIG_TOKEN_DOUBLE;
  734. if (isdigit(c))
  735. state = 81;
  736. else if ((c == 'e') || (c == 'E'))
  737. state = 820;
  738. else if ((c == 'f') || (c == 'F')) {
  739. Delitem(s->text, DOH_END);
  740. return SWIG_TOKEN_FLOAT;
  741. } else if ((c == 'l') || (c == 'L')) {
  742. Delitem(s->text, DOH_END);
  743. return SWIG_TOKEN_DOUBLE;
  744. } else {
  745. retract(s, 1);
  746. return (SWIG_TOKEN_DOUBLE);
  747. }
  748. break;
  749. case 82:
  750. if ((c = nextchar(s)) == 0) {
  751. retract(s, 1);
  752. return SWIG_TOKEN_INT;
  753. }
  754. if ((isdigit(c)) || (c == '-') || (c == '+'))
  755. state = 86;
  756. else {
  757. retract(s, 2);
  758. return (SWIG_TOKEN_INT);
  759. }
  760. break;
  761. case 820:
  762. /* Like case 82, but we've seen a decimal point. */
  763. if ((c = nextchar(s)) == 0) {
  764. retract(s, 1);
  765. return SWIG_TOKEN_DOUBLE;
  766. }
  767. if ((isdigit(c)) || (c == '-') || (c == '+'))
  768. state = 86;
  769. else {
  770. retract(s, 2);
  771. return (SWIG_TOKEN_DOUBLE);
  772. }
  773. break;
  774. case 83:
  775. /* Might be a hexadecimal or octal number */
  776. if ((c = nextchar(s)) == 0)
  777. return SWIG_TOKEN_INT;
  778. if (isdigit(c))
  779. state = 84;
  780. else if ((c == 'x') || (c == 'X'))
  781. state = 85;
  782. else if (c == '.')
  783. state = 81;
  784. else if ((c == 'l') || (c == 'L')) {
  785. state = 87;
  786. } else if ((c == 'u') || (c == 'U')) {
  787. state = 88;
  788. } else {
  789. retract(s, 1);
  790. return SWIG_TOKEN_INT;
  791. }
  792. break;
  793. case 84:
  794. /* This is an octal number */
  795. if ((c = nextchar(s)) == 0)
  796. return SWIG_TOKEN_INT;
  797. if (isdigit(c))
  798. state = 84;
  799. else if ((c == 'l') || (c == 'L')) {
  800. state = 87;
  801. } else if ((c == 'u') || (c == 'U')) {
  802. state = 88;
  803. } else {
  804. retract(s, 1);
  805. return SWIG_TOKEN_INT;
  806. }
  807. break;
  808. case 85:
  809. /* This is an hex number */
  810. if ((c = nextchar(s)) == 0)
  811. return SWIG_TOKEN_INT;
  812. if (isxdigit(c))
  813. state = 85;
  814. else if ((c == 'l') || (c == 'L')) {
  815. state = 87;
  816. } else if ((c == 'u') || (c == 'U')) {
  817. state = 88;
  818. } else {
  819. retract(s, 1);
  820. return SWIG_TOKEN_INT;
  821. }
  822. break;
  823. case 86:
  824. /* Rest of floating point number */
  825. if ((c = nextchar(s)) == 0)
  826. return SWIG_TOKEN_DOUBLE;
  827. if (isdigit(c))
  828. state = 86;
  829. else if ((c == 'f') || (c == 'F')) {
  830. Delitem(s->text, DOH_END);
  831. return SWIG_TOKEN_FLOAT;
  832. } else if ((c == 'l') || (c == 'L')) {
  833. Delitem(s->text, DOH_END);
  834. return SWIG_TOKEN_DOUBLE;
  835. } else {
  836. retract(s, 1);
  837. return SWIG_TOKEN_DOUBLE;
  838. }
  839. break;
  840. case 87:
  841. /* A long integer of some sort */
  842. if ((c = nextchar(s)) == 0)
  843. return SWIG_TOKEN_LONG;
  844. if ((c == 'u') || (c == 'U')) {
  845. return SWIG_TOKEN_ULONG;
  846. } else if ((c == 'l') || (c == 'L')) {
  847. state = 870;
  848. } else {
  849. retract(s, 1);
  850. return SWIG_TOKEN_LONG;
  851. }
  852. break;
  853. /* A long long integer */
  854. case 870:
  855. if ((c = nextchar(s)) == 0)
  856. return SWIG_TOKEN_LONGLONG;
  857. if ((c == 'u') || (c == 'U')) {
  858. return SWIG_TOKEN_ULONGLONG;
  859. } else {
  860. retract(s, 1);
  861. return SWIG_TOKEN_LONGLONG;
  862. }
  863. /* An unsigned number */
  864. case 88:
  865. if ((c = nextchar(s)) == 0)
  866. return SWIG_TOKEN_UINT;
  867. if ((c == 'l') || (c == 'L')) {
  868. state = 880;
  869. } else {
  870. retract(s, 1);
  871. return SWIG_TOKEN_UINT;
  872. }
  873. break;
  874. /* Possibly an unsigned long long or unsigned long */
  875. case 880:
  876. if ((c = nextchar(s)) == 0)
  877. return SWIG_TOKEN_ULONG;
  878. if ((c == 'l') || (c == 'L'))
  879. return SWIG_TOKEN_ULONGLONG;
  880. else {
  881. retract(s, 1);
  882. return SWIG_TOKEN_ULONG;
  883. }
  884. /* A character constant */
  885. case 9:
  886. if ((c = nextchar(s)) == 0) {
  887. Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
  888. return SWIG_TOKEN_ERROR;
  889. }
  890. if (c == '\'') {
  891. Delitem(s->text, DOH_END);
  892. return (SWIG_TOKEN_CHAR);
  893. } else if (c == '\\') {
  894. Delitem(s->text, DOH_END);
  895. get_escape(s);
  896. }
  897. break;
  898. /* A period or maybe a floating point number */
  899. case 100:
  900. if ((c = nextchar(s)) == 0)
  901. return (0);
  902. if (isdigit(c))
  903. state = 81;
  904. else {
  905. retract(s, 1);
  906. return SWIG_TOKEN_PERIOD;
  907. }
  908. break;
  909. case 200: /* PLUS, PLUSPLUS, PLUSEQUAL */
  910. if ((c = nextchar(s)) == 0)
  911. return SWIG_TOKEN_PLUS;
  912. else if (c == '+')
  913. return SWIG_TOKEN_PLUSPLUS;
  914. else if (c == '=')
  915. return SWIG_TOKEN_PLUSEQUAL;
  916. else {
  917. retract(s, 1);
  918. return SWIG_TOKEN_PLUS;
  919. }
  920. break;
  921. case 210: /* MINUS, MINUSMINUS, MINUSEQUAL, ARROW */
  922. if ((c = nextchar(s)) == 0)
  923. return SWIG_TOKEN_MINUS;
  924. else if (c == '-')
  925. return SWIG_TOKEN_MINUSMINUS;
  926. else if (c == '=')
  927. return SWIG_TOKEN_MINUSEQUAL;
  928. else if (c == '>')
  929. state = 211;
  930. else {
  931. retract(s, 1);
  932. return SWIG_TOKEN_MINUS;
  933. }
  934. break;
  935. case 211: /* ARROW, ARROWSTAR */
  936. if ((c = nextchar(s)) == 0)
  937. return SWIG_TOKEN_ARROW;
  938. else if (c == '*')
  939. return SWIG_TOKEN_ARROWSTAR;
  940. else {
  941. retract(s, 1);
  942. return SWIG_TOKEN_ARROW;
  943. }
  944. break;
  945. case 220: /* STAR, TIMESEQUAL */
  946. if ((c = nextchar(s)) == 0)
  947. return SWIG_TOKEN_STAR;
  948. else if (c == '=')
  949. return SWIG_TOKEN_TIMESEQUAL;
  950. else {
  951. retract(s, 1);
  952. return SWIG_TOKEN_STAR;
  953. }
  954. break;
  955. case 230: /* XOR, XOREQUAL */
  956. if ((c = nextchar(s)) == 0)
  957. return SWIG_TOKEN_XOR;
  958. else if (c == '=')
  959. return SWIG_TOKEN_XOREQUAL;
  960. else {
  961. retract(s, 1);
  962. return SWIG_TOKEN_XOR;
  963. }
  964. break;
  965. case 240: /* LSHIFT, LSEQUAL */
  966. if ((c = nextchar(s)) == 0)
  967. return SWIG_TOKEN_LSHIFT;
  968. else if (c == '=')
  969. return SWIG_TOKEN_LSEQUAL;
  970. else {
  971. retract(s, 1);
  972. return SWIG_TOKEN_LSHIFT;
  973. }
  974. break;
  975. case 250: /* RSHIFT, RSEQUAL */
  976. if ((c = nextchar(s)) == 0)
  977. return SWIG_TOKEN_RSHIFT;
  978. else if (c == '=')
  979. return SWIG_TOKEN_RSEQUAL;
  980. else {
  981. retract(s, 1);
  982. return SWIG_TOKEN_RSHIFT;
  983. }
  984. break;
  985. /* An illegal character */
  986. /* Reverse string */
  987. case 900:
  988. if ((c = nextchar(s)) == 0) {
  989. Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
  990. return SWIG_TOKEN_ERROR;
  991. }
  992. if (c == '`') {
  993. Delitem(s->text, DOH_END);
  994. return (SWIG_TOKEN_RSTRING);
  995. }
  996. break;
  997. default:
  998. return SWIG_TOKEN_ILLEGAL;
  999. }
  1000. }
  1001. }
  1002. /* -----------------------------------------------------------------------------
  1003. * Scanner_token()
  1004. *
  1005. * Real entry point to return the next token. Returns 0 if at end of input.
  1006. * ----------------------------------------------------------------------------- */
  1007. int Scanner_token(Scanner * s) {
  1008. int t;
  1009. Delete(s->error);
  1010. if (s->nexttoken >= 0) {
  1011. t = s->nexttoken;
  1012. s->nexttoken = -1;
  1013. return t;
  1014. }
  1015. s->start_line = 0;
  1016. t = look(s);
  1017. if (!s->start_line) {
  1018. Setline(s->text,s->line);
  1019. } else {
  1020. Setline(s->text,s->start_line);
  1021. }
  1022. return t;
  1023. }
  1024. /* -----------------------------------------------------------------------------
  1025. * Scanner_text()
  1026. *
  1027. * Return the lexene associated with the last returned token.
  1028. * ----------------------------------------------------------------------------- */
  1029. String *Scanner_text(Scanner * s) {
  1030. return s->text;
  1031. }
  1032. /* -----------------------------------------------------------------------------
  1033. * Scanner_skip_line()
  1034. *
  1035. * Skips to the end of a line
  1036. * ----------------------------------------------------------------------------- */
  1037. void Scanner_skip_line(Scanner * s) {
  1038. char c;
  1039. int done = 0;
  1040. Clear(s->text);
  1041. Setfile(s->text, Getfile(s->str));
  1042. Setline(s->text, s->line);
  1043. while (!done) {
  1044. if ((c = nextchar(s)) == 0)
  1045. return;
  1046. if (c == '\\') {
  1047. c = nextchar(s);
  1048. } else if (c == '\n') {
  1049. done = 1;
  1050. }
  1051. }
  1052. return;
  1053. }
  1054. /* -----------------------------------------------------------------------------
  1055. * Scanner_skip_balanced()
  1056. *
  1057. * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
  1058. * (...). Ignores symbols inside comments or strings.
  1059. * ----------------------------------------------------------------------------- */
  1060. int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
  1061. char c;
  1062. int num_levels = 1;
  1063. int state = 0;
  1064. char temp[2] = { 0, 0 };
  1065. String *locator = 0;
  1066. temp[0] = (char) startchar;
  1067. Clear(s->text);
  1068. Setfile(s->text, Getfile(s->str));
  1069. Setline(s->text, s->line);
  1070. Append(s->text, temp);
  1071. while (num_levels > 0) {
  1072. if ((c = nextchar(s)) == 0) {
  1073. Delete(locator);
  1074. return -1;
  1075. }
  1076. switch (state) {
  1077. case 0:
  1078. if (c == startchar)
  1079. num_levels++;
  1080. else if (c == endchar)
  1081. num_levels--;
  1082. else if (c == '/')
  1083. state = 10;
  1084. else if (c == '\"')
  1085. state = 20;
  1086. else if (c == '\'')
  1087. state = 30;
  1088. break;
  1089. case 10:
  1090. if (c == '/')
  1091. state = 11;
  1092. else if (c == '*')
  1093. state = 12;
  1094. else if (c == startchar) {
  1095. state = 0;
  1096. num_levels++;
  1097. }
  1098. else
  1099. state = 0;
  1100. break;
  1101. case 11:
  1102. if (c == '\n')
  1103. state = 0;
  1104. else
  1105. state = 11;
  1106. break;
  1107. case 12: /* first character inside C comment */
  1108. if (c == '*')
  1109. state = 14;
  1110. else if (c == '@')
  1111. state = 40;
  1112. else
  1113. state = 13;
  1114. break;
  1115. case 13:
  1116. if (c == '*')
  1117. state = 14;
  1118. break;
  1119. case 14: /* possible end of C comment */
  1120. if (c == '*')
  1121. state = 14;
  1122. else if (c == '/')
  1123. state = 0;
  1124. else
  1125. state = 13;
  1126. break;
  1127. case 20:
  1128. if (c == '\"')
  1129. state = 0;
  1130. else if (c == '\\')
  1131. state = 21;
  1132. break;
  1133. case 21:
  1134. state = 20;
  1135. break;
  1136. case 30:
  1137. if (c == '\'')
  1138. state = 0;
  1139. else if (c == '\\')
  1140. state = 31;
  1141. break;
  1142. case 31:
  1143. state = 30;
  1144. break;
  1145. /* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */
  1146. case 40:
  1147. state = (c == 'S') ? 41 : (c == '*') ? 14 : 13;
  1148. break;
  1149. case 41:
  1150. state = (c == 'W') ? 42 : (c == '*') ? 14 : 13;
  1151. break;
  1152. case 42:
  1153. state = (c == 'I') ? 43 : (c == '*') ? 14 : 13;
  1154. break;
  1155. case 43:
  1156. state = (c == 'G') ? 44 : (c == '*') ? 14 : 13;
  1157. if (c == 'G') {
  1158. Delete(locator);
  1159. locator = NewString("/*@SWIG");
  1160. }
  1161. break;
  1162. case 44:
  1163. if (c == '*')
  1164. state = 45;
  1165. Putc(c, locator);
  1166. break;
  1167. case 45: /* end of SWIG locator in C comment */
  1168. if (c == '/') {
  1169. state = 0;
  1170. Putc(c, locator);
  1171. Scanner_locator(s, locator);
  1172. } else {
  1173. /* malformed locator */
  1174. state = (c == '*') ? 14 : 13;
  1175. }
  1176. break;
  1177. default:
  1178. break;
  1179. }
  1180. }
  1181. Delete(locator);
  1182. return 0;
  1183. }
  1184. /* -----------------------------------------------------------------------------
  1185. * Scanner_isoperator()
  1186. *
  1187. * Returns 0 or 1 depending on whether or not a token corresponds to a C/C++
  1188. * operator.
  1189. * ----------------------------------------------------------------------------- */
  1190. int Scanner_isoperator(int tokval) {
  1191. if (tokval >= 100) return 1;
  1192. return 0;
  1193. }
  1194. /* ----------------------------------------------------------------------
  1195. * locator()
  1196. *
  1197. * Support for locator strings. These are strings of the form
  1198. * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
  1199. * are primarily used for macro line number reporting.
  1200. * We just use the locator to mark when to activate/deactivate linecounting.
  1201. * ---------------------------------------------------------------------- */
  1202. void Scanner_locator(Scanner *s, String *loc) {
  1203. static Locator *locs = 0;
  1204. static int expanding_macro = 0;
  1205. if (!follow_locators) {
  1206. if (Equal(loc, "/*@SWIG@*/")) {
  1207. /* End locator. */
  1208. if (expanding_macro)
  1209. --expanding_macro;
  1210. } else {
  1211. /* Begin locator. */
  1212. ++expanding_macro;
  1213. }
  1214. /* Freeze line number processing in Scanner */
  1215. freeze_line(s,expanding_macro);
  1216. } else {
  1217. int c;
  1218. Locator *l;
  1219. Seek(loc, 7, SEEK_SET);
  1220. c = Getc(loc);
  1221. if (c == '@') {
  1222. /* Empty locator. We pop the last location off */
  1223. if (locs) {
  1224. Scanner_set_location(s, locs->filename, locs->line_number);
  1225. cparse_file = locs->filename;
  1226. cparse_line = locs->line_number;
  1227. l = locs->next;
  1228. free(locs);
  1229. locs = l;
  1230. }
  1231. return;
  1232. }
  1233. /* We're going to push a new location */
  1234. l = (Locator *) malloc(sizeof(Locator));
  1235. l->filename = cparse_file;
  1236. l->line_number = cparse_line;
  1237. l->next = locs;
  1238. locs = l;
  1239. /* Now, parse the new location out of the locator string */
  1240. {
  1241. String *fn = NewStringEmpty();
  1242. /* Putc(c, fn); */
  1243. while ((c = Getc(loc)) != EOF) {
  1244. if ((c == '@') || (c == ','))
  1245. break;
  1246. Putc(c, fn);
  1247. }
  1248. cparse_file = Swig_copy_string(Char(fn));
  1249. Clear(fn);
  1250. cparse_line = 1;
  1251. /* Get the line number */
  1252. while ((c = Getc(loc)) != EOF) {
  1253. if ((c == '@') || (c == ','))
  1254. break;
  1255. Putc(c, fn);
  1256. }
  1257. cparse_line = atoi(Char(fn));
  1258. Clear(fn);
  1259. /* Get the rest of it */
  1260. while ((c = Getc(loc)) != EOF) {
  1261. if (c == '@')
  1262. break;
  1263. Putc(c, fn);
  1264. }
  1265. /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
  1266. Scanner_set_location(s, cparse_file, cparse_line);
  1267. Delete(fn);
  1268. }
  1269. }
  1270. }
  1271. void Swig_cparse_follow_locators(int v) {
  1272. follow_locators = v;
  1273. }