1/* ----------------------------------------------------------------------------- 2 * See the LICENSE file for information on copyright, usage and redistribution 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. 4 * 5 * scanner.c 6 * 7 * SWIG tokenizer. This file is a wrapper around the generic C scanner 8 * found in Swig/scanner.c. Extra logic is added both to accomodate the 9 * bison-based grammar and certain peculiarities of C++ parsing (e.g., 10 * operator overloading, typedef resolution, etc.). This code also splits 11 * C identifiers up into keywords and SWIG directives. 12 * ----------------------------------------------------------------------------- */ 13 14char cvsroot_cscanner_c[] = "$Id: cscanner.c 11123 2009-02-08 22:30:10Z wsfulton $"; 15 16#include "cparse.h" 17#include "parser.h" 18#include <string.h> 19#include <ctype.h> 20 21/* Scanner object */ 22static Scanner *scan = 0; 23 24/* Global string containing C code. Used by the parser to grab code blocks */ 25String *scanner_ccode = 0; 26 27/* The main file being parsed */ 28static String *main_input_file = 0; 29 30/* Error reporting/location information */ 31int cparse_line = 1; 32String *cparse_file = 0; 33int cparse_start_line = 0; 34 35/* C++ mode */ 36int cparse_cplusplus = 0; 37 38/* Private vars */ 39static int scan_init = 0; 40static int num_brace = 0; 41static int last_brace = 0; 42static int last_id = 0; 43static int rename_active = 0; 44static int expanding_macro = 0; 45static int follow_locators = 0; 46 47/* ----------------------------------------------------------------------------- 48 * Swig_cparse_cplusplus() 49 * ----------------------------------------------------------------------------- */ 50 51void Swig_cparse_cplusplus(int v) { 52 cparse_cplusplus = v; 53} 54 55/* ---------------------------------------------------------------------- 56 * locator() 57 * 58 * Support for locator strings. These are strings of the form 59 * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They 60 * are primarily used for macro line number reporting 61 * ---------------------------------------------------------------------- */ 62 63typedef struct Locator { 64 String *filename; 65 int line_number; 66 struct Locator *next; 67} Locator; 68 69static Locator *locs = 0; 70 71/* we just use the locator to mark when active/deactive the linecounting */ 72 73static void scanner_locator(String *loc) { 74 if (!follow_locators) { 75 if (Equal(loc, "/*@SWIG@*/")) { 76 /* End locator. */ 77 if (expanding_macro) 78 --expanding_macro; 79 } else { 80 /* Begin locator. */ 81 ++expanding_macro; 82 } 83 /* Freeze line number processing in Scanner */ 84 Scanner_freeze_line(scan,expanding_macro); 85 } else { 86 int c; 87 Locator *l; 88 Seek(loc, 7, SEEK_SET); 89 c = Getc(loc); 90 if (c == '@') { 91 /* Empty locator. We pop the last location off */ 92 if (locs) { 93 Scanner_set_location(scan,locs->filename,locs->line_number); 94 cparse_file = locs->filename; 95 cparse_line = locs->line_number; 96 l = locs->next; 97 free(locs); 98 locs = l; 99 } 100 return; 101 } 102 103 /* We're going to push a new location */ 104 l = (Locator *) malloc(sizeof(Locator)); 105 l->filename = cparse_file; 106 l->line_number = cparse_line; 107 l->next = locs; 108 locs = l; 109 110 /* Now, parse the new location out of the locator string */ 111 { 112 String *fn = NewStringEmpty(); 113 /* Putc(c, fn); */ 114 115 while ((c = Getc(loc)) != EOF) { 116 if ((c == '@') || (c == ',')) 117 break; 118 Putc(c, fn); 119 } 120 cparse_file = Swig_copy_string(Char(fn)); 121 Clear(fn); 122 cparse_line = 1; 123 /* Get the line number */ 124 while ((c = Getc(loc)) != EOF) { 125 if ((c == '@') || (c == ',')) 126 break; 127 Putc(c, fn); 128 } 129 cparse_line = atoi(Char(fn)); 130 Clear(fn); 131 132 /* Get the rest of it */ 133 while ((c = Getc(loc)) != EOF) { 134 if (c == '@') 135 break; 136 Putc(c, fn); 137 } 138 /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */ 139 Scanner_set_location(scan,cparse_file,cparse_line); 140 Delete(fn); 141 } 142 } 143} 144 145void Swig_cparse_follow_locators(int v) { 146 follow_locators = v; 147} 148 149 150/* ---------------------------------------------------------------------------- 151 * scanner_init() 152 * 153 * Initialize buffers 154 * ------------------------------------------------------------------------- */ 155 156void scanner_init() { 157 scan = NewScanner(); 158 Scanner_idstart(scan,"%"); 159 scan_init = 1; 160 scanner_ccode = NewStringEmpty(); 161} 162 163/* ---------------------------------------------------------------------------- 164 * scanner_file(DOHFile *f) 165 * 166 * Start reading from new file 167 * ------------------------------------------------------------------------- */ 168void scanner_file(DOHFile * f) { 169 if (!scan_init) scanner_init(); 170 Scanner_clear(scan); 171 Scanner_push(scan,f); 172} 173 174/* ---------------------------------------------------------------------------- 175 * start_inline(char *text, int line) 176 * 177 * Take a chunk of text and recursively feed it back into the scanner. Used 178 * by the %inline directive. 179 * ------------------------------------------------------------------------- */ 180 181void start_inline(char *text, int line) { 182 String *stext = NewString(text); 183 184 Seek(stext,0,SEEK_SET); 185 Setfile(stext,cparse_file); 186 Setline(stext,line); 187 Scanner_push(scan,stext); 188 Delete(stext); 189} 190 191/* ----------------------------------------------------------------------------- 192 * skip_balanced() 193 * 194 * Skips a piece of code enclosed in begin/end symbols such as '{...}' or 195 * (...). Ignores symbols inside comments or strings. 196 * ----------------------------------------------------------------------------- */ 197 198void skip_balanced(int startchar, int endchar) { 199 Clear(scanner_ccode); 200 201 if (Scanner_skip_balanced(scan,startchar,endchar) < 0) { 202 Swig_error(Scanner_file(scan),Scanner_errline(scan), "Missing '%c'. Reached end of input.\n", endchar); 203 return; 204 } 205 206 cparse_line = Scanner_line(scan); 207 cparse_file = Scanner_file(scan); 208 209 Append(scanner_ccode, Scanner_text(scan)); 210 if (endchar == '}') 211 num_brace--; 212 return; 213} 214 215/* ---------------------------------------------------------------------------- 216 * void skip_decl(void) 217 * 218 * This tries to skip over an entire declaration. For example 219 * 220 * friend ostream& operator<<(ostream&, const char *s); 221 * 222 * or 223 * friend ostream& operator<<(ostream&, const char *s) { }; 224 * 225 * ------------------------------------------------------------------------- */ 226 227void skip_decl(void) { 228 int tok; 229 int done = 0; 230 int start_line = Scanner_line(scan); 231 232 while (!done) { 233 tok = Scanner_token(scan); 234 if (tok == 0) { 235 if (!Swig_error_count()) { 236 Swig_error(cparse_file, start_line, "Missing semicolon. Reached end of input.\n"); 237 } 238 return; 239 } 240 if (tok == SWIG_TOKEN_LBRACE) { 241 if (Scanner_skip_balanced(scan,'{','}') < 0) { 242 Swig_error(cparse_file, start_line, "Missing '}'. Reached end of input.\n"); 243 } 244 break; 245 } 246 if (tok == SWIG_TOKEN_SEMI) { 247 done = 1; 248 } 249 } 250 cparse_file = Scanner_file(scan); 251 cparse_line = Scanner_line(scan); 252} 253 254/* ---------------------------------------------------------------------------- 255 * int yylook() 256 * 257 * Lexical scanner. 258 * ------------------------------------------------------------------------- */ 259 260int yylook(void) { 261 262 int tok = 0; 263 264 while (1) { 265 if ((tok = Scanner_token(scan)) == 0) 266 return 0; 267 if (tok == SWIG_TOKEN_ERROR) 268 return 0; 269 cparse_start_line = Scanner_start_line(scan); 270 cparse_line = Scanner_line(scan); 271 cparse_file = Scanner_file(scan); 272 273 switch(tok) { 274 case SWIG_TOKEN_ID: 275 return ID; 276 case SWIG_TOKEN_LPAREN: 277 return LPAREN; 278 case SWIG_TOKEN_RPAREN: 279 return RPAREN; 280 case SWIG_TOKEN_SEMI: 281 return SEMI; 282 case SWIG_TOKEN_COMMA: 283 return COMMA; 284 case SWIG_TOKEN_STAR: 285 return STAR; 286 case SWIG_TOKEN_RBRACE: 287 num_brace--; 288 if (num_brace < 0) { 289 Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '}'\n"); 290 num_brace = 0; 291 } else { 292 return RBRACE; 293 } 294 break; 295 case SWIG_TOKEN_LBRACE: 296 last_brace = num_brace; 297 num_brace++; 298 return LBRACE; 299 case SWIG_TOKEN_EQUAL: 300 return EQUAL; 301 case SWIG_TOKEN_EQUALTO: 302 return EQUALTO; 303 case SWIG_TOKEN_PLUS: 304 return PLUS; 305 case SWIG_TOKEN_MINUS: 306 return MINUS; 307 case SWIG_TOKEN_SLASH: 308 return SLASH; 309 case SWIG_TOKEN_AND: 310 return AND; 311 case SWIG_TOKEN_LAND: 312 return LAND; 313 case SWIG_TOKEN_OR: 314 return OR; 315 case SWIG_TOKEN_LOR: 316 return LOR; 317 case SWIG_TOKEN_XOR: 318 return XOR; 319 case SWIG_TOKEN_NOT: 320 return NOT; 321 case SWIG_TOKEN_LNOT: 322 return LNOT; 323 case SWIG_TOKEN_NOTEQUAL: 324 return NOTEQUALTO; 325 case SWIG_TOKEN_LBRACKET: 326 return LBRACKET; 327 case SWIG_TOKEN_RBRACKET: 328 return RBRACKET; 329 case SWIG_TOKEN_QUESTION: 330 return QUESTIONMARK; 331 case SWIG_TOKEN_LESSTHAN: 332 return LESSTHAN; 333 case SWIG_TOKEN_LTEQUAL: 334 return LESSTHANOREQUALTO; 335 case SWIG_TOKEN_LSHIFT: 336 return LSHIFT; 337 case SWIG_TOKEN_GREATERTHAN: 338 return GREATERTHAN; 339 case SWIG_TOKEN_GTEQUAL: 340 return GREATERTHANOREQUALTO; 341 case SWIG_TOKEN_RSHIFT: 342 return RSHIFT; 343 case SWIG_TOKEN_PERIOD: 344 return PERIOD; 345 case SWIG_TOKEN_MODULO: 346 return MODULO; 347 case SWIG_TOKEN_COLON: 348 return COLON; 349 case SWIG_TOKEN_DCOLONSTAR: 350 return DSTAR; 351 352 case SWIG_TOKEN_DCOLON: 353 { 354 int nexttok = Scanner_token(scan); 355 if (nexttok == SWIG_TOKEN_STAR) { 356 return DSTAR; 357 } else if (nexttok == SWIG_TOKEN_NOT) { 358 return DCNOT; 359 } else { 360 Scanner_pushtoken(scan,nexttok,Scanner_text(scan)); 361 if (!last_id) { 362 scanner_next_token(DCOLON); 363 return NONID; 364 } else { 365 return DCOLON; 366 } 367 } 368 } 369 break; 370 371 /* Look for multi-character sequences */ 372 373 case SWIG_TOKEN_RSTRING: 374 yylval.type = NewString(Scanner_text(scan)); 375 return TYPE_RAW; 376 377 case SWIG_TOKEN_STRING: 378 yylval.id = Swig_copy_string(Char(Scanner_text(scan))); 379 return STRING; 380 381 case SWIG_TOKEN_CHAR: 382 yylval.str = NewString(Scanner_text(scan)); 383 if (Len(yylval.str) == 0) { 384 Swig_error(cparse_file, cparse_line, "Empty character constant\n"); 385 Printf(stdout,"%d\n", Len(Scanner_text(scan))); 386 } 387 return CHARCONST; 388 389 /* Numbers */ 390 391 case SWIG_TOKEN_INT: 392 return NUM_INT; 393 394 case SWIG_TOKEN_UINT: 395 return NUM_UNSIGNED; 396 397 case SWIG_TOKEN_LONG: 398 return NUM_LONG; 399 400 case SWIG_TOKEN_ULONG: 401 return NUM_ULONG; 402 403 case SWIG_TOKEN_LONGLONG: 404 return NUM_LONGLONG; 405 406 case SWIG_TOKEN_ULONGLONG: 407 return NUM_ULONGLONG; 408 409 case SWIG_TOKEN_DOUBLE: 410 case SWIG_TOKEN_FLOAT: 411 return NUM_FLOAT; 412 413 case SWIG_TOKEN_POUND: 414 Scanner_skip_line(scan); 415 yylval.id = Swig_copy_string(Char(Scanner_text(scan))); 416 return POUND; 417 break; 418 419 case SWIG_TOKEN_CODEBLOCK: 420 yylval.str = NewString(Scanner_text(scan)); 421 return HBLOCK; 422 423 case SWIG_TOKEN_COMMENT: 424 { 425 String *cmt = Scanner_text(scan); 426 char *loc = Char(cmt); 427 if ((strncmp(loc,"/*@SWIG",7) == 0) && (loc[Len(cmt)-3] == '@')) { 428 scanner_locator(cmt); 429 } 430 } 431 break; 432 case SWIG_TOKEN_ENDLINE: 433 break; 434 case SWIG_TOKEN_BACKSLASH: 435 break; 436 default: 437 Swig_error(cparse_file, cparse_line, "Illegal token '%s'.\n", Scanner_text(scan)); 438 return (ILLEGAL); 439 } 440 } 441} 442 443static int check_typedef = 0; 444 445void scanner_set_location(String *file, int line) { 446 Scanner_set_location(scan,file,line-1); 447} 448 449void scanner_check_typedef() { 450 check_typedef = 1; 451} 452 453void scanner_ignore_typedef() { 454 check_typedef = 0; 455} 456 457void scanner_last_id(int x) { 458 last_id = x; 459} 460 461void scanner_clear_rename() { 462 rename_active = 0; 463} 464 465/* Used to push a ficticious token into the scanner */ 466static int next_token = 0; 467void scanner_next_token(int tok) { 468 next_token = tok; 469} 470 471void scanner_set_main_input_file(String *file) { 472 main_input_file = file; 473} 474 475String *scanner_get_main_input_file() { 476 return main_input_file; 477} 478 479/* ---------------------------------------------------------------------------- 480 * int yylex() 481 * 482 * Gets the lexene and returns tokens. 483 * ------------------------------------------------------------------------- */ 484 485int yylex(void) { 486 487 int l; 488 char *yytext; 489 490 if (!scan_init) { 491 scanner_init(); 492 } 493 494 if (next_token) { 495 l = next_token; 496 next_token = 0; 497 return l; 498 } 499 500 l = yylook(); 501 502 /* Printf(stdout, "%s:%d:::%d: '%s'\n", cparse_file, cparse_line, l, Scanner_text(scan)); */ 503 504 if (l == NONID) { 505 last_id = 1; 506 } else { 507 last_id = 0; 508 } 509 510 /* We got some sort of non-white space object. We set the start_line 511 variable unless it has already been set */ 512 513 if (!cparse_start_line) { 514 cparse_start_line = cparse_line; 515 } 516 517 /* Copy the lexene */ 518 519 switch (l) { 520 521 case NUM_INT: 522 case NUM_FLOAT: 523 case NUM_ULONG: 524 case NUM_LONG: 525 case NUM_UNSIGNED: 526 case NUM_LONGLONG: 527 case NUM_ULONGLONG: 528 if (l == NUM_INT) 529 yylval.dtype.type = T_INT; 530 if (l == NUM_FLOAT) 531 yylval.dtype.type = T_DOUBLE; 532 if (l == NUM_ULONG) 533 yylval.dtype.type = T_ULONG; 534 if (l == NUM_LONG) 535 yylval.dtype.type = T_LONG; 536 if (l == NUM_UNSIGNED) 537 yylval.dtype.type = T_UINT; 538 if (l == NUM_LONGLONG) 539 yylval.dtype.type = T_LONGLONG; 540 if (l == NUM_ULONGLONG) 541 yylval.dtype.type = T_ULONGLONG; 542 yylval.dtype.val = NewString(Scanner_text(scan)); 543 yylval.dtype.bitfield = 0; 544 yylval.dtype.throws = 0; 545 return (l); 546 547 case ID: 548 yytext = Char(Scanner_text(scan)); 549 if (yytext[0] != '%') { 550 /* Look for keywords now */ 551 552 if (strcmp(yytext, "int") == 0) { 553 yylval.type = NewSwigType(T_INT); 554 return (TYPE_INT); 555 } 556 if (strcmp(yytext, "double") == 0) { 557 yylval.type = NewSwigType(T_DOUBLE); 558 return (TYPE_DOUBLE); 559 } 560 if (strcmp(yytext, "void") == 0) { 561 yylval.type = NewSwigType(T_VOID); 562 return (TYPE_VOID); 563 } 564 if (strcmp(yytext, "char") == 0) { 565 yylval.type = NewSwigType(T_CHAR); 566 return (TYPE_CHAR); 567 } 568 if (strcmp(yytext, "wchar_t") == 0) { 569 yylval.type = NewSwigType(T_WCHAR); 570 return (TYPE_WCHAR); 571 } 572 if (strcmp(yytext, "short") == 0) { 573 yylval.type = NewSwigType(T_SHORT); 574 return (TYPE_SHORT); 575 } 576 if (strcmp(yytext, "long") == 0) { 577 yylval.type = NewSwigType(T_LONG); 578 return (TYPE_LONG); 579 } 580 if (strcmp(yytext, "float") == 0) { 581 yylval.type = NewSwigType(T_FLOAT); 582 return (TYPE_FLOAT); 583 } 584 if (strcmp(yytext, "signed") == 0) { 585 yylval.type = NewSwigType(T_INT); 586 return (TYPE_SIGNED); 587 } 588 if (strcmp(yytext, "unsigned") == 0) { 589 yylval.type = NewSwigType(T_UINT); 590 return (TYPE_UNSIGNED); 591 } 592 if (strcmp(yytext, "bool") == 0) { 593 yylval.type = NewSwigType(T_BOOL); 594 return (TYPE_BOOL); 595 } 596 597 /* Non ISO (Windows) C extensions */ 598 if (strcmp(yytext, "__int8") == 0) { 599 yylval.type = NewString(yytext); 600 return (TYPE_NON_ISO_INT8); 601 } 602 if (strcmp(yytext, "__int16") == 0) { 603 yylval.type = NewString(yytext); 604 return (TYPE_NON_ISO_INT16); 605 } 606 if (strcmp(yytext, "__int32") == 0) { 607 yylval.type = NewString(yytext); 608 return (TYPE_NON_ISO_INT32); 609 } 610 if (strcmp(yytext, "__int64") == 0) { 611 yylval.type = NewString(yytext); 612 return (TYPE_NON_ISO_INT64); 613 } 614 615 /* C++ keywords */ 616 if (cparse_cplusplus) { 617 if (strcmp(yytext, "and") == 0) 618 return (LAND); 619 if (strcmp(yytext, "or") == 0) 620 return (LOR); 621 if (strcmp(yytext, "not") == 0) 622 return (LNOT); 623 if (strcmp(yytext, "class") == 0) 624 return (CLASS); 625 if (strcmp(yytext, "private") == 0) 626 return (PRIVATE); 627 if (strcmp(yytext, "public") == 0) 628 return (PUBLIC); 629 if (strcmp(yytext, "protected") == 0) 630 return (PROTECTED); 631 if (strcmp(yytext, "friend") == 0) 632 return (FRIEND); 633 if (strcmp(yytext, "virtual") == 0) 634 return (VIRTUAL); 635 if (strcmp(yytext, "operator") == 0) { 636 int nexttok; 637 String *s = NewString("operator "); 638 639 /* If we have an operator, we have to collect the operator symbol and attach it to 640 the operator identifier. To do this, we need to scan ahead by several tokens. 641 Cases include: 642 643 (1) If the next token is an operator as determined by Scanner_isoperator(), 644 it means that the operator applies to one of the standard C++ mathematical, 645 assignment, or logical operator symbols (e.g., '+','<=','==','&', etc.) 646 In this case, we merely append the symbol text to the operator string above. 647 648 (2) If the next token is (, we look for ). This is operator (). 649 (3) If the next token is [, we look for ]. This is operator []. 650 (4) If the next token is an identifier. The operator is possibly a conversion operator. 651 (a) Must check for special case new[] and delete[] 652 653 Error handling is somewhat tricky here. We'll try to back out gracefully if we can. 654 655 */ 656 657 nexttok = Scanner_token(scan); 658 if (Scanner_isoperator(nexttok)) { 659 /* One of the standard C/C++ symbolic operators */ 660 Append(s,Scanner_text(scan)); 661 yylval.str = s; 662 return OPERATOR; 663 } else if (nexttok == SWIG_TOKEN_LPAREN) { 664 /* Function call operator. The next token MUST be a RPAREN */ 665 nexttok = Scanner_token(scan); 666 if (nexttok != SWIG_TOKEN_RPAREN) { 667 Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n"); 668 } else { 669 Append(s,"()"); 670 yylval.str = s; 671 return OPERATOR; 672 } 673 } else if (nexttok == SWIG_TOKEN_LBRACKET) { 674 /* Array access operator. The next token MUST be a RBRACKET */ 675 nexttok = Scanner_token(scan); 676 if (nexttok != SWIG_TOKEN_RBRACKET) { 677 Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n"); 678 } else { 679 Append(s,"[]"); 680 yylval.str = s; 681 return OPERATOR; 682 } 683 } else if (nexttok == SWIG_TOKEN_ID) { 684 /* We have an identifier. This could be any number of things. It could be a named version of 685 an operator (e.g., 'and_eq') or it could be a conversion operator. To deal with this, we're 686 going to read tokens until we encounter a ( or ;. Some care is needed for formatting. */ 687 int needspace = 1; 688 int termtoken = 0; 689 const char *termvalue = 0; 690 691 Append(s,Scanner_text(scan)); 692 while (1) { 693 694 nexttok = Scanner_token(scan); 695 if (nexttok <= 0) { 696 Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n"); 697 } 698 if (nexttok == SWIG_TOKEN_LPAREN) { 699 termtoken = SWIG_TOKEN_LPAREN; 700 termvalue = "("; 701 break; 702 } else if (nexttok == SWIG_TOKEN_CODEBLOCK) { 703 termtoken = SWIG_TOKEN_CODEBLOCK; 704 termvalue = Char(Scanner_text(scan)); 705 break; 706 } else if (nexttok == SWIG_TOKEN_LBRACE) { 707 termtoken = SWIG_TOKEN_LBRACE; 708 termvalue = "{"; 709 break; 710 } else if (nexttok == SWIG_TOKEN_SEMI) { 711 termtoken = SWIG_TOKEN_SEMI; 712 termvalue = ";"; 713 break; 714 } else if (nexttok == SWIG_TOKEN_STRING) { 715 termtoken = SWIG_TOKEN_STRING; 716 termvalue = Swig_copy_string(Char(Scanner_text(scan))); 717 break; 718 } else if (nexttok == SWIG_TOKEN_ID) { 719 if (needspace) { 720 Append(s," "); 721 } 722 Append(s,Scanner_text(scan)); 723 } else { 724 Append(s,Scanner_text(scan)); 725 needspace = 0; 726 } 727 } 728 yylval.str = s; 729 if (!rename_active) { 730 String *cs; 731 char *t = Char(s) + 9; 732 if (!((strcmp(t, "new") == 0) 733 || (strcmp(t, "delete") == 0) 734 || (strcmp(t, "new[]") == 0) 735 || (strcmp(t, "delete[]") == 0) 736 || (strcmp(t, "and") == 0) 737 || (strcmp(t, "and_eq") == 0) 738 || (strcmp(t, "bitand") == 0) 739 || (strcmp(t, "bitor") == 0) 740 || (strcmp(t, "compl") == 0) 741 || (strcmp(t, "not") == 0) 742 || (strcmp(t, "not_eq") == 0) 743 || (strcmp(t, "or") == 0) 744 || (strcmp(t, "or_eq") == 0) 745 || (strcmp(t, "xor") == 0) 746 || (strcmp(t, "xor_eq") == 0) 747 )) { 748 /* retract(strlen(t)); */ 749 750 /* The operator is a conversion operator. In order to deal with this, we need to feed the 751 type information back into the parser. For now this is a hack. Needs to be cleaned up later. */ 752 cs = NewString(t); 753 if (termtoken) Append(cs,termvalue); 754 Seek(cs,0,SEEK_SET); 755 Setline(cs,cparse_line); 756 Setfile(cs,cparse_file); 757 Scanner_push(scan,cs); 758 Delete(cs); 759 return COPERATOR; 760 } 761 } 762 if (termtoken) 763 Scanner_pushtoken(scan, termtoken, termvalue); 764 return (OPERATOR); 765 } 766 } 767 if (strcmp(yytext, "throw") == 0) 768 return (THROW); 769 if (strcmp(yytext, "try") == 0) 770 return (yylex()); 771 if (strcmp(yytext, "catch") == 0) 772 return (CATCH); 773 if (strcmp(yytext, "inline") == 0) 774 return (yylex()); 775 if (strcmp(yytext, "mutable") == 0) 776 return (yylex()); 777 if (strcmp(yytext, "explicit") == 0) 778 return (EXPLICIT); 779 if (strcmp(yytext, "export") == 0) 780 return (yylex()); 781 if (strcmp(yytext, "typename") == 0) 782 return (TYPENAME); 783 if (strcmp(yytext, "template") == 0) { 784 yylval.ivalue = cparse_line; 785 return (TEMPLATE); 786 } 787 if (strcmp(yytext, "delete") == 0) { 788 return (DELETE_KW); 789 } 790 if (strcmp(yytext, "using") == 0) { 791 return (USING); 792 } 793 if (strcmp(yytext, "namespace") == 0) { 794 return (NAMESPACE); 795 } 796 } else { 797 if (strcmp(yytext, "class") == 0) { 798 Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n"); 799 } 800 if (strcmp(yytext, "complex") == 0) { 801 yylval.type = NewSwigType(T_COMPLEX); 802 return (TYPE_COMPLEX); 803 } 804 if (strcmp(yytext, "restrict") == 0) 805 return (yylex()); 806 } 807 808 /* Misc keywords */ 809 810 if (strcmp(yytext, "extern") == 0) 811 return (EXTERN); 812 if (strcmp(yytext, "const") == 0) 813 return (CONST_QUAL); 814 if (strcmp(yytext, "static") == 0) 815 return (STATIC); 816 if (strcmp(yytext, "struct") == 0) 817 return (STRUCT); 818 if (strcmp(yytext, "union") == 0) 819 return (UNION); 820 if (strcmp(yytext, "enum") == 0) 821 return (ENUM); 822 if (strcmp(yytext, "sizeof") == 0) 823 return (SIZEOF); 824 825 if (strcmp(yytext, "typedef") == 0) { 826 yylval.ivalue = 0; 827 return (TYPEDEF); 828 } 829 830 /* Ignored keywords */ 831 832 if (strcmp(yytext, "volatile") == 0) 833 return (VOLATILE); 834 if (strcmp(yytext, "register") == 0) 835 return (REGISTER); 836 if (strcmp(yytext, "inline") == 0) 837 return (yylex()); 838 839 /* SWIG directives */ 840 } else { 841 if (strcmp(yytext, "%module") == 0) 842 return (MODULE); 843 if (strcmp(yytext, "%insert") == 0) 844 return (INSERT); 845 if (strcmp(yytext, "%name") == 0) 846 return (NAME); 847 if (strcmp(yytext, "%rename") == 0) { 848 rename_active = 1; 849 return (RENAME); 850 } 851 if (strcmp(yytext, "%namewarn") == 0) { 852 rename_active = 1; 853 return (NAMEWARN); 854 } 855 if (strcmp(yytext, "%includefile") == 0) 856 return (INCLUDE); 857 if (strcmp(yytext, "%val") == 0) { 858 Swig_warning(WARN_DEPRECATED_VAL, cparse_file, cparse_line, "%%val directive deprecated (ignored).\n"); 859 return (yylex()); 860 } 861 if (strcmp(yytext, "%out") == 0) { 862 Swig_warning(WARN_DEPRECATED_OUT, cparse_file, cparse_line, "%%out directive deprecated (ignored).\n"); 863 return (yylex()); 864 } 865 if (strcmp(yytext, "%constant") == 0) 866 return (CONSTANT); 867 if (strcmp(yytext, "%typedef") == 0) { 868 yylval.ivalue = 1; 869 return (TYPEDEF); 870 } 871 if (strcmp(yytext, "%native") == 0) 872 return (NATIVE); 873 if (strcmp(yytext, "%pragma") == 0) 874 return (PRAGMA); 875 if (strcmp(yytext, "%extend") == 0) 876 return (EXTEND); 877 if (strcmp(yytext, "%fragment") == 0) 878 return (FRAGMENT); 879 if (strcmp(yytext, "%inline") == 0) 880 return (INLINE); 881 if (strcmp(yytext, "%typemap") == 0) 882 return (TYPEMAP); 883 if (strcmp(yytext, "%feature") == 0) { 884 /* The rename_active indicates we don't need the information of the 885 * following function's return type. This applied for %rename, so do 886 * %feature. 887 */ 888 rename_active = 1; 889 return (FEATURE); 890 } 891 if (strcmp(yytext, "%except") == 0) 892 return (EXCEPT); 893 if (strcmp(yytext, "%importfile") == 0) 894 return (IMPORT); 895 if (strcmp(yytext, "%echo") == 0) 896 return (ECHO); 897 if (strcmp(yytext, "%apply") == 0) 898 return (APPLY); 899 if (strcmp(yytext, "%clear") == 0) 900 return (CLEAR); 901 if (strcmp(yytext, "%types") == 0) 902 return (TYPES); 903 if (strcmp(yytext, "%parms") == 0) 904 return (PARMS); 905 if (strcmp(yytext, "%varargs") == 0) 906 return (VARARGS); 907 if (strcmp(yytext, "%template") == 0) { 908 return (SWIGTEMPLATE); 909 } 910 if (strcmp(yytext, "%warn") == 0) 911 return (WARN); 912 } 913 /* Have an unknown identifier, as a last step, we'll do a typedef lookup on it. */ 914 915 /* Need to fix this */ 916 if (check_typedef) { 917 if (SwigType_istypedef(yytext)) { 918 yylval.type = NewString(yytext); 919 return (TYPE_TYPEDEF); 920 } 921 } 922 yylval.id = Swig_copy_string(yytext); 923 last_id = 1; 924 return (ID); 925 case POUND: 926 return yylex(); 927 default: 928 return (l); 929 } 930} 931