PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Swig/scanner.c

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