]>
Commit | Line | Data |
---|---|---|
c90f71dd RD |
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 | } |