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
17 #include "swig.h"
18 #include <ctype.h>
19
20 extern String *cparse_file;
21 extern int cparse_line;
22 extern int cparse_cplusplus;
23 extern int cparse_start_line;
24
25 struct Scanner {
26 String *text; /* Current token value */
27 List *scanobjs; /* Objects being scanned */
28 String *str; /* Current object being scanned */
29 char *idstart; /* Optional identifier start characters */
30 int nexttoken; /* Next token to be returned */
31 int start_line; /* Starting line of certain declarations */
32 int line;
33 int yylen; /* Length of text pushed into text */
34 String *file;
35 String *error; /* Last error message (if any) */
36 int error_line; /* Error line number */
37 int freeze_line; /* Suspend line number updates */
38 List *brackets; /* Current level of < > brackets on each level */
39 };
40
41 typedef struct Locator {
42 String *filename;
43 int line_number;
44 struct Locator *next;
45 } Locator;
46 static int follow_locators = 0;
47
48 static void brackets_push(Scanner *);
49 static void brackets_clear(Scanner *);
50
51 /* -----------------------------------------------------------------------------
52 * NewScanner()
53 *
54 * Create a new scanner object
55 * ----------------------------------------------------------------------------- */
56
NewScanner(void)57 Scanner *NewScanner(void) {
58 Scanner *s;
59 s = (Scanner *) malloc(sizeof(Scanner));
60 s->line = 1;
61 s->file = 0;
62 s->nexttoken = -1;
63 s->start_line = 1;
64 s->yylen = 0;
65 s->idstart = NULL;
66 s->scanobjs = NewList();
67 s->text = NewStringEmpty();
68 s->str = 0;
69 s->error = 0;
70 s->error_line = 0;
71 s->freeze_line = 0;
72 s->brackets = NewList();
73 brackets_push(s);
74 return s;
75 }
76
77 /* -----------------------------------------------------------------------------
78 * DelScanner()
79 *
80 * Delete a scanner object.
81 * ----------------------------------------------------------------------------- */
82
DelScanner(Scanner * s)83 void DelScanner(Scanner *s) {
84 assert(s);
85 Delete(s->scanobjs);
86 Delete(s->brackets);
87 Delete(s->text);
88 Delete(s->file);
89 Delete(s->error);
90 Delete(s->str);
91 free(s->idstart);
92 free(s);
93 }
94
95 /* -----------------------------------------------------------------------------
96 * Scanner_clear()
97 *
98 * Clear the contents of a scanner object.
99 * ----------------------------------------------------------------------------- */
100
Scanner_clear(Scanner * s)101 void Scanner_clear(Scanner *s) {
102 assert(s);
103 Delete(s->str);
104 Clear(s->text);
105 Clear(s->scanobjs);
106 brackets_clear(s);
107 Delete(s->error);
108 s->str = 0;
109 s->error = 0;
110 s->line = 1;
111 s->nexttoken = -1;
112 s->start_line = 0;
113 s->yylen = 0;
114 /* Should these be cleared too?
115 s->idstart;
116 s->file;
117 s->error_line;
118 s->freeze_line;
119 */
120 }
121
122 /* -----------------------------------------------------------------------------
123 * Scanner_push()
124 *
125 * Push some new text into the scanner. The scanner will start parsing this text
126 * immediately before returning to the old text.
127 * ----------------------------------------------------------------------------- */
128
Scanner_push(Scanner * s,String * txt)129 void Scanner_push(Scanner *s, String *txt) {
130 assert(s && txt);
131 Push(s->scanobjs, txt);
132 if (s->str) {
133 Setline(s->str,s->line);
134 Delete(s->str);
135 }
136 s->str = txt;
137 DohIncref(s->str);
138 s->line = Getline(txt);
139 }
140
141 /* -----------------------------------------------------------------------------
142 * Scanner_pushtoken()
143 *
144 * Push a token into the scanner. This token will be returned on the next
145 * call to Scanner_token().
146 * ----------------------------------------------------------------------------- */
147
Scanner_pushtoken(Scanner * s,int nt,const_String_or_char_ptr val)148 void Scanner_pushtoken(Scanner *s, int nt, const_String_or_char_ptr val) {
149 assert(s);
150 assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
151 s->nexttoken = nt;
152 if ( Char(val) != Char(s->text) ) {
153 Clear(s->text);
154 Append(s->text,val);
155 }
156 }
157
158 /* -----------------------------------------------------------------------------
159 * Scanner_set_location()
160 *
161 * Set the file and line number location of the scanner.
162 * ----------------------------------------------------------------------------- */
163
Scanner_set_location(Scanner * s,String * file,int line)164 void Scanner_set_location(Scanner *s, String *file, int line) {
165 Setline(s->str, line);
166 Setfile(s->str, file);
167 s->line = line;
168 }
169
170 /* -----------------------------------------------------------------------------
171 * Scanner_file()
172 *
173 * Get the current file.
174 * ----------------------------------------------------------------------------- */
175
Scanner_file(Scanner * s)176 String *Scanner_file(Scanner *s) {
177 return Getfile(s->str);
178 }
179
180 /* -----------------------------------------------------------------------------
181 * Scanner_line()
182 *
183 * Get the current line number
184 * ----------------------------------------------------------------------------- */
Scanner_line(Scanner * s)185 int Scanner_line(Scanner *s) {
186 return s->line;
187 }
188
189 /* -----------------------------------------------------------------------------
190 * Scanner_start_line()
191 *
192 * Get the line number on which the current token starts
193 * ----------------------------------------------------------------------------- */
Scanner_start_line(Scanner * s)194 int Scanner_start_line(Scanner *s) {
195 return s->start_line;
196 }
197
198 /* -----------------------------------------------------------------------------
199 * Scanner_idstart()
200 *
201 * Change the set of additional characters that can be used to start an identifier.
202 * ----------------------------------------------------------------------------- */
203
Scanner_idstart(Scanner * s,const char * id)204 void Scanner_idstart(Scanner *s, const char *id) {
205 free(s->idstart);
206 s->idstart = Swig_copy_string(id);
207 }
208
209 /* -----------------------------------------------------------------------------
210 * nextchar()
211 *
212 * Returns the next character from the scanner or 0 if end of the string.
213 * ----------------------------------------------------------------------------- */
nextchar(Scanner * s)214 static char nextchar(Scanner *s) {
215 int nc;
216 if (!s->str)
217 return 0;
218 while ((nc = Getc(s->str)) == EOF) {
219 Delete(s->str);
220 s->str = 0;
221 Delitem(s->scanobjs, 0);
222 if (Len(s->scanobjs) == 0)
223 return 0;
224 s->str = Getitem(s->scanobjs, 0);
225 s->line = Getline(s->str);
226 DohIncref(s->str);
227 }
228 if ((nc == '\n') && (!s->freeze_line))
229 s->line++;
230 Putc(nc,s->text);
231 return (char)nc;
232 }
233
234 /* -----------------------------------------------------------------------------
235 * set_error()
236 *
237 * Sets error information on the scanner.
238 * ----------------------------------------------------------------------------- */
239
set_error(Scanner * s,int line,const_String_or_char_ptr msg)240 static void set_error(Scanner *s, int line, const_String_or_char_ptr msg) {
241 s->error_line = line;
242 s->error = NewString(msg);
243 }
244
245 /* -----------------------------------------------------------------------------
246 * Scanner_errmsg()
247 * Scanner_errline()
248 *
249 * Returns error information (if any)
250 * ----------------------------------------------------------------------------- */
251
Scanner_errmsg(Scanner * s)252 String *Scanner_errmsg(Scanner *s) {
253 return s->error;
254 }
255
Scanner_errline(Scanner * s)256 int Scanner_errline(Scanner *s) {
257 return s->error_line;
258 }
259
260 /* -----------------------------------------------------------------------------
261 * freeze_line()
262 *
263 * Freezes the current line number.
264 * ----------------------------------------------------------------------------- */
265
freeze_line(Scanner * s,int val)266 static void freeze_line(Scanner *s, int val) {
267 s->freeze_line = val;
268 }
269
270 /* -----------------------------------------------------------------------------
271 * brackets_count()
272 *
273 * Returns the number of brackets at the current depth.
274 * A syntax error with unbalanced ) brackets will result in a NULL pointer return.
275 * ----------------------------------------------------------------------------- */
brackets_count(Scanner * s)276 static int *brackets_count(Scanner *s) {
277 int *count;
278 if (Len(s->brackets) > 0)
279 count = (int *)Data(Getitem(s->brackets, 0));
280 else
281 count = 0;
282 return count;
283 }
284
285 /* -----------------------------------------------------------------------------
286 * brackets_clear()
287 *
288 * Resets the current depth and clears all brackets.
289 * Usually called at the end of statements;
290 * ----------------------------------------------------------------------------- */
brackets_clear(Scanner * s)291 static void brackets_clear(Scanner *s) {
292 Clear(s->brackets);
293 brackets_push(s); /* base bracket count should always be created */
294 }
295
296 /* -----------------------------------------------------------------------------
297 * brackets_increment()
298 *
299 * Increases the number of brackets at the current depth.
300 * Usually called when a single '<' is found.
301 * ----------------------------------------------------------------------------- */
brackets_increment(Scanner * s)302 static void brackets_increment(Scanner *s) {
303 int *count = brackets_count(s);
304 if (count)
305 (*count)++;
306 }
307
308 /* -----------------------------------------------------------------------------
309 * brackets_decrement()
310 *
311 * Decreases the number of brackets at the current depth.
312 * Usually called when a single '>' is found.
313 * ----------------------------------------------------------------------------- */
brackets_decrement(Scanner * s)314 static void brackets_decrement(Scanner *s) {
315 int *count = brackets_count(s);
316 if (count)
317 (*count)--;
318 }
319
320 /* -----------------------------------------------------------------------------
321 * brackets_reset()
322 *
323 * Sets the number of '<' brackets back to zero. Called at the point where
324 * it is no longer possible to have a matching closing >> pair for a template.
325 * ----------------------------------------------------------------------------- */
brackets_reset(Scanner * s)326 static void brackets_reset(Scanner *s) {
327 int *count = brackets_count(s);
328 if (count)
329 *count = 0;
330 }
331
332 /* -----------------------------------------------------------------------------
333 * brackets_push()
334 *
335 * Increases the depth of brackets.
336 * Usually called when '(' is found.
337 * ----------------------------------------------------------------------------- */
brackets_push(Scanner * s)338 static void brackets_push(Scanner *s) {
339 int *newInt = (int *)malloc(sizeof(int));
340 *newInt = 0;
341 Push(s->brackets, NewVoid(newInt, free));
342 }
343
344 /* -----------------------------------------------------------------------------
345 * brackets_pop()
346 *
347 * Decreases the depth of brackets.
348 * Usually called when ')' is found.
349 * ----------------------------------------------------------------------------- */
brackets_pop(Scanner * s)350 static void brackets_pop(Scanner *s) {
351 if (Len(s->brackets) > 0) /* protect against unbalanced ')' brackets */
352 Delitem(s->brackets, 0);
353 }
354
355 /* -----------------------------------------------------------------------------
356 * brackets_allow_shift()
357 *
358 * Return 1 to allow shift (>>), or 0 if (>>) should be split into (> >).
359 * This is for C++11 template syntax for closing templates.
360 * ----------------------------------------------------------------------------- */
brackets_allow_shift(Scanner * s)361 static int brackets_allow_shift(Scanner *s) {
362 int *count = brackets_count(s);
363 return !count || (*count <= 0);
364 }
365
366 /* -----------------------------------------------------------------------------
367 * retract()
368 *
369 * Retract n characters
370 * ----------------------------------------------------------------------------- */
retract(Scanner * s,int n)371 static void retract(Scanner *s, int n) {
372 int i, l;
373 char *str;
374
375 str = Char(s->text);
376 l = Len(s->text);
377 assert(n <= l);
378 for (i = 0; i < n; i++) {
379 if (str[l - 1] == '\n') {
380 if (!s->freeze_line) s->line--;
381 }
382 (void)Seek(s->str, -1, SEEK_CUR);
383 Delitem(s->text, DOH_END);
384 }
385 }
386
387 /* -----------------------------------------------------------------------------
388 * get_escape()
389 *
390 * Get escape sequence. Called when a backslash is found in a string
391 * ----------------------------------------------------------------------------- */
392
get_escape(Scanner * s)393 static void get_escape(Scanner *s) {
394 int result = 0;
395 int state = 0;
396 int c;
397
398 while (1) {
399 c = nextchar(s);
400 if (c == 0)
401 break;
402 switch (state) {
403 case 0:
404 if (c == 'n') {
405 Delitem(s->text, DOH_END);
406 Append(s->text,"\n");
407 return;
408 }
409 if (c == 'r') {
410 Delitem(s->text, DOH_END);
411 Append(s->text,"\r");
412 return;
413 }
414 if (c == 't') {
415 Delitem(s->text, DOH_END);
416 Append(s->text,"\t");
417 return;
418 }
419 if (c == 'a') {
420 Delitem(s->text, DOH_END);
421 Append(s->text,"\a");
422 return;
423 }
424 if (c == 'b') {
425 Delitem(s->text, DOH_END);
426 Append(s->text,"\b");
427 return;
428 }
429 if (c == 'f') {
430 Delitem(s->text, DOH_END);
431 Append(s->text,"\f");
432 return;
433 }
434 if (c == '\\') {
435 Delitem(s->text, DOH_END);
436 Append(s->text,"\\");
437 return;
438 }
439 if (c == 'v') {
440 Delitem(s->text, DOH_END);
441 Append(s->text,"\v");
442 return;
443 }
444 if (c == 'e') {
445 Delitem(s->text, DOH_END);
446 Append(s->text,"\033");
447 return;
448 }
449 if (c == '\'') {
450 Delitem(s->text, DOH_END);
451 Append(s->text,"\'");
452 return;
453 }
454 if (c == '\"') {
455 Delitem(s->text, DOH_END);
456 Append(s->text,"\"");
457 return;
458 }
459 if (c == '\n') {
460 Delitem(s->text, DOH_END);
461 return;
462 }
463 if (isdigit(c)) {
464 state = 10;
465 result = (c - '0');
466 Delitem(s->text, DOH_END);
467 } else if (c == 'x') {
468 state = 20;
469 Delitem(s->text, DOH_END);
470 } else {
471 char tmp[3];
472 tmp[0] = '\\';
473 tmp[1] = (char)c;
474 tmp[2] = 0;
475 Delitem(s->text, DOH_END);
476 Append(s->text, tmp);
477 return;
478 }
479 break;
480 case 10:
481 if (!isdigit(c)) {
482 retract(s,1);
483 Putc((char)result,s->text);
484 return;
485 }
486 result = (result << 3) + (c - '0');
487 Delitem(s->text, DOH_END);
488 break;
489 case 20:
490 if (!isxdigit(c)) {
491 retract(s,1);
492 Putc((char)result, s->text);
493 return;
494 }
495 if (isdigit(c))
496 result = (result << 4) + (c - '0');
497 else
498 result = (result << 4) + (10 + tolower(c) - 'a');
499 Delitem(s->text, DOH_END);
500 break;
501 }
502 }
503 return;
504 }
505
506 /* -----------------------------------------------------------------------------
507 * look()
508 *
509 * Return the raw value of the next token.
510 * ----------------------------------------------------------------------------- */
511
look(Scanner * s)512 static int look(Scanner *s) {
513 int state = 0;
514 int c = 0;
515 String *str_delimiter = 0;
516
517 Clear(s->text);
518 s->start_line = s->line;
519 Setfile(s->text, Getfile(s->str));
520
521
522 while (1) {
523 switch (state) {
524 case 0:
525 if ((c = nextchar(s)) == 0)
526 return (0);
527
528 /* Process delimiters */
529
530 if (c == '\n') {
531 return SWIG_TOKEN_ENDLINE;
532 } else if (!isspace(c)) {
533 retract(s, 1);
534 state = 1000;
535 Clear(s->text);
536 Setline(s->text, s->line);
537 Setfile(s->text, Getfile(s->str));
538 }
539 break;
540
541 case 1000:
542 if ((c = nextchar(s)) == 0)
543 return (0);
544 if (c == '%')
545 state = 4; /* Possibly a SWIG directive */
546
547 /* Look for possible identifiers or unicode/delimiter strings */
548 else if ((isalpha(c)) || (c == '_') ||
549 (s->idstart && strchr(s->idstart, c))) {
550 state = 7;
551 }
552
553 /* Look for single character symbols */
554
555 else if (c == '(') {
556 brackets_push(s);
557 return SWIG_TOKEN_LPAREN;
558 }
559 else if (c == ')') {
560 brackets_pop(s);
561 return SWIG_TOKEN_RPAREN;
562 }
563 else if (c == ';') {
564 brackets_clear(s);
565 return SWIG_TOKEN_SEMI;
566 }
567 else if (c == ',')
568 return SWIG_TOKEN_COMMA;
569 else if (c == '*')
570 state = 220;
571 else if (c == '}')
572 return SWIG_TOKEN_RBRACE;
573 else if (c == '{') {
574 brackets_reset(s);
575 return SWIG_TOKEN_LBRACE;
576 }
577 else if (c == '=')
578 state = 33;
579 else if (c == '+')
580 state = 200;
581 else if (c == '-')
582 state = 210;
583 else if (c == '&')
584 state = 31;
585 else if (c == '|')
586 state = 32;
587 else if (c == '^')
588 state = 230;
589 else if (c == '<')
590 state = 60;
591 else if (c == '>')
592 state = 61;
593 else if (c == '~')
594 return SWIG_TOKEN_NOT;
595 else if (c == '!')
596 state = 3;
597 else if (c == '\\')
598 return SWIG_TOKEN_BACKSLASH;
599 else if (c == '[')
600 return SWIG_TOKEN_LBRACKET;
601 else if (c == ']')
602 return SWIG_TOKEN_RBRACKET;
603 else if (c == '@')
604 return SWIG_TOKEN_AT;
605 else if (c == '$')
606 state = 75;
607 else if (c == '#')
608 return SWIG_TOKEN_POUND;
609 else if (c == '?')
610 return SWIG_TOKEN_QUESTION;
611
612 /* Look for multi-character sequences */
613
614 else if (c == '/') {
615 state = 1; /* Comment (maybe) */
616 s->start_line = s->line;
617 }
618
619 else if (c == ':')
620 state = 5; /* maybe double colon */
621 else if (c == '0')
622 state = 83; /* An octal or hex value */
623 else if (c == '\"') {
624 state = 2; /* A string constant */
625 s->start_line = s->line;
626 Clear(s->text);
627 }
628 else if (c == '\'') {
629 s->start_line = s->line;
630 Clear(s->text);
631 state = 9; /* A character constant */
632 } else if (c == '`') {
633 s->start_line = s->line;
634 Clear(s->text);
635 state = 900;
636 }
637
638 else if (c == '.')
639 state = 100; /* Maybe a number, maybe just a period */
640 else if (isdigit(c))
641 state = 8; /* A numerical value */
642 else
643 state = 99; /* An error */
644 break;
645
646 case 1: /* Comment block */
647 if ((c = nextchar(s)) == 0)
648 return (0);
649 if (c == '/') {
650 state = 10; /* C++ style comment */
651 Clear(s->text);
652 Setline(s->text, Getline(s->str));
653 Setfile(s->text, Getfile(s->str));
654 Append(s->text, "//");
655 } else if (c == '*') {
656 state = 11; /* C style comment */
657 Clear(s->text);
658 Setline(s->text, Getline(s->str));
659 Setfile(s->text, Getfile(s->str));
660 Append(s->text, "/*");
661 } else if (c == '=') {
662 return SWIG_TOKEN_DIVEQUAL;
663 } else {
664 retract(s, 1);
665 return SWIG_TOKEN_SLASH;
666 }
667 break;
668 case 10: /* C++ style comment */
669 if ((c = nextchar(s)) == 0) {
670 Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
671 return SWIG_TOKEN_ERROR;
672 }
673 if (c == '\n') {
674 retract(s,1);
675 return SWIG_TOKEN_COMMENT;
676 } else {
677 state = 10;
678 }
679 break;
680 case 11: /* C style comment block */
681 if ((c = nextchar(s)) == 0) {
682 Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
683 return SWIG_TOKEN_ERROR;
684 }
685 if (c == '*') {
686 state = 12;
687 } else {
688 state = 11;
689 }
690 break;
691 case 12: /* Still in C style comment */
692 if ((c = nextchar(s)) == 0) {
693 Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
694 return SWIG_TOKEN_ERROR;
695 }
696 if (c == '*') {
697 state = 12;
698 } else if (c == '/') {
699 return SWIG_TOKEN_COMMENT;
700 } else {
701 state = 11;
702 }
703 break;
704
705 case 2: /* Processing a string */
706 if (!str_delimiter) {
707 state=20;
708 break;
709 }
710
711 if ((c = nextchar(s)) == 0) {
712 Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
713 return SWIG_TOKEN_ERROR;
714 }
715 else if (c == '(') {
716 state = 20;
717 }
718 else {
719 char temp[2] = { 0, 0 };
720 temp[0] = c;
721 Append( str_delimiter, temp );
722 }
723
724 break;
725
726 case 20: /* Inside the string */
727 if ((c = nextchar(s)) == 0) {
728 Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
729 return SWIG_TOKEN_ERROR;
730 }
731
732 if (!str_delimiter) { /* Ordinary string: "value" */
733 if (c == '\"') {
734 Delitem(s->text, DOH_END);
735 return SWIG_TOKEN_STRING;
736 } else if (c == '\\') {
737 Delitem(s->text, DOH_END);
738 get_escape(s);
739 }
740 } else { /* Custom delimiter string: R"XXXX(value)XXXX" */
741 if (c==')') {
742 int i=0;
743 String *end_delimiter = NewStringEmpty();
744 while ((c = nextchar(s)) != 0 && c!='\"') {
745 char temp[2] = { 0, 0 };
746 temp[0] = c;
747 Append( end_delimiter, temp );
748 i++;
749 }
750
751 if (Strcmp( str_delimiter, end_delimiter )==0) {
752 int len = Len(s->text);
753 Delslice(s->text, len - 2 - Len(str_delimiter), len); /* Delete ending )XXXX" */
754 Delslice(s->text, 0, Len(str_delimiter) + 1); /* Delete starting XXXX( */
755 Delete( end_delimiter ); /* Correct end delimiter )XXXX" occurred */
756 Delete( str_delimiter );
757 str_delimiter = 0;
758 return SWIG_TOKEN_STRING;
759 } else { /* Incorrect end delimiter occurred */
760 if (c == 0) {
761 Swig_error(cparse_file, cparse_start_line, "Unterminated raw string, started with R\"%s( is not terminated by )%s\"\n", str_delimiter, str_delimiter);
762 return SWIG_TOKEN_ERROR;
763 }
764 retract( s, i );
765 Delete( end_delimiter );
766 }
767 }
768 }
769
770 break;
771
772 case 3: /* Maybe a not equals */
773 if ((c = nextchar(s)) == 0)
774 return SWIG_TOKEN_LNOT;
775 else if (c == '=')
776 return SWIG_TOKEN_NOTEQUAL;
777 else {
778 retract(s, 1);
779 return SWIG_TOKEN_LNOT;
780 }
781 break;
782
783 case 31: /* AND or Logical AND or ANDEQUAL */
784 if ((c = nextchar(s)) == 0)
785 return SWIG_TOKEN_AND;
786 else if (c == '&')
787 return SWIG_TOKEN_LAND;
788 else if (c == '=')
789 return SWIG_TOKEN_ANDEQUAL;
790 else {
791 retract(s, 1);
792 return SWIG_TOKEN_AND;
793 }
794 break;
795
796 case 32: /* OR or Logical OR */
797 if ((c = nextchar(s)) == 0)
798 return SWIG_TOKEN_OR;
799 else if (c == '|')
800 return SWIG_TOKEN_LOR;
801 else if (c == '=')
802 return SWIG_TOKEN_OREQUAL;
803 else {
804 retract(s, 1);
805 return SWIG_TOKEN_OR;
806 }
807 break;
808
809 case 33: /* EQUAL or EQUALTO */
810 if ((c = nextchar(s)) == 0)
811 return SWIG_TOKEN_EQUAL;
812 else if (c == '=')
813 return SWIG_TOKEN_EQUALTO;
814 else {
815 retract(s, 1);
816 return SWIG_TOKEN_EQUAL;
817 }
818 break;
819
820 case 4: /* A wrapper generator directive (maybe) */
821 if ((c = nextchar(s)) == 0)
822 return SWIG_TOKEN_PERCENT;
823 if (c == '{') {
824 state = 40; /* Include block */
825 Clear(s->text);
826 Setline(s->text, Getline(s->str));
827 Setfile(s->text, Getfile(s->str));
828 s->start_line = s->line;
829 } else if (s->idstart && strchr(s->idstart, '%') &&
830 ((isalpha(c)) || (c == '_'))) {
831 state = 7;
832 } else if (c == '=') {
833 return SWIG_TOKEN_MODEQUAL;
834 } else if (c == '}') {
835 Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '%%}'\n");
836 SWIG_exit(EXIT_FAILURE);
837 } else {
838 retract(s, 1);
839 return SWIG_TOKEN_PERCENT;
840 }
841 break;
842
843 case 40: /* Process an include block */
844 if ((c = nextchar(s)) == 0) {
845 Swig_error(cparse_file, cparse_start_line, "Unterminated block\n");
846 return SWIG_TOKEN_ERROR;
847 }
848 if (c == '%')
849 state = 41;
850 break;
851 case 41: /* Still processing include block */
852 if ((c = nextchar(s)) == 0) {
853 set_error(s,s->start_line,"Unterminated code block");
854 return 0;
855 }
856 if (c == '}') {
857 Delitem(s->text, DOH_END);
858 Delitem(s->text, DOH_END);
859 Seek(s->text,0,SEEK_SET);
860 return SWIG_TOKEN_CODEBLOCK;
861 } else {
862 state = 40;
863 }
864 break;
865
866 case 5: /* Maybe a double colon */
867
868 if ((c = nextchar(s)) == 0)
869 return SWIG_TOKEN_COLON;
870 if (c == ':')
871 state = 50;
872 else {
873 retract(s, 1);
874 return SWIG_TOKEN_COLON;
875 }
876 break;
877
878 case 50: /* DCOLON, DCOLONSTAR */
879 if ((c = nextchar(s)) == 0)
880 return SWIG_TOKEN_DCOLON;
881 else if (c == '*')
882 return SWIG_TOKEN_DCOLONSTAR;
883 else {
884 retract(s, 1);
885 return SWIG_TOKEN_DCOLON;
886 }
887 break;
888
889 case 60: /* shift operators */
890 if ((c = nextchar(s)) == 0) {
891 brackets_increment(s);
892 return SWIG_TOKEN_LESSTHAN;
893 }
894 if (c == '<')
895 state = 240;
896 else if (c == '=')
897 return SWIG_TOKEN_LTEQUAL;
898 else {
899 retract(s, 1);
900 brackets_increment(s);
901 return SWIG_TOKEN_LESSTHAN;
902 }
903 break;
904 case 61:
905 if ((c = nextchar(s)) == 0) {
906 brackets_decrement(s);
907 return SWIG_TOKEN_GREATERTHAN;
908 }
909 if (c == '>' && brackets_allow_shift(s))
910 state = 250;
911 else if (c == '=')
912 return SWIG_TOKEN_GTEQUAL;
913 else {
914 retract(s, 1);
915 brackets_decrement(s);
916 return SWIG_TOKEN_GREATERTHAN;
917 }
918 break;
919
920 case 7: /* Identifier or true/false or unicode/custom delimiter string */
921 if (c == 'R') { /* Possibly CUSTOM DELIMITER string */
922 state = 72;
923 break;
924 }
925 else if (c == 'L') { /* Probably identifier but may be a wide string literal */
926 state = 77;
927 break;
928 }
929 else if (c != 'u' && c != 'U') { /* Definitely an identifier */
930 state = 70;
931 break;
932 }
933
934 if ((c = nextchar(s)) == 0) {
935 state = 76;
936 }
937 else if (c == '\"') { /* Definitely u, U or L string */
938 retract(s, 1);
939 state = 1000;
940 }
941 else if (c == '\'') { /* Definitely u, U or L char */
942 retract(s, 1);
943 state = 77;
944 }
945 else if (c == 'R') { /* Possibly CUSTOM DELIMITER u, U, L string */
946 state = 73;
947 }
948 else if (c == '8') { /* Possibly u8 string/char */
949 state = 71;
950 }
951 else {
952 retract(s, 1); /* Definitely an identifier */
953 state = 70;
954 }
955 break;
956
957 case 70: /* Identifier */
958 if ((c = nextchar(s)) == 0)
959 state = 76;
960 else if (isalnum(c) || (c == '_') || (c == '$')) {
961 state = 70;
962 } else {
963 retract(s, 1);
964 state = 76;
965 }
966 break;
967
968 case 71: /* Possibly u8 string/char */
969 if ((c = nextchar(s)) == 0) {
970 state = 76;
971 }
972 else if (c=='\"') {
973 retract(s, 1); /* Definitely u8 string */
974 state = 1000;
975 }
976 else if (c=='\'') {
977 retract(s, 1); /* Definitely u8 char */
978 state = 77;
979 }
980 else if (c=='R') {
981 state = 74; /* Possibly CUSTOM DELIMITER u8 string */
982 }
983 else {
984 retract(s, 2); /* Definitely an identifier. Retract 8" */
985 state = 70;
986 }
987
988 break;
989
990 case 72: /* Possibly CUSTOM DELIMITER string */
991 case 73:
992 case 74:
993 if ((c = nextchar(s)) == 0) {
994 state = 76;
995 }
996 else if (c=='\"') {
997 retract(s, 1); /* Definitely custom delimiter u, U or L string */
998 str_delimiter = NewStringEmpty();
999 state = 1000;
1000 }
1001 else {
1002 if (state==72) {
1003 retract(s, 1); /* Definitely an identifier. Retract ? */
1004 }
1005 else if (state==73) {
1006 retract(s, 2); /* Definitely an identifier. Retract R? */
1007 }
1008 else if (state==74) {
1009 retract(s, 3); /* Definitely an identifier. Retract 8R? */
1010 }
1011 state = 70;
1012 }
1013
1014 break;
1015
1016 case 75: /* Special identifier $ */
1017 if ((c = nextchar(s)) == 0)
1018 return SWIG_TOKEN_DOLLAR;
1019 if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
1020 state = 70;
1021 } else {
1022 retract(s,1);
1023 if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR;
1024 state = 76;
1025 }
1026 break;
1027
1028 case 76: /* Identifier or true/false */
1029 if (cparse_cplusplus) {
1030 if (Strcmp(s->text, "true") == 0)
1031 return SWIG_TOKEN_BOOL;
1032 else if (Strcmp(s->text, "false") == 0)
1033 return SWIG_TOKEN_BOOL;
1034 }
1035 return SWIG_TOKEN_ID;
1036 break;
1037
1038 case 77: /*identifier or wide string literal*/
1039 if ((c = nextchar(s)) == 0)
1040 return SWIG_TOKEN_ID;
1041 else if (c == '\"') {
1042 s->start_line = s->line;
1043 Clear(s->text);
1044 state = 78;
1045 }
1046 else if (c == '\'') {
1047 s->start_line = s->line;
1048 Clear(s->text);
1049 state = 79;
1050 }
1051 else if (isalnum(c) || (c == '_') || (c == '$'))
1052 state = 7;
1053 else {
1054 retract(s, 1);
1055 return SWIG_TOKEN_ID;
1056 }
1057 break;
1058
1059 case 78: /* Processing a wide string literal*/
1060 if ((c = nextchar(s)) == 0) {
1061 Swig_error(cparse_file, cparse_start_line, "Unterminated wide string\n");
1062 return SWIG_TOKEN_ERROR;
1063 }
1064 if (c == '\"') {
1065 Delitem(s->text, DOH_END);
1066 return SWIG_TOKEN_WSTRING;
1067 } else if (c == '\\') {
1068 if ((c = nextchar(s)) == 0) {
1069 Swig_error(cparse_file, cparse_start_line, "Unterminated wide string\n");
1070 return SWIG_TOKEN_ERROR;
1071 }
1072 }
1073 break;
1074
1075 case 79: /* Processing a wide char literal */
1076 if ((c = nextchar(s)) == 0) {
1077 Swig_error(cparse_file, cparse_start_line, "Unterminated wide character constant\n");
1078 return SWIG_TOKEN_ERROR;
1079 }
1080 if (c == '\'') {
1081 Delitem(s->text, DOH_END);
1082 return (SWIG_TOKEN_WCHAR);
1083 } else if (c == '\\') {
1084 if ((c = nextchar(s)) == 0) {
1085 Swig_error(cparse_file, cparse_start_line, "Unterminated wide character literal\n");
1086 return SWIG_TOKEN_ERROR;
1087 }
1088 }
1089 break;
1090
1091 case 8: /* A numerical digit */
1092 if ((c = nextchar(s)) == 0)
1093 return SWIG_TOKEN_INT;
1094 if (c == '.') {
1095 state = 81;
1096 } else if ((c == 'e') || (c == 'E')) {
1097 state = 82;
1098 } else if ((c == 'f') || (c == 'F')) {
1099 Delitem(s->text, DOH_END);
1100 return SWIG_TOKEN_FLOAT;
1101 } else if (isdigit(c)) {
1102 state = 8;
1103 } else if ((c == 'l') || (c == 'L')) {
1104 state = 87;
1105 } else if ((c == 'u') || (c == 'U')) {
1106 state = 88;
1107 } else {
1108 retract(s, 1);
1109 return SWIG_TOKEN_INT;
1110 }
1111 break;
1112 case 81: /* A floating pointer number of some sort */
1113 if ((c = nextchar(s)) == 0)
1114 return SWIG_TOKEN_DOUBLE;
1115 if (isdigit(c))
1116 state = 81;
1117 else if ((c == 'e') || (c == 'E'))
1118 state = 820;
1119 else if ((c == 'f') || (c == 'F')) {
1120 Delitem(s->text, DOH_END);
1121 return SWIG_TOKEN_FLOAT;
1122 } else if ((c == 'l') || (c == 'L')) {
1123 Delitem(s->text, DOH_END);
1124 return SWIG_TOKEN_DOUBLE;
1125 } else {
1126 retract(s, 1);
1127 return (SWIG_TOKEN_DOUBLE);
1128 }
1129 break;
1130 case 82:
1131 if ((c = nextchar(s)) == 0) {
1132 Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
1133 return SWIG_TOKEN_ERROR;
1134 }
1135 if ((isdigit(c)) || (c == '-') || (c == '+'))
1136 state = 86;
1137 else {
1138 retract(s, 2);
1139 Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
1140 return SWIG_TOKEN_ERROR;
1141 }
1142 break;
1143 case 820:
1144 /* Like case 82, but we've seen a decimal point. */
1145 if ((c = nextchar(s)) == 0) {
1146 Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
1147 return SWIG_TOKEN_ERROR;
1148 }
1149 if ((isdigit(c)) || (c == '-') || (c == '+'))
1150 state = 86;
1151 else {
1152 retract(s, 2);
1153 Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
1154 return SWIG_TOKEN_ERROR;
1155 }
1156 break;
1157 case 83:
1158 /* Might be a hexadecimal or octal number */
1159 if ((c = nextchar(s)) == 0)
1160 return SWIG_TOKEN_INT;
1161 if (isdigit(c))
1162 state = 84;
1163 else if ((c == 'e') || (c == 'E'))
1164 state = 82;
1165 else if ((c == 'x') || (c == 'X'))
1166 state = 85;
1167 else if ((c == 'b') || (c == 'B'))
1168 state = 850;
1169 else if (c == '.')
1170 state = 81;
1171 else if ((c == 'l') || (c == 'L')) {
1172 state = 87;
1173 } else if ((c == 'u') || (c == 'U')) {
1174 state = 88;
1175 } else {
1176 retract(s, 1);
1177 return SWIG_TOKEN_INT;
1178 }
1179 break;
1180 case 84:
1181 /* This is an octal number */
1182 if ((c = nextchar(s)) == 0)
1183 return SWIG_TOKEN_INT;
1184 if (isdigit(c))
1185 state = 84;
1186 else if (c == '.')
1187 state = 81;
1188 else if ((c == 'e') || (c == 'E'))
1189 state = 82;
1190 else if ((c == 'l') || (c == 'L')) {
1191 state = 87;
1192 } else if ((c == 'u') || (c == 'U')) {
1193 state = 88;
1194 } else {
1195 retract(s, 1);
1196 return SWIG_TOKEN_INT;
1197 }
1198 break;
1199 case 85:
1200 /* This is an hex number */
1201 if ((c = nextchar(s)) == 0)
1202 return SWIG_TOKEN_INT;
1203 if (isxdigit(c))
1204 state = 85;
1205 else if (c == '.') /* hexadecimal float */
1206 state = 860;
1207 else if ((c == 'p') || (c == 'P')) /* hexadecimal float */
1208 state = 820;
1209 else if ((c == 'l') || (c == 'L')) {
1210 state = 87;
1211 } else if ((c == 'u') || (c == 'U')) {
1212 state = 88;
1213 } else {
1214 retract(s, 1);
1215 return SWIG_TOKEN_INT;
1216 }
1217 break;
1218 case 850:
1219 /* This is a binary number */
1220 if ((c = nextchar(s)) == 0)
1221 return SWIG_TOKEN_INT;
1222 if ((c == '0') || (c == '1'))
1223 state = 850;
1224 else if ((c == 'l') || (c == 'L')) {
1225 state = 87;
1226 } else if ((c == 'u') || (c == 'U')) {
1227 state = 88;
1228 } else {
1229 retract(s, 1);
1230 return SWIG_TOKEN_INT;
1231 }
1232 break;
1233 case 860:
1234 /* hexadecimal float */
1235 if ((c = nextchar(s)) == 0) {
1236 Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
1237 return SWIG_TOKEN_ERROR;
1238 }
1239 if (isxdigit(c))
1240 state = 860;
1241 else if ((c == 'p') || (c == 'P'))
1242 state = 820;
1243 else {
1244 retract(s, 2);
1245 Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
1246 return SWIG_TOKEN_ERROR;
1247 }
1248 break;
1249 case 86:
1250 /* Rest of floating point number */
1251
1252 if ((c = nextchar(s)) == 0)
1253 return SWIG_TOKEN_DOUBLE;
1254 if (isdigit(c))
1255 state = 86;
1256 else if ((c == 'f') || (c == 'F')) {
1257 Delitem(s->text, DOH_END);
1258 return SWIG_TOKEN_FLOAT;
1259 } else if ((c == 'l') || (c == 'L')) {
1260 Delitem(s->text, DOH_END);
1261 return SWIG_TOKEN_DOUBLE;
1262 } else {
1263 retract(s, 1);
1264 return SWIG_TOKEN_DOUBLE;
1265 }
1266 break;
1267
1268 case 87:
1269 /* A long integer of some sort */
1270 if ((c = nextchar(s)) == 0)
1271 return SWIG_TOKEN_LONG;
1272 if ((c == 'u') || (c == 'U')) {
1273 return SWIG_TOKEN_ULONG;
1274 } else if ((c == 'l') || (c == 'L')) {
1275 state = 870;
1276 } else {
1277 retract(s, 1);
1278 return SWIG_TOKEN_LONG;
1279 }
1280 break;
1281
1282 /* A long long integer */
1283
1284 case 870:
1285 if ((c = nextchar(s)) == 0)
1286 return SWIG_TOKEN_LONGLONG;
1287 if ((c == 'u') || (c == 'U')) {
1288 return SWIG_TOKEN_ULONGLONG;
1289 } else {
1290 retract(s, 1);
1291 return SWIG_TOKEN_LONGLONG;
1292 }
1293
1294 /* An unsigned number */
1295 case 88:
1296
1297 if ((c = nextchar(s)) == 0)
1298 return SWIG_TOKEN_UINT;
1299 if ((c == 'l') || (c == 'L')) {
1300 state = 880;
1301 } else {
1302 retract(s, 1);
1303 return SWIG_TOKEN_UINT;
1304 }
1305 break;
1306
1307 /* Possibly an unsigned long long or unsigned long */
1308 case 880:
1309 if ((c = nextchar(s)) == 0)
1310 return SWIG_TOKEN_ULONG;
1311 if ((c == 'l') || (c == 'L'))
1312 return SWIG_TOKEN_ULONGLONG;
1313 else {
1314 retract(s, 1);
1315 return SWIG_TOKEN_ULONG;
1316 }
1317
1318 /* A character constant */
1319 case 9:
1320 if ((c = nextchar(s)) == 0) {
1321 Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
1322 return SWIG_TOKEN_ERROR;
1323 }
1324 if (c == '\'') {
1325 Delitem(s->text, DOH_END);
1326 return (SWIG_TOKEN_CHAR);
1327 } else if (c == '\\') {
1328 Delitem(s->text, DOH_END);
1329 get_escape(s);
1330 }
1331 break;
1332
1333 /* A period or maybe a floating point number */
1334
1335 case 100:
1336 if ((c = nextchar(s)) == 0)
1337 return (0);
1338 if (isdigit(c))
1339 state = 81;
1340 else {
1341 retract(s, 1);
1342 return SWIG_TOKEN_PERIOD;
1343 }
1344 break;
1345
1346 case 200: /* PLUS, PLUSPLUS, PLUSEQUAL */
1347 if ((c = nextchar(s)) == 0)
1348 return SWIG_TOKEN_PLUS;
1349 else if (c == '+')
1350 return SWIG_TOKEN_PLUSPLUS;
1351 else if (c == '=')
1352 return SWIG_TOKEN_PLUSEQUAL;
1353 else {
1354 retract(s, 1);
1355 return SWIG_TOKEN_PLUS;
1356 }
1357 break;
1358
1359 case 210: /* MINUS, MINUSMINUS, MINUSEQUAL, ARROW */
1360 if ((c = nextchar(s)) == 0)
1361 return SWIG_TOKEN_MINUS;
1362 else if (c == '-')
1363 return SWIG_TOKEN_MINUSMINUS;
1364 else if (c == '=')
1365 return SWIG_TOKEN_MINUSEQUAL;
1366 else if (c == '>')
1367 state = 211;
1368 else {
1369 retract(s, 1);
1370 return SWIG_TOKEN_MINUS;
1371 }
1372 break;
1373
1374 case 211: /* ARROW, ARROWSTAR */
1375 if ((c = nextchar(s)) == 0)
1376 return SWIG_TOKEN_ARROW;
1377 else if (c == '*')
1378 return SWIG_TOKEN_ARROWSTAR;
1379 else {
1380 retract(s, 1);
1381 return SWIG_TOKEN_ARROW;
1382 }
1383 break;
1384
1385
1386 case 220: /* STAR, TIMESEQUAL */
1387 if ((c = nextchar(s)) == 0)
1388 return SWIG_TOKEN_STAR;
1389 else if (c == '=')
1390 return SWIG_TOKEN_TIMESEQUAL;
1391 else {
1392 retract(s, 1);
1393 return SWIG_TOKEN_STAR;
1394 }
1395 break;
1396
1397 case 230: /* XOR, XOREQUAL */
1398 if ((c = nextchar(s)) == 0)
1399 return SWIG_TOKEN_XOR;
1400 else if (c == '=')
1401 return SWIG_TOKEN_XOREQUAL;
1402 else {
1403 retract(s, 1);
1404 return SWIG_TOKEN_XOR;
1405 }
1406 break;
1407
1408 case 240: /* LSHIFT, LSEQUAL */
1409 if ((c = nextchar(s)) == 0)
1410 return SWIG_TOKEN_LSHIFT;
1411 else if (c == '=')
1412 return SWIG_TOKEN_LSEQUAL;
1413 else {
1414 retract(s, 1);
1415 return SWIG_TOKEN_LSHIFT;
1416 }
1417 break;
1418
1419 case 250: /* RSHIFT, RSEQUAL */
1420 if ((c = nextchar(s)) == 0)
1421 return SWIG_TOKEN_RSHIFT;
1422 else if (c == '=')
1423 return SWIG_TOKEN_RSEQUAL;
1424 else {
1425 retract(s, 1);
1426 return SWIG_TOKEN_RSHIFT;
1427 }
1428 break;
1429
1430
1431 /* An illegal character */
1432
1433 /* Reverse string */
1434 case 900:
1435 if ((c = nextchar(s)) == 0) {
1436 Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
1437 return SWIG_TOKEN_ERROR;
1438 }
1439 if (c == '`') {
1440 Delitem(s->text, DOH_END);
1441 return (SWIG_TOKEN_RSTRING);
1442 }
1443 break;
1444
1445 default:
1446 return SWIG_TOKEN_ILLEGAL;
1447 }
1448 }
1449 }
1450
1451 /* -----------------------------------------------------------------------------
1452 * Scanner_token()
1453 *
1454 * Real entry point to return the next token. Returns 0 if at end of input.
1455 * ----------------------------------------------------------------------------- */
1456
Scanner_token(Scanner * s)1457 int Scanner_token(Scanner *s) {
1458 int t;
1459 Delete(s->error);
1460 if (s->nexttoken >= 0) {
1461 t = s->nexttoken;
1462 s->nexttoken = -1;
1463 return t;
1464 }
1465 s->start_line = 0;
1466 t = look(s);
1467 if (!s->start_line) {
1468 Setline(s->text,s->line);
1469 } else {
1470 Setline(s->text,s->start_line);
1471 }
1472 return t;
1473 }
1474
1475 /* -----------------------------------------------------------------------------
1476 * Scanner_text()
1477 *
1478 * Return the lexene associated with the last returned token.
1479 * ----------------------------------------------------------------------------- */
1480
Scanner_text(Scanner * s)1481 String *Scanner_text(Scanner *s) {
1482 return s->text;
1483 }
1484
1485 /* -----------------------------------------------------------------------------
1486 * Scanner_skip_line()
1487 *
1488 * Skips to the end of a line
1489 * ----------------------------------------------------------------------------- */
1490
Scanner_skip_line(Scanner * s)1491 void Scanner_skip_line(Scanner *s) {
1492 char c;
1493 int done = 0;
1494 Clear(s->text);
1495 Setfile(s->text, Getfile(s->str));
1496 Setline(s->text, s->line);
1497 while (!done) {
1498 if ((c = nextchar(s)) == 0)
1499 return;
1500 if (c == '\\') {
1501 nextchar(s);
1502 } else if (c == '\n') {
1503 done = 1;
1504 }
1505 }
1506 return;
1507 }
1508
1509 /* -----------------------------------------------------------------------------
1510 * Scanner_skip_balanced()
1511 *
1512 * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
1513 * (...). Ignores symbols inside comments or strings.
1514 * ----------------------------------------------------------------------------- */
1515
Scanner_skip_balanced(Scanner * s,int startchar,int endchar)1516 int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
1517 char c;
1518 int num_levels = 1;
1519 int state = 0;
1520 char temp[2] = { 0, 0 };
1521 String *locator = 0;
1522 temp[0] = (char) startchar;
1523 Clear(s->text);
1524 Setfile(s->text, Getfile(s->str));
1525 Setline(s->text, s->line);
1526
1527 Append(s->text, temp);
1528 while (num_levels > 0) {
1529 if ((c = nextchar(s)) == 0) {
1530 Delete(locator);
1531 return -1;
1532 }
1533 switch (state) {
1534 case 0:
1535 if (c == startchar)
1536 num_levels++;
1537 else if (c == endchar)
1538 num_levels--;
1539 else if (c == '/')
1540 state = 10;
1541 else if (c == '\"')
1542 state = 20;
1543 else if (c == '\'')
1544 state = 30;
1545 break;
1546 case 10:
1547 if (c == '/')
1548 state = 11;
1549 else if (c == '*')
1550 state = 12;
1551 else if (c == startchar) {
1552 state = 0;
1553 num_levels++;
1554 }
1555 else
1556 state = 0;
1557 break;
1558 case 11:
1559 if (c == '\n')
1560 state = 0;
1561 else
1562 state = 11;
1563 break;
1564 case 12: /* first character inside C comment */
1565 if (c == '*')
1566 state = 14;
1567 else if (c == '@')
1568 state = 40;
1569 else
1570 state = 13;
1571 break;
1572 case 13:
1573 if (c == '*')
1574 state = 14;
1575 break;
1576 case 14: /* possible end of C comment */
1577 if (c == '*')
1578 state = 14;
1579 else if (c == '/')
1580 state = 0;
1581 else
1582 state = 13;
1583 break;
1584 case 20:
1585 if (c == '\"')
1586 state = 0;
1587 else if (c == '\\')
1588 state = 21;
1589 break;
1590 case 21:
1591 state = 20;
1592 break;
1593 case 30:
1594 if (c == '\'')
1595 state = 0;
1596 else if (c == '\\')
1597 state = 31;
1598 break;
1599 case 31:
1600 state = 30;
1601 break;
1602 /* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */
1603 case 40:
1604 state = (c == 'S') ? 41 : (c == '*') ? 14 : 13;
1605 break;
1606 case 41:
1607 state = (c == 'W') ? 42 : (c == '*') ? 14 : 13;
1608 break;
1609 case 42:
1610 state = (c == 'I') ? 43 : (c == '*') ? 14 : 13;
1611 break;
1612 case 43:
1613 state = (c == 'G') ? 44 : (c == '*') ? 14 : 13;
1614 if (c == 'G') {
1615 Delete(locator);
1616 locator = NewString("/*@SWIG");
1617 }
1618 break;
1619 case 44:
1620 if (c == '*')
1621 state = 45;
1622 Putc(c, locator);
1623 break;
1624 case 45: /* end of SWIG locator in C comment */
1625 if (c == '/') {
1626 state = 0;
1627 Putc(c, locator);
1628 Scanner_locator(s, locator);
1629 } else {
1630 /* malformed locator */
1631 state = (c == '*') ? 14 : 13;
1632 }
1633 break;
1634 default:
1635 break;
1636 }
1637 }
1638 Delete(locator);
1639 return 0;
1640 }
1641
1642 /* -----------------------------------------------------------------------------
1643 * Scanner_get_raw_text_balanced()
1644 *
1645 * Returns raw text between 2 braces, does not change scanner state in any way
1646 * ----------------------------------------------------------------------------- */
1647
Scanner_get_raw_text_balanced(Scanner * s,int startchar,int endchar)1648 String *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) {
1649 String *result = 0;
1650 char c;
1651 int old_line = s->line;
1652 String *old_text = Copy(s->text);
1653 long position = Tell(s->str);
1654
1655 int num_levels = 1;
1656 int state = 0;
1657 char temp[2] = { 0, 0 };
1658 temp[0] = (char) startchar;
1659 Clear(s->text);
1660 Setfile(s->text, Getfile(s->str));
1661 Setline(s->text, s->line);
1662 Append(s->text, temp);
1663 while (num_levels > 0) {
1664 if ((c = nextchar(s)) == 0) {
1665 Clear(s->text);
1666 Append(s->text, old_text);
1667 Delete(old_text);
1668 s->line = old_line;
1669 return 0;
1670 }
1671 switch (state) {
1672 case 0:
1673 if (c == startchar)
1674 num_levels++;
1675 else if (c == endchar)
1676 num_levels--;
1677 else if (c == '/')
1678 state = 10;
1679 else if (c == '\"')
1680 state = 20;
1681 else if (c == '\'')
1682 state = 30;
1683 break;
1684 case 10:
1685 if (c == '/')
1686 state = 11;
1687 else if (c == '*')
1688 state = 12;
1689 else if (c == startchar) {
1690 state = 0;
1691 num_levels++;
1692 }
1693 else
1694 state = 0;
1695 break;
1696 case 11:
1697 if (c == '\n')
1698 state = 0;
1699 else
1700 state = 11;
1701 break;
1702 case 12: /* first character inside C comment */
1703 if (c == '*')
1704 state = 14;
1705 else
1706 state = 13;
1707 break;
1708 case 13:
1709 if (c == '*')
1710 state = 14;
1711 break;
1712 case 14: /* possible end of C comment */
1713 if (c == '*')
1714 state = 14;
1715 else if (c == '/')
1716 state = 0;
1717 else
1718 state = 13;
1719 break;
1720 case 20:
1721 if (c == '\"')
1722 state = 0;
1723 else if (c == '\\')
1724 state = 21;
1725 break;
1726 case 21:
1727 state = 20;
1728 break;
1729 case 30:
1730 if (c == '\'')
1731 state = 0;
1732 else if (c == '\\')
1733 state = 31;
1734 break;
1735 case 31:
1736 state = 30;
1737 break;
1738 default:
1739 break;
1740 }
1741 }
1742 Seek(s->str, position, SEEK_SET);
1743 result = Copy(s->text);
1744 Clear(s->text);
1745 Append(s->text, old_text);
1746 Delete(old_text);
1747 s->line = old_line;
1748 return result;
1749 }
1750 /* -----------------------------------------------------------------------------
1751 * Scanner_isoperator()
1752 *
1753 * Returns 0 or 1 depending on whether or not a token corresponds to a C/C++
1754 * operator.
1755 * ----------------------------------------------------------------------------- */
1756
Scanner_isoperator(int tokval)1757 int Scanner_isoperator(int tokval) {
1758 if (tokval >= 100) return 1;
1759 return 0;
1760 }
1761
1762 /* ----------------------------------------------------------------------
1763 * locator()
1764 *
1765 * Support for locator strings. These are strings of the form
1766 * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
1767 * are primarily used for macro line number reporting.
1768 * We just use the locator to mark when to activate/deactivate linecounting.
1769 * ---------------------------------------------------------------------- */
1770
1771
Scanner_locator(Scanner * s,String * loc)1772 void Scanner_locator(Scanner *s, String *loc) {
1773 static Locator *locs = 0;
1774 static int expanding_macro = 0;
1775
1776 if (!follow_locators) {
1777 if (Equal(loc, "/*@SWIG@*/")) {
1778 /* End locator. */
1779 if (expanding_macro)
1780 --expanding_macro;
1781 } else {
1782 /* Begin locator. */
1783 ++expanding_macro;
1784 }
1785 /* Freeze line number processing in Scanner */
1786 freeze_line(s,expanding_macro);
1787 } else {
1788 int c;
1789 Locator *l;
1790 (void)Seek(loc, 7, SEEK_SET);
1791 c = Getc(loc);
1792 if (c == '@') {
1793 /* Empty locator. We pop the last location off */
1794 if (locs) {
1795 Scanner_set_location(s, locs->filename, locs->line_number);
1796 cparse_file = locs->filename;
1797 cparse_line = locs->line_number;
1798 l = locs->next;
1799 free(locs);
1800 locs = l;
1801 }
1802 return;
1803 }
1804
1805 /* We're going to push a new location */
1806 l = (Locator *) malloc(sizeof(Locator));
1807 l->filename = cparse_file;
1808 l->line_number = cparse_line;
1809 l->next = locs;
1810 locs = l;
1811
1812 /* Now, parse the new location out of the locator string */
1813 {
1814 String *fn = NewStringEmpty();
1815 /* Putc(c, fn); */
1816
1817 while ((c = Getc(loc)) != EOF) {
1818 if ((c == '@') || (c == ','))
1819 break;
1820 Putc(c, fn);
1821 }
1822 cparse_file = Swig_copy_string(Char(fn));
1823 Clear(fn);
1824 cparse_line = 1;
1825 /* Get the line number */
1826 while ((c = Getc(loc)) != EOF) {
1827 if ((c == '@') || (c == ','))
1828 break;
1829 Putc(c, fn);
1830 }
1831 cparse_line = atoi(Char(fn));
1832 Clear(fn);
1833
1834 /* Get the rest of it */
1835 while ((c = Getc(loc)) != EOF) {
1836 if (c == '@')
1837 break;
1838 Putc(c, fn);
1839 }
1840 /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
1841 Scanner_set_location(s, cparse_file, cparse_line);
1842 Delete(fn);
1843 }
1844 }
1845 }
1846
Swig_cparse_follow_locators(int v)1847 void Swig_cparse_follow_locators(int v) {
1848 follow_locators = v;
1849 }
1850
1851
1852