]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/scanner.cxx
reSWIGged
[wxWidgets.git] / wxPython / wxSWIG / SWIG / scanner.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
3 *
4 * Author : David Beazley
5 *
6 * Department of Computer Science
7 * University of Chicago
8 * 1100 E 58th Street
9 * Chicago, IL 60637
10 * beazley@cs.uchicago.edu
11 *
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
15
16 /*************************************************************************
17 * $Header$
18 * scanner.c
19 *
20 * Dave Beazley
21 * January 1996
22 *
23 * Input scanner. This scanner finds and returns tokens
24 * for the wrapper generator. Since using lex/flex from
25 * C++ is so F'ed up, I've written this function to replace
26 * them entirely. It's not as fast, but hopefully it will
27 * eliminate alot of compilation problems.
28 *
29 *************************************************************************/
30
31
32 #include "internal.h"
33 #include "parser.h"
34 #include <string.h>
35 #include <ctype.h>
36
37 #define YYBSIZE 8192
38
39 struct InFile {
40 FILE *f;
41 int line_number;
42 char *in_file;
43 int extern_mode;
44 int force_extern;
45 struct InFile *prev;
46 };
47
48 // This structure is used for managing code fragments as
49 // might be used by the %inline directive and handling of
50 // nested structures.
51
52 struct CodeFragment {
53 char *text;
54 int line_number;
55 CodeFragment *next;
56 };
57
58 InFile *in_head;
59
60 FILE *LEX_in = NULL;
61
62 static String header;
63 static String comment;
64 String CCode; // String containing C code
65 static char *yybuffer;
66 static int lex_pos = 0;
67 static int lex_len = 0;
68 static char *inline_yybuffer = 0;
69 static int inline_lex_pos = 0;
70 static int inline_lex_len = 0;
71 static int inline_line_number = 0;
72 static CodeFragment *fragments = 0; // Code fragments
73
74 static
75 char yytext[YYBSIZE];
76 static int yylen = 0;
77 int line_number = 1;
78 int column = 1;
79 int column_start = 1;
80 char *input_file;
81 int start_line = 0;
82 static int comment_start;
83 static int scan_init = 0;
84 static int num_brace = 0;
85 static int last_brace = 0;
86 static int in_define = 0;
87 static int define_first_id = 0; /* Set when looking for first identifier of a define */
88 extern int Error;
89
90
91 /**************************************************************
92 * scanner_init()
93 *
94 * Initialize buffers
95 **************************************************************/
96
97 void scanner_init() {
98
99 yybuffer = (char *) malloc(YYBSIZE);
100 scan_init = 1;
101 }
102
103 /**************************************************************
104 * scanner_file(FILE *f)
105 *
106 * Start reading from new file
107 **************************************************************/
108 void scanner_file(FILE *f) {
109 InFile *in;
110
111 in = new InFile;
112 in->f = f;
113 in->in_file = input_file;
114 in->extern_mode = WrapExtern;
115 in->force_extern = ForceExtern;
116 if (in_head) in_head->line_number = line_number+1;
117 if (!in_head) in->prev = 0;
118 else in->prev = in_head;
119 in_head = in;
120 LEX_in = f;
121 line_number = 1;
122 }
123
124 /**************************************************************
125 * scanner_close()
126 *
127 * Close current input file and go to next
128 **************************************************************/
129
130 void scanner_close() {
131
132 InFile *p;
133 static int lib_insert = 0;
134 fclose(LEX_in);
135 if (!in_head) return;
136 p = in_head->prev;
137 if (p != 0) {
138 LEX_in = p->f;
139 line_number = p->line_number;
140 input_file = p->in_file;
141 WrapExtern = p->extern_mode;
142 if (!WrapExtern) remove_symbol("SWIGEXTERN");
143 ForceExtern = p->force_extern;
144 } else {
145 LEX_in = NULL;
146 }
147 delete in_head;
148 in_head = p;
149
150 // if LEX_in is NULL it means we're done with the interface file. We're now
151 // going to grab all of the library files.
152
153 if ((!LEX_in) && (!lib_insert)) {
154 library_insert();
155 lib_insert = 1;
156 }
157
158 }
159
160 /**************************************************************
161 * char nextchar()
162 *
163 * gets next character from input.
164 * If we're in inlining mode, we actually retrieve a character
165 * from inline_yybuffer instead.
166 **************************************************************/
167
168 char nextchar() {
169
170 char c = 0;
171
172 if (Inline) {
173 if (inline_lex_pos >= inline_lex_len) {
174 // Done with inlined code. Check to see if we have any
175 // new code fragments. If so, switch to them.
176 delete inline_yybuffer;
177 if (fragments) {
178 CodeFragment *f;
179 inline_yybuffer = fragments->text;
180 inline_lex_pos = 1;
181 inline_lex_len = strlen(fragments->text);
182 line_number = fragments->line_number;
183 f = fragments->next;
184 delete fragments;
185 fragments = f;
186 c = inline_yybuffer[0];
187 } else {
188 c = 0;
189 Inline = 0;
190 line_number = inline_line_number; // Restore old line number
191 }
192 } else {
193 inline_lex_pos++;
194 c = inline_yybuffer[inline_lex_pos-1];
195 }
196 }
197 if (!Inline) {
198 if (lex_pos >= lex_len) {
199 if (!LEX_in) {
200 SWIG_exit(1);
201 }
202 while(fgets(yybuffer, YYBSIZE, LEX_in) == NULL) {
203 scanner_close(); // Close current input file
204 if (!LEX_in) return 0; // No more, we're outta here
205 }
206 lex_len = strlen(yybuffer);
207 lex_pos = 0;
208 }
209
210 lex_pos++;
211 c = yybuffer[lex_pos-1];
212 }
213
214 if (yylen >= YYBSIZE) {
215 fprintf(stderr,"** FATAL ERROR. Buffer overflow in scanner.cxx.\nReport this to swig@cs.utah.edu.\n");
216 SWIG_exit(1);
217 }
218 yytext[yylen] = c;
219 yylen++;
220 if (c == '\n') {
221 line_number++;
222 column = 1;
223 } else {
224 column++;
225 }
226 return(c);
227 }
228
229 void retract(int n) {
230 int i, j, c;
231
232 for (i = 0; i < n; i++) {
233 if (Inline) {
234 inline_lex_pos--;
235 if (inline_lex_pos < 0) {
236 fprintf(stderr,"Internal scanner error. inline_lex_pos < 0\n");
237 SWIG_exit(1);
238 }
239 }
240 else lex_pos--;
241 yylen--;
242 column--;
243 if (yylen >= 0) {
244 if (yytext[yylen] == '\n') {
245 line_number--;
246 // Figure out what column we're in
247 c = yylen-1;
248 j = 1;
249 while (c >= 0){
250 if (yytext[c] == '\n') break;
251 j++;
252 c--;
253 }
254 column = j;
255 }
256 }
257 }
258 if (yylen < 0) yylen = 0;
259 }
260
261 /**************************************************************
262 * start_inline(char *text, int line)
263 *
264 * This grabs a chunk of text and tries to inline it into
265 * the current file. (This is kind of wild, but cool when
266 * it works).
267 *
268 * If we're already in inlining mode, we will save the code
269 * as a new fragment.
270 **************************************************************/
271
272 void start_inline(char *text, int line) {
273
274 if (Inline) {
275
276 // Already processing a code fragment, simply hang on
277 // to this one for later.
278
279 CodeFragment *f,*f1;
280
281 // Add a new code fragment to our list
282 f = new CodeFragment;
283 f->text = copy_string(text);
284 f->line_number = line;
285 f->next = 0;
286 if (!fragments) fragments = f;
287 else {
288 f1 = fragments;
289 while (f1->next) f1 = f1->next;
290 f1->next = f;
291 }
292 } else {
293
294 // Switch our scanner over to process text from a string.
295 // Save current line number and other information however.
296
297 inline_yybuffer = copy_string(text);
298 inline_lex_len = strlen(text);
299 inline_lex_pos = 0;
300 inline_line_number = line_number; // Make copy of old line number
301 line_number = line;
302 Inline = 1;
303 }
304 }
305
306 /**************************************************************
307 * yycomment(char *, int line)
308 *
309 * Inserts a comment into a documentation entry.
310 **************************************************************/
311
312 void yycomment(char *s, int line, int col) {
313 comment_handler->add_comment(s,line,col,input_file);
314 }
315
316 /**************************************************************
317 * void skip_brace(void)
318 *
319 * Found a {.
320 * Skip all characters until we find a matching closed }.
321 *
322 * This function is used to skip over inlined C code and other
323 * garbage found in interface files.
324 ***************************************************************/
325
326 void skip_brace(void) {
327
328 char c;
329 CCode = "{";
330 while (num_brace > last_brace) {
331 if ((c = nextchar()) == 0) {
332 fprintf(stderr,"%s : Line %d. Missing '}'. Reached end of input.\n",
333 input_file, line_number);
334 FatalError();
335 return;
336 }
337 CCode << c;
338 if (c == '{') num_brace++;
339 if (c == '}') num_brace--;
340 yylen = 0;
341 }
342 }
343
344
345 /**************************************************************
346 * void skip_template(void)
347 *
348 * Found a <.
349 * Skip all characters until we find a matching closed >.
350 *
351 * This function is used to skip over C++ templated types
352 * and objective-C protocols.
353 ***************************************************************/
354
355 void skip_template(void) {
356
357 char c;
358 CCode = "<";
359 int num_lt = 1;
360 while (num_lt > 0) {
361 if ((c = nextchar()) == 0) {
362 fprintf(stderr,"%s : Line %d. Missing '>'. Reached end of input.\n",
363 input_file, line_number);
364 FatalError();
365 return;
366 }
367 CCode << c;
368 if (c == '<') num_lt++;
369 if (c == '>') num_lt--;
370 yylen = 0;
371 }
372 }
373
374 /**************************************************************
375 * void skip_to_end(void)
376 *
377 * Skips to the @end directive in a Objective-C definition
378 **************************************************************/
379
380 void skip_to_end(void) {
381 char c;
382 int state = 0;
383 yylen = 0;
384 while ((c = nextchar())){
385 switch(state) {
386 case 0:
387 if (c == '@') state = 1;
388 else yylen = 0;
389 break;
390 case 1:
391 if (isspace(c)) {
392 if (strncmp(yytext,"@end",4) == 0) return;
393 else {
394 yylen = 0;
395 state = 0;
396 }
397 } else {
398 state = 1;
399 }
400 break;
401 }
402 }
403 fprintf(stderr,"%s : EOF. Missing @end. Reached end of input.\n",
404 input_file);
405 FatalError();
406 return;
407 }
408
409 /**************************************************************
410 * void skip_decl(void)
411 *
412 * This tries to skip over an entire declaration. For example
413 *
414 * friend ostream& operator<<(ostream&, const char *s);
415 *
416 * or
417 * friend ostream& operator<<(ostream&, const char *s) { };
418 *
419 **************************************************************/
420
421 void skip_decl(void) {
422 char c;
423 int done = 0;
424 while (!done) {
425 if ((c = nextchar()) == 0) {
426 fprintf(stderr,"%s : Line %d. Missing semicolon. Reached end of input.\n",
427 input_file, line_number);
428 FatalError();
429 return;
430 }
431 if (c == '{') {
432 last_brace = num_brace;
433 num_brace++;
434 break;
435 }
436 yylen = 0;
437 if (c == ';') done = 1;
438 }
439 if (!done) {
440 while (num_brace > last_brace) {
441 if ((c = nextchar()) == 0) {
442 fprintf(stderr,"%s : Line %d. Missing '}'. Reached end of input.\n",
443 input_file, line_number);
444 FatalError();
445 return;
446 }
447 if (c == '{') num_brace++;
448 if (c == '}') num_brace--;
449 yylen = 0;
450 }
451 }
452 }
453
454 /**************************************************************
455 * void skip_define(void)
456 *
457 * Skips to the end of a #define statement.
458 *
459 **************************************************************/
460
461 void skip_define(void) {
462 char c;
463 while (in_define) {
464 if ((c = nextchar()) == 0) return;
465 if (c == '\\') in_define = 2;
466 if (c == '\n') {
467 if (in_define == 2) {
468 in_define = 1;
469 } else if (in_define == 1) {
470 in_define = 0;
471 }
472 }
473 yylen = 0;
474 }
475 }
476
477 /**************************************************************
478 * int skip_cond(int inthen)
479 *
480 * Skips the false portion of an #ifdef directive. Looks
481 * for either a matching #else or #endif
482 *
483 * inthen is 0 or 1 depending on whether or not we're
484 * handling the "then" or "else" part of a conditional.
485 *
486 * Returns 1 if the else part of the #if-#endif block was
487 * reached. Returns 0 otherwise. Returns -1 on error.
488 **************************************************************/
489
490 int skip_cond(int inthen) {
491 int level = 0; /* Used to handled nested if-then-else */
492 int state = 0;
493 char c;
494 int start_line;
495 char *file;
496
497 file = copy_string(input_file);
498 start_line = line_number;
499 yylen = 0;
500
501 while(1) {
502 switch(state) {
503 case 0 :
504 if ((c = nextchar()) == 0) {
505 fprintf(stderr,"%s : Line %d. Unterminated #if-else directive.\n", file, start_line);
506 FatalError();
507 return -1; /* Error */
508 }
509 if ((c == '#') || (c == '%')) {
510 state = 1;
511 } else if (isspace(c)) {
512 yylen =0;
513 state = 0;
514 } else {
515 /* Some non-whitespace character. Look for line end */
516 yylen = 0;
517 state = 3;
518 }
519 break;
520 case 1:
521 /* Beginning of a C preprocessor statement */
522 if ((c = nextchar()) == 0) {
523 fprintf(stderr,"%s : Line %d. Unterminated #if-else directive.\n", file, start_line);
524 FatalError();
525 return -1; /* Error */
526 }
527 if (c == '\n') {
528 state = 0;
529 yylen = 0;
530 }
531 else if (isspace(c)) {
532 state = 1;
533 yylen--;
534 } else {
535 state = 2;
536 }
537 break;
538 case 2:
539 /* CPP directive */
540 if ((c = nextchar()) == 0) {
541 fprintf(stderr,"%s : Line %d. Unterminated #if-else directive.\n", file, start_line);
542 FatalError();
543 return -1; /* Error */
544 }
545 if ((c == ' ') || (c == '\t') || (c=='\n')) {
546 yytext[yylen-1] = 0;
547 if ((strcmp(yytext,"#ifdef") == 0) || (strcmp(yytext,"%ifdef") == 0)) {
548 level++;
549 state = 0;
550 } else if ((strcmp(yytext,"#ifndef") == 0) || (strcmp(yytext,"%ifndef") == 0)) {
551 level++;
552 state = 0;
553 } else if ((strcmp(yytext,"#if") == 0) || (strcmp(yytext,"%if") == 0)) {
554 level++;
555 state = 0;
556 } else if ((strcmp(yytext,"#else") == 0) || (strcmp(yytext,"%else") == 0)) {
557 if (level == 0) { /* Found matching else. exit */
558 if (!inthen) {
559 /* Hmmm. We've got an "extra #else" directive here */
560 fprintf(stderr,"%s : Line %d. Misplaced #else.\n", input_file, line_number);
561 FatalError();
562 yylen = 0;
563 state = 0;
564 } else {
565 yylen = 0;
566 delete file;
567 return 1;
568 }
569 } else {
570 yylen = 0;
571 state = 0;
572 }
573 } else if ((strcmp(yytext,"#endif") == 0) || (strcmp(yytext,"%endif") == 0)) {
574 if (level <= 0) { /* Found matching endif. exit */
575 yylen = 0;
576 delete file;
577 return 0;
578 } else {
579 state = 0;
580 yylen = 0;
581 level--;
582 }
583 } else if ((strcmp(yytext,"#elif") == 0) || (strcmp(yytext,"%elif") == 0)) {
584 if (level <= 0) {
585 // If we come across this, we pop it back onto the input queue and return
586 retract(6);
587 delete file;
588 return 0;
589 } else {
590 yylen = 0;
591 state = 0;
592 }
593 } else {
594 yylen = 0;
595 state = 0;
596 }
597 }
598 break;
599 case 3:
600 /* Non-white space. Look for line break */
601 if ((c = nextchar()) == 0) {
602 fprintf(stderr,"%s : Line %d. Unterminated #if directive.\n", file, start_line);
603 FatalError();
604 return -1; /* Error */
605 }
606 if (c == '\n') {
607 yylen = 0;
608 state = 0;
609 } else {
610 yylen = 0;
611 state = 3;
612 }
613 break;
614 }
615 }
616 }
617
618 /**************************************************************
619 * int yylook()
620 *
621 * Lexical scanner.
622 * See Aho,Sethi, and Ullman, pg. 106
623 **************************************************************/
624
625 int yylook(void) {
626
627 int state;
628 char c = 0;
629
630 state = 0;
631 yylen = 0;
632 while(1) {
633
634 /* printf("State = %d\n", state); */
635 switch(state) {
636
637 case 0 :
638 if((c = nextchar()) == 0) return(0);
639
640 /* Process delimeters */
641
642 if (c == '\n') {
643 state = 0;
644 yylen = 0;
645 if (in_define == 1) {
646 in_define = 0;
647 return(ENDDEF);
648 } else if (in_define == 2) {
649 in_define = 1;
650 }
651 } else if (isspace(c)) {
652 state = 0;
653 yylen = 0;
654 }
655
656 /* Look for single character symbols */
657
658 else if (c == '(') return (LPAREN);
659 else if (c == ')') return (RPAREN);
660 else if (c == ';') return (SEMI);
661 else if (c == ',') return (COMMA);
662 else if (c == '*') return (STAR);
663 else if (c == '}') {
664 num_brace--;
665 if (num_brace < 0) {
666 fprintf(stderr,"%s : Line %d. Error. Extraneous '}' (Ignored)\n",
667 input_file, line_number);
668 state = 0;
669 num_brace = 0;
670 } else {
671 return (RBRACE);
672 }
673 }
674 else if (c == '{') {
675 last_brace = num_brace;
676 num_brace++;
677 return (LBRACE);
678 }
679 else if (c == '=') return (EQUAL);
680 else if (c == '+') return (PLUS);
681 else if (c == '-') return (MINUS);
682 else if (c == '&') return (AND);
683 else if (c == '|') return (OR);
684 else if (c == '^') return (XOR);
685 else if (c == '<') state = 60;
686 else if (c == '>') state = 61;
687 else if (c == '~') return (NOT);
688 else if (c == '!') return (LNOT);
689 else if (c == '\\') {
690 if (in_define == 1) {
691 in_define = 2;
692 state = 0;
693 } else
694 state = 99;
695 }
696 else if (c == '[') return (LBRACKET);
697 else if (c == ']') return (RBRACKET);
698
699 /* Look for multi-character sequences */
700
701 else if (c == '/') state = 1; // Comment (maybe)
702 else if (c == '\"') state = 2; // Possibly a string
703 else if (c == '#') state = 3; // CPP
704 else if (c == '%') state = 4; // Directive
705 else if (c == '@') state = 4; // Objective C keyword
706 else if (c == ':') state = 5; // maybe double colon
707 else if (c == '0') state = 83; // An octal or hex value
708 else if (c == '\'') state = 9; // A character constant
709 else if (c == '.') state = 100; // Maybe a number, maybe just a period
710 else if (isdigit(c)) state = 8; // A numerical value
711 else if ((isalpha(c)) || (c == '_') || (c == '$')) state = 7;
712 else state = 99;
713 break;
714 case 1: /* Comment block */
715 if ((c = nextchar()) == 0) return(0);
716 if (c == '/') {
717 comment_start = line_number;
718 column_start = column;
719 comment = " ";
720 state = 10; // C++ style comment
721 } else if (c == '*') {
722 comment_start = line_number;
723 column_start = column;
724 comment = " ";
725 state = 11; // C style comment
726 } else {
727 retract(1);
728 return(SLASH);
729 }
730 break;
731 case 10: /* C++ style comment */
732 if ((c = nextchar()) == 0) {
733 fprintf(stderr,"%s : EOF. Unterminated comment detected.\n",input_file);
734 FatalError();
735 return 0;
736 }
737 if (c == '\n') {
738 comment << c;
739 // Add the comment to documentation
740 yycomment(comment.get(),comment_start, column_start);
741 yylen = 0;
742 state = 0;
743 if (in_define == 1) {
744 in_define = 0;
745 return(ENDDEF);
746 }
747 } else {
748 state = 10;
749 comment << c;
750 yylen = 0;
751 }
752 break;
753 case 11: /* C style comment block */
754 if ((c = nextchar()) == 0) {
755 fprintf(stderr,"%s : EOF. Unterminated comment detected.\n", input_file);
756 FatalError();
757 return 0;
758 }
759 if (c == '*') {
760 state = 12;
761 } else {
762 comment << c;
763 yylen = 0;
764 state = 11;
765 }
766 break;
767 case 12: /* Still in C style comment */
768 if ((c = nextchar()) == 0) {
769 fprintf(stderr,"%s : EOF. Unterminated comment detected.\n", input_file);
770 FatalError();
771 return 0;
772 }
773 if (c == '*') {
774 comment << c;
775 state = 12;
776 } else if (c == '/') {
777 comment << " \n";
778 yycomment(comment.get(),comment_start,column_start);
779 yylen = 0;
780 state = 0;
781 } else {
782 comment << '*' << c;
783 yylen = 0;
784 state = 11;
785 }
786 break;
787
788 case 2: /* Processing a string */
789 if ((c = nextchar()) == 0) {
790 fprintf(stderr,"%s : EOF. Unterminated string detected.\n", input_file);
791 FatalError();
792 return 0;
793 }
794 if (c == '\"') {
795 yytext[yylen-1] = 0;
796 yylval.id = copy_string(yytext+1);
797 return(STRING);
798 } else if (c == '\\') {
799 state = 21; /* Possibly an escape sequence. */
800 break;
801 } else state = 2;
802 break;
803 case 21: /* An escape sequence. get next character, then go
804 back to processing strings */
805
806 if ((c = nextchar()) == 0) return 0;
807 state = 2;
808 break;
809
810 case 3: /* a CPP directive */
811
812 if (( c= nextchar()) == 0) return 0;
813 if (c == '\n') {
814 retract(1);
815 yytext[yylen] = 0;
816 yylval.id = yytext;
817 return(POUND);
818 } else if ((c == ' ') || (c == '\t')) { // Ignore white space after # symbol
819 yytext[yylen] = 0;
820 yylen--;
821 state = 3;
822 } else {
823 yytext[yylen] = 0;
824 state = 31;
825 }
826 break;
827 case 31:
828 if ((c = nextchar()) == 0) return 0;
829 if ((c == ' ') || (c == '\t') || (c=='\n')) {
830 retract(1);
831 yytext[yylen] = 0;
832 if (strcmp(yytext,"#define") == 0) {
833 in_define = 1;
834 define_first_id = 1;
835 return(DEFINE);
836 } else if (strcmp(yytext,"#ifdef") == 0) {
837 return(IFDEF);
838 } else if (strcmp(yytext,"#ifndef") == 0) {
839 return(IFNDEF);
840 } else if (strcmp(yytext,"#else") == 0) {
841 return(ELSE);
842 } else if (strcmp(yytext,"#endif") == 0) {
843 return(ENDIF);
844 } else if (strcmp(yytext,"#undef") == 0) {
845 return(UNDEF);
846 } else if (strcmp(yytext,"#if") == 0) {
847 return(IF);
848 } else if (strcmp(yytext,"#elif") == 0) {
849 return(ELIF);
850 } else {
851 /* Some kind of "unknown CPP directive. Skip to end of the line */
852 state = 32;
853 }
854 }
855 break;
856 case 32:
857 if ((c = nextchar()) == 0) return 0;
858 if (c == '\n') {
859 retract(1);
860 yytext[yylen] = 0;
861 yylval.id = yytext;
862 return(POUND);
863 }
864 state = 32;
865 break;
866
867 case 4: /* A wrapper generator directive (maybe) */
868 if (( c= nextchar()) == 0) return 0;
869 if (c == '{') {
870 state = 40; /* Include block */
871 header = "";
872 start_line = line_number;
873 }
874 else if ((isalpha(c)) || (c == '_')) state = 7;
875 else {
876 retract(1);
877 state = 99;
878 }
879 break;
880
881 case 40: /* Process an include block */
882 if ((c = nextchar()) == 0) {
883 fprintf(stderr,"%s : EOF. Unterminated include block detected.\n", input_file);
884 FatalError();
885 return 0;
886 }
887 yylen = 0;
888 if (c == '%') state = 41;
889 else {
890 header << c;
891 yylen = 0;
892 state = 40;
893 }
894 break;
895 case 41: /* Still processing include block */
896 if ((c = nextchar()) == 0) {
897 fprintf(stderr,"%s : EOF. Unterminated include block detected.\n", input_file);
898 FatalError();
899 return 0;
900 }
901 if (c == '}') {
902 yylval.id = header.get();
903 return(HBLOCK);
904 } else {
905 header << '%';
906 header << c;
907 yylen = 0;
908 state = 40;
909 }
910 break;
911
912 case 5: /* Maybe a double colon */
913
914 if (( c= nextchar()) == 0) return 0;
915 if ( c == ':') return DCOLON;
916 else {
917 retract(1);
918 return COLON;
919 }
920
921
922 case 60: /* shift operators */
923 if ((c = nextchar()) == 0) return (0);
924 if (c == '<') return LSHIFT;
925 else {
926 retract(1);
927 return LESSTHAN;
928 }
929 break;
930 case 61:
931 if ((c = nextchar()) == 0) return (0);
932 if (c == '>') return RSHIFT;
933 else {
934 retract(1);
935 return GREATERTHAN;
936 }
937 break;
938 case 7: /* Identifier */
939 if ((c = nextchar()) == 0) return(0);
940 if (isalnum(c) || (c == '_') || (c == '.') || (c == '$'))
941 // || (c == '.') || (c == '-'))
942 state = 7;
943 else if (c == '(') {
944 /* We might just be in a CPP macro definition. Better check */
945 if ((in_define) && (define_first_id)) {
946 /* Yep. We're going to ignore the rest of it */
947 skip_define();
948 define_first_id = 0;
949 return (MACRO);
950 } else {
951 retract(1);
952 define_first_id = 0;
953 return(ID);
954 }
955 } else {
956 retract(1);
957 define_first_id = 0;
958 return(ID);
959 }
960 break;
961 case 8: /* A numerical digit */
962 if ((c = nextchar()) == 0) return(0);
963 if (c == '.') {state = 81;}
964 else if ((c == 'e') || (c == 'E')) {state = 86;}
965 else if ((c == 'f') || (c == 'F')) {
966 yytext[yylen] = 0;
967 yylval.id = copy_string(yytext);
968 return(NUM_FLOAT);
969 }
970 else if (isdigit(c)) { state = 8;}
971 else if ((c == 'l') || (c == 'L')) {
972 state = 87;
973 } else if ((c == 'u') || (c == 'U')) {
974 state = 88;
975 } else {
976 retract(1);
977 yytext[yylen] = 0;
978 yylval.id = copy_string(yytext);
979 return(NUM_INT);
980 }
981 break;
982 case 81: /* A floating pointer number of some sort */
983 if ((c = nextchar()) == 0) return(0);
984 if (isdigit(c)) state = 81;
985 else if ((c == 'e') || (c == 'E')) state = 82;
986 else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) {
987 yytext[yylen] = 0;
988 yylval.id = copy_string(yytext);
989 return(NUM_FLOAT);
990 } else {
991 retract(1);
992 yytext[yylen] = 0;
993 yylval.id = copy_string(yytext);
994 return(NUM_FLOAT);
995 }
996 break;
997 case 82:
998 if ((c = nextchar()) == 0) return(0);
999 if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86;
1000 else {
1001 retract(2);
1002 yytext[yylen-1] = 0;
1003 yylval.id = copy_string(yytext);
1004 return(NUM_INT);
1005 }
1006 break;
1007 case 83:
1008 /* Might be a hexidecimal or octal number */
1009 if ((c = nextchar()) == 0) return(0);
1010 if (isdigit(c)) state = 84;
1011 else if ((c == 'x') || (c == 'X')) state = 85;
1012 else if (c == '.') state = 81;
1013 else if ((c == 'l') || (c == 'L')) {
1014 state = 87;
1015 } else if ((c == 'u') || (c == 'U')) {
1016 state = 88;
1017 } else {
1018 retract(1);
1019 yytext[yylen] = 0;
1020 yylval.id = copy_string(yytext);
1021 return(NUM_INT);
1022 }
1023 break;
1024 case 84:
1025 /* This is an octal number */
1026 if ((c = nextchar()) == 0) return (0);
1027 if (isdigit(c)) state = 84;
1028 else if ((c == 'l') || (c == 'L')) {
1029 state = 87;
1030 } else if ((c == 'u') || (c == 'U')) {
1031 state = 88;
1032 } else {
1033 retract(1);
1034 yytext[yylen] = 0;
1035 yylval.id = copy_string(yytext);
1036 return(NUM_INT);
1037 }
1038 break;
1039 case 85:
1040 /* This is an hex number */
1041 if ((c = nextchar()) == 0) return (0);
1042 if ((isdigit(c)) || (c=='a') || (c=='b') || (c=='c') ||
1043 (c=='d') || (c=='e') || (c=='f') || (c=='A') ||
1044 (c=='B') || (c=='C') || (c=='D') || (c=='E') ||
1045 (c=='F'))
1046 state = 85;
1047 else if ((c == 'l') || (c == 'L')) {
1048 state = 87;
1049 } else if ((c == 'u') || (c == 'U')) {
1050 state = 88;
1051 } else {
1052 retract(1);
1053 yytext[yylen] = 0;
1054 yylval.id = copy_string(yytext);
1055 return(NUM_INT);
1056 }
1057 break;
1058
1059 case 86:
1060 /* Rest of floating point number */
1061
1062 if ((c = nextchar()) == 0) return (0);
1063 if (isdigit(c)) state = 86;
1064 else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) {
1065 yytext[yylen] = 0;
1066 yylval.id = copy_string(yytext);
1067 return(NUM_FLOAT);
1068 } else {
1069 retract(1);
1070 yytext[yylen] = 0;
1071 yylval.id = copy_string(yytext);
1072 return(NUM_FLOAT);
1073 }
1074 /* Parse a character constant. ie. 'a' */
1075 break;
1076
1077 case 87 :
1078 /* A long integer of some sort */
1079 if ((c = nextchar()) == 0) return (0);
1080 if ((c == 'u') || (c == 'U')) {
1081 yytext[yylen] = 0;
1082 yylval.id = copy_string(yytext);
1083 return(NUM_ULONG);
1084 } else {
1085 retract(1);
1086 yytext[yylen] = 0;
1087 yylval.id = copy_string(yytext);
1088 return(NUM_LONG);
1089 }
1090
1091 case 88:
1092 /* An unsigned integer of some sort */
1093 if ((c = nextchar()) == 0) return (0);
1094 if ((c == 'l') || (c == 'L')) {
1095 yytext[yylen] = 0;
1096 yylval.id = copy_string(yytext);
1097 return(NUM_ULONG);
1098 } else {
1099 retract(1);
1100 yytext[yylen] = 0;
1101 yylval.id = copy_string(yytext);
1102 return(NUM_UNSIGNED);
1103 }
1104
1105 case 9:
1106 if ((c = nextchar()) == 0) return (0);
1107 if (c == '\'') {
1108 yytext[yylen-1] = 0;
1109 yylval.id = copy_string(yytext+1);
1110 return(CHARCONST);
1111 }
1112 break;
1113
1114 case 100:
1115 if ((c = nextchar()) == 0) return (0);
1116 if (isdigit(c)) state = 81;
1117 else {
1118 retract(1);
1119 return(PERIOD);
1120 }
1121 break;
1122 default:
1123 if (!Error) {
1124 fprintf(stderr,"%s : Line %d ::Illegal character '%c'=%d.\n",input_file, line_number,c,c);
1125 FatalError();
1126 }
1127 state = 0;
1128 Error = 1;
1129 return(ILLEGAL);
1130 }
1131 }
1132 }
1133
1134 static int check_typedef = 0;
1135
1136 void scanner_check_typedef() {
1137 check_typedef = 1;
1138 }
1139
1140 void scanner_ignore_typedef() {
1141 check_typedef = 0;
1142 }
1143
1144
1145 /**************************************************************
1146 * int yylex()
1147 *
1148 * Gets the lexene and returns tokens.
1149 *************************************************************/
1150
1151 extern "C" int yylex(void) {
1152
1153 int l;
1154
1155 if (!scan_init) {
1156 scanner_init();
1157 // if (LEX_in == NULL) LEX_in = stdin;
1158 // scanner_file(LEX_in);
1159 }
1160
1161 l = yylook();
1162
1163 /* We got some sort of non-white space object. We set the start_line
1164 variable unless it has already been set */
1165
1166 if (!start_line) {
1167 start_line = line_number;
1168 }
1169
1170 /* Copy the lexene */
1171
1172 yytext[yylen] = 0;
1173
1174 /* Hack to support ignoring of CPP macros */
1175
1176 if (l != DEFINE) {
1177 define_first_id = 0;
1178 }
1179
1180 switch(l) {
1181
1182 case ID:
1183
1184 /* Look for keywords now */
1185
1186 if (strcmp(yytext,"int") == 0) {
1187 yylval.type = new DataType;
1188 yylval.type->type = T_INT;
1189 strcpy(yylval.type->name,yytext);
1190 return(TYPE_INT);
1191 }
1192 if (strcmp(yytext,"double") == 0) {
1193 yylval.type = new DataType;
1194 yylval.type->type = T_DOUBLE;
1195 strcpy(yylval.type->name,yytext);
1196 return(TYPE_DOUBLE);
1197 }
1198 if (strcmp(yytext,"void") == 0) {
1199 yylval.type = new DataType;
1200 yylval.type->type = T_VOID;
1201 strcpy(yylval.type->name,yytext);
1202 return(TYPE_VOID);
1203 }
1204 if (strcmp(yytext,"char") == 0) {
1205 yylval.type = new DataType;
1206 yylval.type->type = T_CHAR;
1207 strcpy(yylval.type->name,yytext);
1208 return(TYPE_CHAR);
1209 }
1210 if (strcmp(yytext,"short") == 0) {
1211 yylval.type = new DataType;
1212 yylval.type->type = T_SHORT;
1213 strcpy(yylval.type->name,yytext);
1214 return(TYPE_SHORT);
1215 }
1216 if (strcmp(yytext,"long") == 0) {
1217 yylval.type = new DataType;
1218 yylval.type->type = T_LONG;
1219 strcpy(yylval.type->name,yytext);
1220 return(TYPE_LONG);
1221 }
1222 if (strcmp(yytext,"float") == 0) {
1223 yylval.type = new DataType;
1224 yylval.type->type = T_FLOAT;
1225 strcpy(yylval.type->name,yytext);
1226 return(TYPE_FLOAT);
1227 }
1228 if (strcmp(yytext,"signed") == 0) {
1229 yylval.type = new DataType;
1230 yylval.type->type = T_SINT;
1231 strcpy(yylval.type->name,yytext);
1232 return(TYPE_SIGNED);
1233 }
1234 if (strcmp(yytext,"unsigned") == 0) {
1235 yylval.type = new DataType;
1236 yylval.type->type = T_UINT;
1237 strcpy(yylval.type->name,yytext);
1238 return(TYPE_UNSIGNED);
1239 }
1240 if (strcmp(yytext,"bool") == 0) {
1241 yylval.type = new DataType;
1242 yylval.type->type = T_BOOL;
1243 strcpy(yylval.type->name,yytext);
1244 return(TYPE_BOOL);
1245 }
1246 // C++ keywords
1247
1248 if (CPlusPlus) {
1249 if (strcmp(yytext,"class") == 0) return(CLASS);
1250 if (strcmp(yytext,"private") == 0) return(PRIVATE);
1251 if (strcmp(yytext,"public") == 0) return(PUBLIC);
1252 if (strcmp(yytext,"protected") == 0) return(PROTECTED);
1253 if (strcmp(yytext,"friend") == 0) return(FRIEND);
1254 if (strcmp(yytext,"virtual") == 0) return(VIRTUAL);
1255 if (strcmp(yytext,"operator") == 0) return(OPERATOR);
1256 if (strcmp(yytext,"throw") == 0) return(THROW);
1257 if (strcmp(yytext,"inline") == 0) return(yylex());
1258 if (strcmp(yytext,"template") == 0) return(TEMPLATE);
1259 }
1260
1261 // Objective-C keywords
1262 if (ObjC) {
1263 if (strcmp(yytext,"@interface") == 0) return (OC_INTERFACE);
1264 if (strcmp(yytext,"@end") == 0) return (OC_END);
1265 if (strcmp(yytext,"@public") == 0) return (OC_PUBLIC);
1266 if (strcmp(yytext,"@private") == 0) return (OC_PRIVATE);
1267 if (strcmp(yytext,"@protected") == 0) return (OC_PROTECTED);
1268 if (strcmp(yytext,"@class") == 0) return(OC_CLASS);
1269 if (strcmp(yytext,"@implementation") == 0) return(OC_IMPLEMENT);
1270 if (strcmp(yytext,"@protocol") == 0) return(OC_PROTOCOL);
1271 }
1272
1273 // Misc keywords
1274
1275 if (strcmp(yytext,"static") == 0) return(STATIC);
1276 if (strcmp(yytext,"extern") == 0) return(EXTERN);
1277 if (strcmp(yytext,"const") == 0) return(CONST);
1278 if (strcmp(yytext,"struct") == 0) return(STRUCT);
1279 if (strcmp(yytext,"union") == 0) return(UNION);
1280 if (strcmp(yytext,"enum") == 0) return(ENUM);
1281 if (strcmp(yytext,"sizeof") == 0) return(SIZEOF);
1282 if (strcmp(yytext,"defined") == 0) return(DEFINED);
1283
1284 // Ignored keywords
1285
1286 if (strcmp(yytext,"volatile") == 0) return(yylex());
1287
1288 // SWIG directives
1289
1290 if (strcmp(yytext,"%module") == 0) return(MODULE);
1291 if (strcmp(yytext,"%init") == 0) return(INIT);
1292 if (strcmp(yytext,"%wrapper") == 0) return(WRAPPER);
1293 if (strcmp(yytext,"%readonly") == 0) return(READONLY);
1294 if (strcmp(yytext,"%readwrite") == 0) return(READWRITE);
1295 if (strcmp(yytext,"%name") == 0) return(NAME);
1296 if (strcmp(yytext,"%rename") == 0) return(RENAME);
1297 if (strcmp(yytext,"%include") == 0) return(INCLUDE);
1298 if (strcmp(yytext,"%extern") == 0) return(WEXTERN);
1299 if (strcmp(yytext,"%checkout") == 0) return(CHECKOUT);
1300 if (strcmp(yytext,"%val") == 0) return(CVALUE);
1301 if (strcmp(yytext,"%out") == 0) return(COUT);
1302
1303 if (strcmp(yytext,"%section") == 0) {
1304 yylval.ivalue = line_number;
1305 return(SECTION);
1306 }
1307 if (strcmp(yytext,"%subsection") == 0) {
1308 yylval.ivalue = line_number;
1309 return(SUBSECTION);
1310 }
1311 if (strcmp(yytext,"%subsubsection") == 0) {
1312 yylval.ivalue = line_number;
1313 return (SUBSUBSECTION);
1314 }
1315 if (strcmp(yytext,"%title") == 0) {
1316 yylval.ivalue = line_number;
1317 return(TITLE);
1318 }
1319 if (strcmp(yytext,"%style") == 0) return(STYLE);
1320 if (strcmp(yytext,"%localstyle") == 0) return(LOCALSTYLE);
1321 if (strcmp(yytext,"%typedef") == 0) {
1322 yylval.ivalue = 1;
1323 return(TYPEDEF);
1324 }
1325 if (strcmp(yytext,"typedef") == 0) {
1326 yylval.ivalue = 0;
1327 return(TYPEDEF);
1328 }
1329 if (strcmp(yytext,"%alpha") == 0) return(ALPHA_MODE);
1330 if (strcmp(yytext,"%raw") == 0) return(RAW_MODE);
1331 if (strcmp(yytext,"%text") == 0) return(TEXT);
1332 if (strcmp(yytext,"%native") == 0) return(NATIVE);
1333 if (strcmp(yytext,"%disabledoc") == 0) return(DOC_DISABLE);
1334 if (strcmp(yytext,"%enabledoc") == 0) return(DOC_ENABLE);
1335 if (strcmp(yytext,"%ifdef") == 0) return(IFDEF);
1336 if (strcmp(yytext,"%else") == 0) return(ELSE);
1337 if (strcmp(yytext,"%ifndef") == 0) return(IFNDEF);
1338 if (strcmp(yytext,"%endif") == 0) return(ENDIF);
1339 if (strcmp(yytext,"%if") == 0) return(IF);
1340 if (strcmp(yytext,"%elif") == 0) return(ELIF);
1341 if (strcmp(yytext,"%pragma") == 0) return(PRAGMA);
1342 if (strcmp(yytext,"%addmethods") == 0) return(ADDMETHODS);
1343 if (strcmp(yytext,"%inline") == 0) return(INLINE);
1344 if (strcmp(yytext,"%typemap") == 0) return(TYPEMAP);
1345 if (strcmp(yytext,"%except") == 0) return(EXCEPT);
1346 if (strcmp(yytext,"%import") == 0) return(IMPORT);
1347 if (strcmp(yytext,"%echo") == 0) return(ECHO);
1348 if (strcmp(yytext,"%new") == 0) return(NEW);
1349 if (strcmp(yytext,"%apply") == 0) return(APPLY);
1350 if (strcmp(yytext,"%clear") == 0) return(CLEAR);
1351 if (strcmp(yytext,"%doconly") == 0) return(DOCONLY);
1352
1353 // Have an unknown identifier, as a last step, we'll
1354 // do a typedef lookup on it.
1355
1356 if (check_typedef) {
1357 if (DataType::is_typedef(yytext)) {
1358 yylval.type = new DataType;
1359 yylval.type->type = T_USER;
1360 strcpy(yylval.type->name,yytext);
1361 yylval.type->typedef_resolve();
1362 return(TYPE_TYPEDEF);
1363 }
1364 }
1365
1366 yylval.id = copy_string(yytext);
1367 return(ID);
1368 default:
1369 return(l);
1370 }
1371 }
1372
1373 // --------------------------------------------------------------
1374 // scanner_clear_start()
1375 //
1376 // Clears the start of a declaration
1377 // --------------------------------------------------------------
1378
1379 void scanner_clear_start() {
1380 start_line = 0;
1381 }