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