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 * cpp.c 6 * 7 * An implementation of a C preprocessor plus some support for additional 8 * SWIG directives. 9 * 10 * - SWIG directives such as %include, %extern, and %import are handled 11 * - A new macro %define ... %enddef can be used for multiline macros 12 * - No preprocessing is performed in %{ ... %} blocks 13 * - Lines beginning with %# are stripped down to #... and passed through. 14 * ----------------------------------------------------------------------------- */ 15 16char cvsroot_cpp_c[] = "$Id: cpp.c 11098 2009-01-30 10:32:59Z bhy $"; 17 18#include "swig.h" 19#include "preprocessor.h" 20#include <ctype.h> 21 22static Hash *cpp = 0; /* C preprocessor data */ 23static int include_all = 0; /* Follow all includes */ 24static int ignore_missing = 0; 25static int import_all = 0; /* Follow all includes, but as %import statements */ 26static int imported_depth = 0; /* Depth of %imported files */ 27static int single_include = 1; /* Only include each file once */ 28static Hash *included_files = 0; 29static List *dependencies = 0; 30static Scanner *id_scan = 0; 31static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */ 32 33/* Test a character to see if it starts an identifier */ 34#define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$')) 35 36/* Test a character to see if it valid in an identifier (after the first letter) */ 37#define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$')) 38 39DOH *Preprocessor_replace(DOH *); 40 41/* Skip whitespace */ 42static void skip_whitespace(String *s, String *out) { 43 int c; 44 while ((c = Getc(s)) != EOF) { 45 if (!isspace(c)) { 46 Ungetc(c, s); 47 break; 48 } else if (out) 49 Putc(c, out); 50 } 51} 52 53/* Skip to a specified character taking line breaks into account */ 54static int skip_tochar(String *s, int ch, String *out) { 55 int c; 56 while ((c = Getc(s)) != EOF) { 57 if (out) 58 Putc(c, out); 59 if (c == ch) 60 break; 61 if (c == '\\') { 62 c = Getc(s); 63 if ((c != EOF) && (out)) 64 Putc(c, out); 65 } 66 } 67 if (c == EOF) 68 return -1; 69 return 0; 70} 71 72static void copy_location(const DOH *s1, DOH *s2) { 73 Setfile(s2, Getfile((DOH *) s1)); 74 Setline(s2, Getline((DOH *) s1)); 75} 76 77static String *cpp_include(const_String_or_char_ptr fn, int sysfile) { 78 String *s = sysfile ? Swig_include_sys(fn) : Swig_include(fn); 79 if (s && single_include) { 80 String *file = Getfile(s); 81 if (Getattr(included_files, file)) { 82 Delete(s); 83 return 0; 84 } 85 Setattr(included_files, file, file); 86 } 87 if (!s) { 88 /* XXX(bhy) may not need the seek */ 89 /* Seek(fn, 0, SEEK_SET); */ 90 if (ignore_missing) { 91 Swig_warning(WARN_PP_MISSING_FILE, Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn); 92 } else { 93 Swig_error(Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn); 94 } 95 } else { 96 String *lf; 97 Seek(s, 0, SEEK_SET); 98 if (!dependencies) { 99 dependencies = NewList(); 100 } 101 lf = Copy(Swig_last_file()); 102 Append(dependencies, lf); 103 Delete(lf); 104 } 105 return s; 106} 107 108List *Preprocessor_depend(void) { 109 return dependencies; 110} 111 112/* ----------------------------------------------------------------------------- 113 * void Preprocessor_cpp_init() - Initialize the preprocessor 114 * ----------------------------------------------------------------------------- */ 115static String *kpp_args = 0; 116static String *kpp_define = 0; 117static String *kpp_defined = 0; 118static String *kpp_elif = 0; 119static String *kpp_else = 0; 120static String *kpp_endif = 0; 121static String *kpp_expanded = 0; 122static String *kpp_if = 0; 123static String *kpp_ifdef = 0; 124static String *kpp_ifndef = 0; 125static String *kpp_name = 0; 126static String *kpp_swigmacro = 0; 127static String *kpp_symbols = 0; 128static String *kpp_undef = 0; 129static String *kpp_value = 0; 130static String *kpp_varargs = 0; 131static String *kpp_error = 0; 132static String *kpp_warning = 0; 133static String *kpp_line = 0; 134static String *kpp_include = 0; 135static String *kpp_pragma = 0; 136static String *kpp_level = 0; 137 138static String *kpp_dline = 0; 139static String *kpp_ddefine = 0; 140static String *kpp_dinclude = 0; 141static String *kpp_dimport = 0; 142static String *kpp_dextern = 0; 143 144static String *kpp_LINE = 0; 145static String *kpp_FILE = 0; 146 147void Preprocessor_init(void) { 148 Hash *s; 149 150 kpp_args = NewString("args"); 151 kpp_define = NewString("define"); 152 kpp_defined = NewString("defined"); 153 kpp_else = NewString("else"); 154 kpp_elif = NewString("elif"); 155 kpp_endif = NewString("endif"); 156 kpp_expanded = NewString("*expanded*"); 157 kpp_if = NewString("if"); 158 kpp_ifdef = NewString("ifdef"); 159 kpp_ifndef = NewString("ifndef"); 160 kpp_name = NewString("name"); 161 kpp_swigmacro = NewString("swigmacro"); 162 kpp_symbols = NewString("symbols"); 163 kpp_undef = NewString("undef"); 164 kpp_value = NewString("value"); 165 kpp_error = NewString("error"); 166 kpp_warning = NewString("warning"); 167 kpp_pragma = NewString("pragma"); 168 kpp_level = NewString("level"); 169 kpp_line = NewString("line"); 170 kpp_include = NewString("include"); 171 kpp_varargs = NewString("varargs"); 172 173 kpp_dinclude = NewString("%include"); 174 kpp_dimport = NewString("%import"); 175 kpp_dextern = NewString("%extern"); 176 kpp_ddefine = NewString("%define"); 177 kpp_dline = NewString("%line"); 178 179 180 kpp_LINE = NewString("__LINE__"); 181 kpp_FILE = NewString("__FILE__"); 182 183 cpp = NewHash(); 184 s = NewHash(); 185 Setattr(cpp, kpp_symbols, s); 186 Delete(s); 187 Preprocessor_expr_init(); /* Initialize the expression evaluator */ 188 included_files = NewHash(); 189 190 id_scan = NewScanner();; 191 192} 193 194void Preprocessor_delete(void) { 195 Delete(kpp_args); 196 Delete(kpp_define); 197 Delete(kpp_defined); 198 Delete(kpp_else); 199 Delete(kpp_elif); 200 Delete(kpp_endif); 201 Delete(kpp_expanded); 202 Delete(kpp_if); 203 Delete(kpp_ifdef); 204 Delete(kpp_ifndef); 205 Delete(kpp_name); 206 Delete(kpp_swigmacro); 207 Delete(kpp_symbols); 208 Delete(kpp_undef); 209 Delete(kpp_value); 210 Delete(kpp_error); 211 Delete(kpp_warning); 212 Delete(kpp_pragma); 213 Delete(kpp_level); 214 Delete(kpp_line); 215 Delete(kpp_include); 216 Delete(kpp_varargs); 217 218 Delete(kpp_dinclude); 219 Delete(kpp_dimport); 220 Delete(kpp_dextern); 221 Delete(kpp_ddefine); 222 Delete(kpp_dline); 223 224 225 Delete(kpp_LINE); 226 Delete(kpp_FILE); 227 Delete(cpp); 228 Delete(included_files); 229 Preprocessor_expr_delete(); 230 DelScanner(id_scan); 231 232 Delete(dependencies); 233 234 Delete(Swig_add_directory(0)); 235} 236 237/* ----------------------------------------------------------------------------- 238 * void Preprocessor_include_all() - Instruct preprocessor to include all files 239 * ----------------------------------------------------------------------------- */ 240void Preprocessor_include_all(int a) { 241 include_all = a; 242} 243 244void Preprocessor_import_all(int a) { 245 import_all = a; 246} 247 248void Preprocessor_ignore_missing(int a) { 249 ignore_missing = a; 250} 251 252void Preprocessor_error_as_warning(int a) { 253 error_as_warning = a; 254} 255 256 257/* ----------------------------------------------------------------------------- 258 * Preprocessor_define() 259 * 260 * Defines a new C preprocessor symbol. swigmacro specifies whether or not the macro has 261 * SWIG macro semantics. 262 * ----------------------------------------------------------------------------- */ 263 264 265String *Macro_vararg_name(const_String_or_char_ptr str, const_String_or_char_ptr line) { 266 String *argname; 267 String *varargname; 268 char *s, *dots; 269 270 argname = Copy(str); 271 s = Char(argname); 272 dots = strchr(s, '.'); 273 if (!dots) { 274 Delete(argname); 275 return NULL; 276 } 277 278 if (strcmp(dots, "...") != 0) { 279 Swig_error(Getfile(line), Getline(line), "Illegal macro argument name '%s'\n", str); 280 Delete(argname); 281 return NULL; 282 } 283 if (dots == s) { 284 varargname = NewString("__VA_ARGS__"); 285 } else { 286 *dots = '\0'; 287 varargname = NewString(s); 288 } 289 Delete(argname); 290 return varargname; 291} 292 293Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) { 294 String *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0; 295 Hash *macro = 0, *symbols = 0, *m1; 296 List *arglist = 0; 297 int c, line; 298 int varargs = 0; 299 String *str; 300 301 assert(cpp); 302 assert(_str); 303 304 /* First make sure that string is actually a string */ 305 if (DohCheck(_str)) { 306 s = Copy(_str); 307 copy_location(_str, s); 308 str = s; 309 } else { 310 str = NewString((char *) _str); 311 } 312 Seek(str, 0, SEEK_SET); 313 line = Getline(str); 314 file = Getfile(str); 315 316 /* Skip over any leading whitespace */ 317 skip_whitespace(str, 0); 318 319 /* Now look for a macro name */ 320 macroname = NewStringEmpty(); 321 while ((c = Getc(str)) != EOF) { 322 if (c == '(') { 323 argstr = NewStringEmpty(); 324 copy_location(str, argstr); 325 /* It is a macro. Go extract its argument string */ 326 while ((c = Getc(str)) != EOF) { 327 if (c == ')') 328 break; 329 else 330 Putc(c, argstr); 331 } 332 if (c != ')') { 333 Swig_error(Getfile(str), Getline(str), "Missing \')\' in macro parameters\n"); 334 goto macro_error; 335 } 336 break; 337 } else if (isidchar(c) || (c == '%')) { 338 Putc(c, macroname); 339 } else if (isspace(c)) { 340 break; 341 } else if (c == '\\') { 342 c = Getc(str); 343 if (c != '\n') { 344 Ungetc(c, str); 345 Ungetc('\\', str); 346 break; 347 } 348 } else { 349 /*Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n"); 350 goto macro_error; */ 351 Ungetc(c, str); 352 break; 353 } 354 } 355 if (!swigmacro) 356 skip_whitespace(str, 0); 357 macrovalue = NewStringEmpty(); 358 while ((c = Getc(str)) != EOF) { 359 Putc(c, macrovalue); 360 } 361 362 /* If there are any macro arguments, convert into a list */ 363 if (argstr) { 364 String *argname, *varargname; 365 arglist = NewList(); 366 Seek(argstr, 0, SEEK_SET); 367 argname = NewStringEmpty(); 368 while ((c = Getc(argstr)) != EOF) { 369 if (c == ',') { 370 varargname = Macro_vararg_name(argname, str); 371 if (varargname) { 372 Delete(varargname); 373 Swig_error(Getfile(str), Getline(str), "Variable-length macro argument must be last parameter\n"); 374 } else { 375 Append(arglist, argname); 376 } 377 Delete(argname); 378 argname = NewStringEmpty(); 379 } else if (isidchar(c) || (c == '.')) { 380 Putc(c, argname); 381 } else if (!(isspace(c) || (c == '\\'))) { 382 Delete(argname); 383 Swig_error(Getfile(str), Getline(str), "Illegal character in macro argument name\n"); 384 goto macro_error; 385 } 386 } 387 if (Len(argname)) { 388 /* Check for varargs */ 389 varargname = Macro_vararg_name(argname, str); 390 if (varargname) { 391 Append(arglist, varargname); 392 Delete(varargname); 393 varargs = 1; 394 } else { 395 Append(arglist, argname); 396 } 397 } 398 Delete(argname); 399 } 400 401 if (!swigmacro) { 402 Replace(macrovalue, "\\\n", " ", DOH_REPLACE_NOQUOTE); 403 } 404 405 /* Look for special # substitutions. We only consider # that appears 406 outside of quotes and comments */ 407 408 { 409 int state = 0; 410 char *cc = Char(macrovalue); 411 while (*cc) { 412 switch (state) { 413 case 0: 414 if (*cc == '#') 415 *cc = '\001'; 416 else if (*cc == '/') 417 state = 10; 418 else if (*cc == '\'') 419 state = 20; 420 else if (*cc == '\"') 421 state = 30; 422 break; 423 case 10: 424 if (*cc == '*') 425 state = 11; 426 else if (*cc == '/') 427 state = 15; 428 else { 429 state = 0; 430 cc--; 431 } 432 break; 433 case 11: 434 if (*cc == '*') 435 state = 12; 436 break; 437 case 12: 438 if (*cc == '/') 439 state = 0; 440 else if (*cc != '*') 441 state = 11; 442 break; 443 case 15: 444 if (*cc == '\n') 445 state = 0; 446 break; 447 case 20: 448 if (*cc == '\'') 449 state = 0; 450 if (*cc == '\\') 451 state = 21; 452 break; 453 case 21: 454 state = 20; 455 break; 456 case 30: 457 if (*cc == '\"') 458 state = 0; 459 if (*cc == '\\') 460 state = 31; 461 break; 462 case 31: 463 state = 30; 464 break; 465 default: 466 break; 467 } 468 cc++; 469 } 470 } 471 472 /* Get rid of whitespace surrounding # */ 473 /* Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); */ 474 while (strstr(Char(macrovalue), "\001 ")) { 475 Replace(macrovalue, "\001 ", "\001", DOH_REPLACE_ANY); 476 } 477 while (strstr(Char(macrovalue), " \001")) { 478 Replace(macrovalue, " \001", "\001", DOH_REPLACE_ANY); 479 } 480 /* Replace '##' with a special token */ 481 Replace(macrovalue, "\001\001", "\002", DOH_REPLACE_ANY); 482 /* Replace '#@' with a special token */ 483 Replace(macrovalue, "\001@", "\004", DOH_REPLACE_ANY); 484 /* Replace '##@' with a special token */ 485 Replace(macrovalue, "\002@", "\005", DOH_REPLACE_ANY); 486 487 /* Go create the macro */ 488 macro = NewHash(); 489 Setattr(macro, kpp_name, macroname); 490 491 if (arglist) { 492 Setattr(macro, kpp_args, arglist); 493 Delete(arglist); 494 if (varargs) { 495 Setattr(macro, kpp_varargs, "1"); 496 } 497 } 498 Setattr(macro, kpp_value, macrovalue); 499 Setline(macro, line); 500 Setfile(macro, file); 501 if (swigmacro) { 502 Setattr(macro, kpp_swigmacro, "1"); 503 } 504 symbols = Getattr(cpp, kpp_symbols); 505 if ((m1 = Getattr(symbols, macroname))) { 506 if (!Checkattr(m1, kpp_value, macrovalue)) { 507 Swig_error(Getfile(str), Getline(str), "Macro '%s' redefined,\n", macroname); 508 Swig_error(Getfile(m1), Getline(m1), "previous definition of '%s'.\n", macroname); 509 goto macro_error; 510 } 511 } else { 512 Setattr(symbols, macroname, macro); 513 Delete(macro); 514 } 515 516 Delete(macroname); 517 Delete(macrovalue); 518 519 Delete(str); 520 Delete(argstr); 521 return macro; 522 523macro_error: 524 Delete(str); 525 Delete(argstr); 526 Delete(arglist); 527 Delete(macroname); 528 Delete(macrovalue); 529 return 0; 530} 531 532/* ----------------------------------------------------------------------------- 533 * Preprocessor_undef() 534 * 535 * Undefines a macro. 536 * ----------------------------------------------------------------------------- */ 537void Preprocessor_undef(const_String_or_char_ptr str) { 538 Hash *symbols; 539 assert(cpp); 540 symbols = Getattr(cpp, kpp_symbols); 541 Delattr(symbols, str); 542} 543 544/* ----------------------------------------------------------------------------- 545 * find_args() 546 * 547 * Isolates macro arguments and returns them in a list. For each argument, 548 * leading and trailing whitespace is stripped (ala K&R, pg. 230). 549 * ----------------------------------------------------------------------------- */ 550static List *find_args(String *s) { 551 List *args; 552 String *str; 553 int c, level; 554 long pos; 555 556 /* Create a new list */ 557 args = NewList(); 558 copy_location(s, args); 559 560 /* First look for a '(' */ 561 pos = Tell(s); 562 skip_whitespace(s, 0); 563 564 /* Now see if the next character is a '(' */ 565 c = Getc(s); 566 if (c != '(') { 567 /* Not a macro, bail out now! */ 568 Seek(s, pos, SEEK_SET); 569 Delete(args); 570 return 0; 571 } 572 c = Getc(s); 573 /* Okay. This appears to be a macro so we will start isolating arguments */ 574 while (c != EOF) { 575 if (isspace(c)) { 576 skip_whitespace(s, 0); /* Skip leading whitespace */ 577 c = Getc(s); 578 } 579 str = NewStringEmpty(); 580 copy_location(s, str); 581 level = 0; 582 while (c != EOF) { 583 if (c == '\"') { 584 Putc(c, str); 585 skip_tochar(s, '\"', str); 586 c = Getc(s); 587 continue; 588 } else if (c == '\'') { 589 Putc(c, str); 590 skip_tochar(s, '\'', str); 591 c = Getc(s); 592 continue; 593 } 594 if ((c == ',') && (level == 0)) 595 break; 596 if ((c == ')') && (level == 0)) 597 break; 598 Putc(c, str); 599 if (c == '(') 600 level++; 601 if (c == ')') 602 level--; 603 c = Getc(s); 604 } 605 if (level > 0) { 606 goto unterm; 607 } 608 Chop(str); 609 if (Len(args) || Len(str)) 610 Append(args, str); 611 Delete(str); 612 613 /* if (Len(str) && (c != ')')) 614 Append(args,str); */ 615 616 if (c == ')') 617 return args; 618 c = Getc(s); 619 } 620unterm: 621 Swig_error(Getfile(args), Getline(args), "Unterminated macro call.\n"); 622 return args; 623} 624 625/* ----------------------------------------------------------------------------- 626 * DOH *get_filename(DOH *str) 627 * 628 * Read a filename from str. A filename can be enclose in quotes, angle brackets, 629 * or bare. 630 * ----------------------------------------------------------------------------- */ 631 632static String *get_filename(String *str, int *sysfile) { 633 String *fn; 634 int c; 635 636 skip_whitespace(str, 0); 637 fn = NewStringEmpty(); 638 copy_location(str, fn); 639 c = Getc(str); 640 *sysfile = 0; 641 if (c == '\"') { 642 while (((c = Getc(str)) != EOF) && (c != '\"')) 643 Putc(c, fn); 644 } else if (c == '<') { 645 *sysfile = 1; 646 while (((c = Getc(str)) != EOF) && (c != '>')) 647 Putc(c, fn); 648 } else { 649 Putc(c, fn); 650 while (((c = Getc(str)) != EOF) && (!isspace(c))) 651 Putc(c, fn); 652 if (isspace(c)) 653 Ungetc(c, str); 654 } 655 Swig_filename_correct(fn); 656 Seek(fn, 0, SEEK_SET); 657 return fn; 658} 659 660static String *get_options(String *str) { 661 662 int c; 663 skip_whitespace(str, 0); 664 c = Getc(str); 665 if (c == '(') { 666 String *opt; 667 int level = 1; 668 opt = NewString("("); 669 while (((c = Getc(str)) != EOF)) { 670 Putc(c, opt); 671 if (c == ')') { 672 level--; 673 if (!level) 674 return opt; 675 } 676 if (c == '(') 677 level++; 678 } 679 Delete(opt); 680 return 0; 681 } else { 682 Ungetc(c, str); 683 return 0; 684 } 685} 686 687/* ----------------------------------------------------------------------------- 688 * expand_macro() 689 * 690 * Perform macro expansion and return a new string. Returns NULL if some sort 691 * of error occurred. 692 * ----------------------------------------------------------------------------- */ 693 694static String *expand_macro(String *name, List *args) { 695 String *ns; 696 DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e; 697 int i, l; 698 int isvarargs = 0; 699 700 symbols = Getattr(cpp, kpp_symbols); 701 if (!symbols) 702 return 0; 703 704 /* See if the name is actually defined */ 705 macro = Getattr(symbols, name); 706 if (!macro) 707 return 0; 708 if (Getattr(macro, kpp_expanded)) { 709 ns = NewStringEmpty(); 710 Append(ns, name); 711 if (args) { 712 int lenargs = Len(args); 713 if (lenargs) 714 Putc('(', ns); 715 for (i = 0; i < lenargs; i++) { 716 Append(ns, Getitem(args, i)); 717 if (i < (lenargs - 1)) 718 Putc(',', ns); 719 } 720 if (i) 721 Putc(')', ns); 722 } 723 return ns; 724 } 725 726 /* Get macro arguments and value */ 727 mvalue = Getattr(macro, kpp_value); 728 assert(mvalue); 729 margs = Getattr(macro, kpp_args); 730 731 if (args && Getattr(macro, kpp_varargs)) { 732 isvarargs = 1; 733 /* Variable length argument macro. We need to collect all of the extra arguments into a single argument */ 734 if (Len(args) >= (Len(margs) - 1)) { 735 int i; 736 int vi, na; 737 String *vararg = NewStringEmpty(); 738 vi = Len(margs) - 1; 739 na = Len(args); 740 for (i = vi; i < na; i++) { 741 Append(vararg, Getitem(args, i)); 742 if ((i + 1) < na) { 743 Append(vararg, ","); 744 } 745 } 746 /* Remove arguments */ 747 for (i = vi; i < na; i++) { 748 Delitem(args, vi); 749 } 750 Append(args, vararg); 751 Delete(vararg); 752 } 753 } 754 /* If there are arguments, see if they match what we were given */ 755 if (args && (margs) && (Len(margs) != Len(args))) { 756 if (Len(margs) > (1 + isvarargs)) 757 Swig_error(Getfile(args), Getline(args), "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs); 758 else if (Len(margs) == (1 + isvarargs)) 759 Swig_error(Getfile(args), Getline(args), "Macro '%s' expects 1 argument\n", name); 760 else 761 Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name); 762 return 0; 763 } 764 765 /* If the macro expects arguments, but none were supplied, we leave it in place */ 766 if (!args && (margs) && Len(margs) > 0) { 767 return NewString(name); 768 } 769 770 /* Copy the macro value */ 771 ns = Copy(mvalue); 772 copy_location(mvalue, ns); 773 774 /* Tag the macro as being expanded. This is to avoid recursion in 775 macro expansion */ 776 777 temp = NewStringEmpty(); 778 tempa = NewStringEmpty(); 779 if (args && margs) { 780 l = Len(margs); 781 for (i = 0; i < l; i++) { 782 DOH *arg, *aname; 783 String *reparg; 784 arg = Getitem(args, i); /* Get an argument value */ 785 reparg = Preprocessor_replace(arg); 786 aname = Getitem(margs, i); /* Get macro argument name */ 787 if (strstr(Char(ns), "\001")) { 788 /* Try to replace a quoted version of the argument */ 789 Clear(temp); 790 Clear(tempa); 791 Printf(temp, "\001%s", aname); 792 Printf(tempa, "\"%s\"", arg); 793 Replace(ns, temp, tempa, DOH_REPLACE_ID_END); 794 } 795 if (strstr(Char(ns), "\002")) { 796 /* Look for concatenation tokens */ 797 Clear(temp); 798 Clear(tempa); 799 Printf(temp, "\002%s", aname); 800 Append(tempa, "\002\003"); 801 Replace(ns, temp, tempa, DOH_REPLACE_ID_END); 802 Clear(temp); 803 Clear(tempa); 804 Printf(temp, "%s\002", aname); 805 Append(tempa, "\003\002"); 806 Replace(ns, temp, tempa, DOH_REPLACE_ID_BEGIN); 807 } 808 809 /* Non-standard macro expansion. The value `x` is replaced by a quoted 810 version of the argument except that if the argument is already quoted 811 nothing happens */ 812 813 if (strchr(Char(ns), '`')) { 814 String *rep; 815 char *c; 816 Clear(temp); 817 Printf(temp, "`%s`", aname); 818 c = Char(arg); 819 if (*c == '\"') { 820 rep = arg; 821 } else { 822 Clear(tempa); 823 Printf(tempa, "\"%s\"", arg); 824 rep = tempa; 825 } 826 Replace(ns, temp, rep, DOH_REPLACE_ANY); 827 } 828 829 /* Non-standard mangle expansions. 830 The #@Name is replaced by mangle_arg(Name). */ 831 if (strstr(Char(ns), "\004")) { 832 String *marg = Swig_string_mangle(arg); 833 Clear(temp); 834 Printf(temp, "\004%s", aname); 835 Replace(ns, temp, marg, DOH_REPLACE_ID_END); 836 Delete(marg); 837 } 838 if (strstr(Char(ns), "\005")) { 839 String *marg = Swig_string_mangle(arg); 840 Clear(temp); 841 Clear(tempa); 842 Printf(temp, "\005%s", aname); 843 Printf(tempa, "\"%s\"", marg); 844 Replace(ns, temp, tempa, DOH_REPLACE_ID_END); 845 Delete(marg); 846 } 847 848 if (isvarargs && i == l - 1 && Len(arg) == 0) { 849 /* Zero length varargs macro argument. We search for commas that might appear before and nuke them */ 850 char *a, *s, *t, *name; 851 int namelen; 852 s = Char(ns); 853 name = Char(aname); 854 namelen = Len(aname); 855 a = strstr(s, name); 856 while (a) { 857 char ca = a[namelen + 1]; 858 if (!isidchar((int) ca)) { 859 /* Matched the entire vararg name, not just a prefix */ 860 t = a - 1; 861 if (*t == '\002') { 862 t--; 863 while (t >= s) { 864 if (isspace((int) *t)) 865 t--; 866 else if (*t == ',') { 867 *t = ' '; 868 } else 869 break; 870 } 871 } 872 } 873 a = strstr(a + namelen, name); 874 } 875 } 876 /* Replace(ns, aname, arg, DOH_REPLACE_ID); */ 877 Replace(ns, aname, reparg, DOH_REPLACE_ID); /* Replace expanded args */ 878 Replace(ns, "\003", arg, DOH_REPLACE_ANY); /* Replace unexpanded arg */ 879 Delete(reparg); 880 } 881 } 882 Replace(ns, "\002", "", DOH_REPLACE_ANY); /* Get rid of concatenation tokens */ 883 Replace(ns, "\001", "#", DOH_REPLACE_ANY); /* Put # back (non-standard C) */ 884 Replace(ns, "\004", "#@", DOH_REPLACE_ANY); /* Put # back (non-standard C) */ 885 886 /* Expand this macro even further */ 887 Setattr(macro, kpp_expanded, "1"); 888 889 e = Preprocessor_replace(ns); 890 891 Delattr(macro, kpp_expanded); 892 Delete(ns); 893 894 if (Getattr(macro, kpp_swigmacro)) { 895 String *g; 896 String *f = NewStringEmpty(); 897 Seek(e, 0, SEEK_SET); 898 copy_location(macro, e); 899 g = Preprocessor_parse(e); 900 901#if 0 902 /* Drop the macro in place, but with a marker around it */ 903 Printf(f, "/*@%s,%d,%s@*/%s/*@@*/", Getfile(macro), Getline(macro), name, g); 904#else 905 /* Use simplified around markers to properly count lines in cscanner.c */ 906 if (strchr(Char(g), '\n')) { 907 Printf(f, "/*@SWIG:%s,%d,%s@*/%s/*@SWIG@*/", Getfile(macro), Getline(macro), name, g); 908#if 0 909 Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g); 910#endif 911 } else { 912 Append(f, g); 913 } 914#endif 915 916 Delete(g); 917 Delete(e); 918 e = f; 919 } 920 Delete(temp); 921 Delete(tempa); 922 return e; 923} 924 925/* ----------------------------------------------------------------------------- 926 * evaluate_args() 927 * 928 * Evaluate the arguments of a macro 929 * ----------------------------------------------------------------------------- */ 930 931List *evaluate_args(List *x) { 932 Iterator i; 933 List *nl = NewList(); 934 935 for (i = First(x); i.item; i = Next(i)) { 936 Append(nl, Preprocessor_replace(i.item)); 937 } 938 return nl; 939} 940 941/* ----------------------------------------------------------------------------- 942 * DOH *Preprocessor_replace(DOH *s) 943 * 944 * Performs a macro substitution on a string s. Returns a new string with 945 * substitutions applied. This function works by walking down s and looking 946 * for identifiers. When found, a check is made to see if they are macros 947 * which are then expanded. 948 * ----------------------------------------------------------------------------- */ 949 950/* #define SWIG_PUT_BUFF */ 951 952DOH *Preprocessor_replace(DOH *s) { 953 DOH *ns, *symbols, *m; 954 int c, i, state = 0; 955 956 String *id = NewStringEmpty(); 957 958 assert(cpp); 959 symbols = Getattr(cpp, kpp_symbols); 960 961 ns = NewStringEmpty(); 962 copy_location(s, ns); 963 Seek(s, 0, SEEK_SET); 964 965 /* Try to locate identifiers in s and replace them with macro replacements */ 966 while ((c = Getc(s)) != EOF) { 967 switch (state) { 968 case 0: 969 if (isidentifier(c) || (c == '%')) { 970 Clear(id); 971 Putc(c, id); 972 state = 1; 973 } else if (c == '\"') { 974 Putc(c, ns); 975 skip_tochar(s, '\"', ns); 976 } else if (c == '\'') { 977 Putc(c, ns); 978 skip_tochar(s, '\'', ns); 979 } else if (c == '/') { 980 Putc(c, ns); 981 state = 10; 982 } else { 983 Putc(c, ns); 984 } 985 break; 986 case 1: /* An identifier */ 987 if (isidchar(c)) { 988 Putc(c, id); 989 state = 1; 990 } else { 991 /* We found the end of a valid identifier */ 992 Ungetc(c, s); 993 /* See if this is the special "defined" macro */ 994 if (Equal(kpp_defined, id)) { 995 int lenargs = 0; 996 DOH *args = 0; 997 /* See whether or not a paranthesis has been used */ 998 skip_whitespace(s, 0); 999 c = Getc(s); 1000 if (c == '(') { 1001 Ungetc(c, s); 1002 args = find_args(s); 1003 } else if (isidchar(c)) { 1004 DOH *arg = NewStringEmpty(); 1005 args = NewList(); 1006 Putc(c, arg); 1007 while (((c = Getc(s)) != EOF)) { 1008 if (!isidchar(c)) { 1009 Ungetc(c, s); 1010 break; 1011 } 1012 Putc(c, arg); 1013 } 1014 if (Len(arg)) 1015 Append(args, arg); 1016 Delete(arg); 1017 } else { 1018 Seek(s, -1, SEEK_CUR); 1019 } 1020 lenargs = Len(args); 1021 if ((!args) || (!lenargs)) { 1022 /* This is not a defined() macro. */ 1023 Append(ns, id); 1024 state = 0; 1025 break; 1026 } 1027 for (i = 0; i < lenargs; i++) { 1028 DOH *o = Getitem(args, i); 1029 if (!Getattr(symbols, o)) { 1030 break; 1031 } 1032 } 1033 if (i < lenargs) 1034 Putc('0', ns); 1035 else 1036 Putc('1', ns); 1037 Delete(args); 1038 state = 0; 1039 break; 1040 } 1041 if (Equal(kpp_LINE, id)) { 1042 Printf(ns, "%d", Getline(s)); 1043 state = 0; 1044 break; 1045 } 1046 if (Equal(kpp_FILE, id)) { 1047 String *fn = Copy(Getfile(s)); 1048 Replaceall(fn, "\\", "\\\\"); 1049 Printf(ns, "\"%s\"", fn); 1050 Delete(fn); 1051 state = 0; 1052 break; 1053 } 1054 /* See if the macro is defined in the preprocessor symbol table */ 1055 if ((m = Getattr(symbols, id))) { 1056 DOH *args = 0; 1057 DOH *e; 1058 /* See if the macro expects arguments */ 1059 if (Getattr(m, kpp_args)) { 1060 /* Yep. We need to go find the arguments and do a substitution */ 1061 args = find_args(s); 1062 if (!Len(args)) { 1063 Delete(args); 1064 args = 0; 1065 } 1066 } else { 1067 args = 0; 1068 } 1069 e = expand_macro(id, args); 1070 if (e) { 1071 Append(ns, e); 1072 } 1073 Delete(e); 1074 Delete(args); 1075 } else { 1076 Append(ns, id); 1077 } 1078 state = 0; 1079 } 1080 break; 1081 case 10: 1082 if (c == '/') 1083 state = 11; 1084 else if (c == '*') 1085 state = 12; 1086 else { 1087 Ungetc(c, s); 1088 state = 0; 1089 break; 1090 } 1091 Putc(c, ns); 1092 break; 1093 case 11: 1094 Putc(c, ns); 1095 if (c == '\n') 1096 state = 0; 1097 break; 1098 case 12: 1099 Putc(c, ns); 1100 if (c == '*') 1101 state = 13; 1102 break; 1103 case 13: 1104 Putc(c, ns); 1105 if (c == '/') 1106 state = 0; 1107 else if (c != '*') 1108 state = 12; 1109 break; 1110 default: 1111 state = 0; 1112 break; 1113 } 1114 } 1115 1116 /* Identifier at the end */ 1117 if (state == 1) { 1118 /* See if this is the special "defined" macro */ 1119 if (Equal(kpp_defined, id)) { 1120 Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n"); 1121 } else if ((m = Getattr(symbols, id))) { 1122 DOH *e; 1123 /* Yes. There is a macro here */ 1124 /* See if the macro expects arguments */ 1125 /* if (Getattr(m,"args")) { 1126 Swig_error(Getfile(id),Getline(id),"Macro arguments expected.\n"); 1127 } */ 1128 e = expand_macro(id, 0); 1129 Append(ns, e); 1130 Delete(e); 1131 } else { 1132 Append(ns, id); 1133 } 1134 } 1135 Delete(id); 1136 return ns; 1137} 1138 1139 1140/* ----------------------------------------------------------------------------- 1141 * int checkpp_id(DOH *s) 1142 * 1143 * Checks the string s to see if it contains any unresolved identifiers. This 1144 * function contains the heuristic that determines whether or not a macro 1145 * definition passes through the preprocessor as a constant declaration. 1146 * ----------------------------------------------------------------------------- */ 1147static int checkpp_id(DOH *s) { 1148 int c; 1149 int hastok = 0; 1150 Scanner *scan = id_scan; 1151 1152 Seek(s, 0, SEEK_SET); 1153 1154 Scanner_clear(scan); 1155 s = Copy(s); 1156 Seek(s, SEEK_SET, 0); 1157 Scanner_push(scan, s); 1158 while ((c = Scanner_token(scan))) { 1159 hastok = 1; 1160 if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE)) 1161 return 1; 1162 } 1163 if (!hastok) 1164 return 1; 1165 return 0; 1166} 1167 1168/* addline(). Utility function for adding lines to a chunk */ 1169static void addline(DOH *s1, DOH *s2, int allow) { 1170 if (allow) { 1171 Append(s1, s2); 1172 } else { 1173 char *c = Char(s2); 1174 while (*c) { 1175 if (*c == '\n') 1176 Putc('\n', s1); 1177 c++; 1178 } 1179 } 1180} 1181 1182static void add_chunk(DOH *ns, DOH *chunk, int allow) { 1183 DOH *echunk; 1184 Seek(chunk, 0, SEEK_SET); 1185 if (allow) { 1186 echunk = Preprocessor_replace(chunk); 1187 addline(ns, echunk, allow); 1188 Delete(echunk); 1189 } else { 1190 addline(ns, chunk, 0); 1191 } 1192 Clear(chunk); 1193} 1194 1195/* 1196 push/pop_imported(): helper functions for defining and undefining 1197 SWIGIMPORTED (when %importing a file). 1198 */ 1199static void push_imported() { 1200 if (imported_depth == 0) { 1201 Preprocessor_define("SWIGIMPORTED 1", 0); 1202 } 1203 ++imported_depth; 1204} 1205 1206static void pop_imported() { 1207 --imported_depth; 1208 if (imported_depth == 0) { 1209 Preprocessor_undef("SWIGIMPORTED"); 1210 } 1211} 1212 1213 1214/* ----------------------------------------------------------------------------- 1215 * Preprocessor_parse() 1216 * 1217 * Parses the string s. Returns a new string containing the preprocessed version. 1218 * 1219 * Parsing rules : 1220 * 1. Lines starting with # are C preprocessor directives 1221 * 2. Macro expansion inside strings is not allowed 1222 * 3. All code inside false conditionals is changed to blank lines 1223 * 4. Code in %{, %} is not parsed because it may need to be 1224 * included inline (with all preprocessor directives included). 1225 * ----------------------------------------------------------------------------- */ 1226 1227String *Preprocessor_parse(String *s) { 1228 String *ns; /* New string containing the preprocessed text */ 1229 String *chunk, *decl; 1230 Hash *symbols; 1231 String *id = 0, *value = 0, *comment = 0; 1232 int i, state, e, c; 1233 int start_line = 0; 1234 int allow = 1; 1235 int level = 0; 1236 int dlevel = 0; 1237 int mask = 0; 1238 int start_level = 0; 1239 int cpp_lines = 0; 1240 int cond_lines[256]; 1241 1242 /* Blow away all carriage returns */ 1243 Replace(s, "\015", "", DOH_REPLACE_ANY); 1244 1245 ns = NewStringEmpty(); /* Return result */ 1246 1247 decl = NewStringEmpty(); 1248 id = NewStringEmpty(); 1249 value = NewStringEmpty(); 1250 comment = NewStringEmpty(); 1251 chunk = NewStringEmpty(); 1252 copy_location(s, chunk); 1253 copy_location(s, ns); 1254 symbols = Getattr(cpp, kpp_symbols); 1255 1256 state = 0; 1257 while ((c = Getc(s)) != EOF) { 1258 switch (state) { 1259 case 0: /* Initial state - in first column */ 1260 /* Look for C preprocessor directives. Otherwise, go directly to state 1 */ 1261 if (c == '#') { 1262 add_chunk(ns, chunk, allow); 1263 copy_location(s, chunk); 1264 cpp_lines = 1; 1265 state = 40; 1266 } else if (isspace(c)) { 1267 Putc(c, chunk); 1268 skip_whitespace(s, chunk); 1269 } else { 1270 state = 1; 1271 Ungetc(c, s); 1272 } 1273 break; 1274 case 1: /* Non-preprocessor directive */ 1275 /* Look for SWIG directives */ 1276 if (c == '%') { 1277 state = 100; 1278 break; 1279 } 1280 Putc(c, chunk); 1281 if (c == '\n') 1282 state = 0; 1283 else if (c == '\"') { 1284 start_line = Getline(s); 1285 if (skip_tochar(s, '\"', chunk) < 0) { 1286 Swig_error(Getfile(s), -1, "Unterminated string constant starting at line %d\n", start_line); 1287 } 1288 } else if (c == '\'') { 1289 start_line = Getline(s); 1290 if (skip_tochar(s, '\'', chunk) < 0) { 1291 Swig_error(Getfile(s), -1, "Unterminated character constant starting at line %d\n", start_line); 1292 } 1293 } else if (c == '/') 1294 state = 30; /* Comment */ 1295 break; 1296 1297 case 30: /* Possibly a comment string of some sort */ 1298 start_line = Getline(s); 1299 Putc(c, chunk); 1300 if (c == '/') 1301 state = 31; 1302 else if (c == '*') 1303 state = 32; 1304 else 1305 state = 1; 1306 break; 1307 case 31: 1308 Putc(c, chunk); 1309 if (c == '\n') 1310 state = 0; 1311 break; 1312 case 32: 1313 Putc(c, chunk); 1314 if (c == '*') 1315 state = 33; 1316 break; 1317 case 33: 1318 Putc(c, chunk); 1319 if (c == '/') 1320 state = 1; 1321 else if (c != '*') 1322 state = 32; 1323 break; 1324 1325 case 40: /* Start of a C preprocessor directive */ 1326 if (c == '\n') { 1327 Putc('\n', chunk); 1328 state = 0; 1329 } else if (isspace(c)) { 1330 state = 40; 1331 } else { 1332 /* Got the start of a preprocessor directive */ 1333 Ungetc(c, s); 1334 Clear(id); 1335 copy_location(s, id); 1336 state = 41; 1337 } 1338 break; 1339 1340 case 41: /* Build up the name of the preprocessor directive */ 1341 if ((isspace(c) || (!isalpha(c)))) { 1342 Clear(value); 1343 Clear(comment); 1344 if (c == '\n') { 1345 Ungetc(c, s); 1346 state = 50; 1347 } else { 1348 state = 42; 1349 if (!isspace(c)) { 1350 Ungetc(c, s); 1351 } 1352 } 1353 1354 copy_location(s, value); 1355 break; 1356 } 1357 Putc(c, id); 1358 break; 1359 1360 case 42: /* Strip any leading space before preprocessor value */ 1361 if (isspace(c)) { 1362 if (c == '\n') { 1363 Ungetc(c, s); 1364 state = 50; 1365 } 1366 break; 1367 } 1368 state = 43; 1369 /* no break intended here */ 1370 1371 case 43: 1372 /* Get preprocessor value */ 1373 if (c == '\n') { 1374 Ungetc(c, s); 1375 state = 50; 1376 } else if (c == '/') { 1377 state = 45; 1378 } else if (c == '\"') { 1379 Putc(c, value); 1380 skip_tochar(s, '\"', value); 1381 } else if (c == '\'') { 1382 Putc(c, value); 1383 skip_tochar(s, '\'', value); 1384 } else { 1385 Putc(c, value); 1386 if (c == '\\') 1387 state = 44; 1388 } 1389 break; 1390 1391 case 44: 1392 if (c == '\n') { 1393 Putc(c, value); 1394 cpp_lines++; 1395 } else { 1396 Ungetc(c, s); 1397 } 1398 state = 43; 1399 break; 1400 1401 /* States 45-48 are used to remove, but retain comments from macro values. The comments 1402 will be placed in the output in an alternative form */ 1403 1404 case 45: 1405 if (c == '/') 1406 state = 46; 1407 else if (c == '*') 1408 state = 47; 1409 else if (c == '\n') { 1410 Putc('/', value); 1411 Ungetc(c, s); 1412 cpp_lines++; 1413 state = 50; 1414 } else { 1415 Putc('/', value); 1416 Putc(c, value); 1417 state = 43; 1418 } 1419 break; 1420 case 46: 1421 if (c == '\n') { 1422 Ungetc(c, s); 1423 cpp_lines++; 1424 state = 50; 1425 } else 1426 Putc(c, comment); 1427 break; 1428 case 47: 1429 if (c == '*') 1430 state = 48; 1431 else 1432 Putc(c, comment); 1433 break; 1434 case 48: 1435 if (c == '/') 1436 state = 43; 1437 else if (c == '*') 1438 Putc(c, comment); 1439 else { 1440 Putc('*', comment); 1441 Putc(c, comment); 1442 state = 47; 1443 } 1444 break; 1445 case 50: 1446 /* Check for various preprocessor directives */ 1447 Chop(value); 1448 if (Equal(id, kpp_define)) { 1449 if (allow) { 1450 DOH *m, *v, *v1; 1451 Seek(value, 0, SEEK_SET); 1452 m = Preprocessor_define(value, 0); 1453 if ((m) && !(Getattr(m, kpp_args))) { 1454 v = Copy(Getattr(m, kpp_value)); 1455 if (Len(v)) { 1456 Swig_error_silent(1); 1457 v1 = Preprocessor_replace(v); 1458 Swig_error_silent(0); 1459 /* Printf(stdout,"checking '%s'\n", v1); */ 1460 if (!checkpp_id(v1)) { 1461 if (Len(comment) == 0) 1462 Printf(ns, "%%constant %s = %s;\n", Getattr(m, kpp_name), v1); 1463 else 1464 Printf(ns, "%%constant %s = %s; /*%s*/\n", Getattr(m, kpp_name), v1, comment); 1465 cpp_lines--; 1466 } 1467 Delete(v1); 1468 } 1469 Delete(v); 1470 } 1471 } 1472 } else if (Equal(id, kpp_undef)) { 1473 if (allow) 1474 Preprocessor_undef(value); 1475 } else if (Equal(id, kpp_ifdef)) { 1476 cond_lines[level] = Getline(id); 1477 level++; 1478 if (allow) { 1479 start_level = level; 1480 /* See if the identifier is in the hash table */ 1481 if (!Getattr(symbols, value)) 1482 allow = 0; 1483 mask = 1; 1484 } 1485 } else if (Equal(id, kpp_ifndef)) { 1486 cond_lines[level] = Getline(id); 1487 level++; 1488 if (allow) { 1489 start_level = level; 1490 /* See if the identifier is in the hash table */ 1491 if (Getattr(symbols, value)) 1492 allow = 0; 1493 mask = 1; 1494 } 1495 } else if (Equal(id, kpp_else)) { 1496 if (level <= 0) { 1497 Swig_error(Getfile(s), Getline(id), "Misplaced #else.\n"); 1498 } else { 1499 cond_lines[level - 1] = Getline(id); 1500 if (allow) { 1501 allow = 0; 1502 mask = 0; 1503 } else if (level == start_level) { 1504 allow = 1 * mask; 1505 } 1506 } 1507 } else if (Equal(id, kpp_endif)) { 1508 level--; 1509 if (level < 0) { 1510 Swig_error(Getfile(id), Getline(id), "Extraneous #endif.\n"); 1511 level = 0; 1512 } else { 1513 if (level < start_level) { 1514 allow = 1; 1515 start_level--; 1516 } 1517 } 1518 } else if (Equal(id, kpp_if)) { 1519 cond_lines[level] = Getline(id); 1520 level++; 1521 if (allow) { 1522 int val; 1523 String *sval = Preprocessor_replace(value); 1524 start_level = level; 1525 Seek(sval, 0, SEEK_SET); 1526 /* Printf(stdout,"Evaluating '%s'\n", sval); */ 1527 val = Preprocessor_expr(sval, &e); 1528 if (e) { 1529 char *msg = Preprocessor_expr_error(); 1530 Seek(value, 0, SEEK_SET); 1531 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value); 1532 if (msg) 1533 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg); 1534 allow = 0; 1535 } else { 1536 if (val == 0) 1537 allow = 0; 1538 } 1539 mask = 1; 1540 } 1541 } else if (Equal(id, kpp_elif)) { 1542 if (level == 0) { 1543 Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n"); 1544 } else { 1545 cond_lines[level - 1] = Getline(id); 1546 if (allow) { 1547 allow = 0; 1548 mask = 0; 1549 } else if (level == start_level) { 1550 int val; 1551 String *sval = Preprocessor_replace(value); 1552 Seek(sval, 0, SEEK_SET); 1553 val = Preprocessor_expr(sval, &e); 1554 if (e) { 1555 char *msg = Preprocessor_expr_error(); 1556 Seek(value, 0, SEEK_SET); 1557 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate '%s'\n", value); 1558 if (msg) 1559 Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Error: '%s'\n", msg); 1560 allow = 0; 1561 } else { 1562 if (val) 1563 allow = 1 * mask; 1564 else 1565 allow = 0; 1566 } 1567 } 1568 } 1569 } else if (Equal(id, kpp_warning)) { 1570 if (allow) { 1571 Swig_warning(WARN_PP_CPP_WARNING, Getfile(s), Getline(id), "CPP #warning, %s\n", value); 1572 } 1573 } else if (Equal(id, kpp_error)) { 1574 if (allow) { 1575 if (error_as_warning) { 1576 Swig_warning(WARN_PP_CPP_ERROR, Getfile(s), Getline(id), "CPP #error \"%s\".\n", value); 1577 } else { 1578 Swig_error(Getfile(s), Getline(id), "CPP #error \"%s\". Use the -cpperraswarn option to continue swig processing.\n", value); 1579 } 1580 } 1581 } else if (Equal(id, kpp_line)) { 1582 } else if (Equal(id, kpp_include)) { 1583 if (((include_all) || (import_all)) && (allow)) { 1584 String *s1, *s2, *fn; 1585 char *dirname; 1586 int sysfile = 0; 1587 if (include_all && import_all) { 1588 Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall\n"); 1589 import_all = 0; 1590 } 1591 Seek(value, 0, SEEK_SET); 1592 fn = get_filename(value, &sysfile); 1593 s1 = cpp_include(fn, sysfile); 1594 if (s1) { 1595 if (include_all) 1596 Printf(ns, "%%includefile \"%s\" [\n", Swig_last_file()); 1597 else if (import_all) { 1598 Printf(ns, "%%importfile \"%s\" [\n", Swig_last_file()); 1599 push_imported(); 1600 } 1601 1602 /* See if the filename has a directory component */ 1603 dirname = Swig_file_dirname(Swig_last_file()); 1604 if (sysfile || !strlen(dirname)) 1605 dirname = 0; 1606 if (dirname) { 1607 dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */ 1608 Swig_push_directory(dirname); 1609 } 1610 s2 = Preprocessor_parse(s1); 1611 addline(ns, s2, allow); 1612 Append(ns, "\n]"); 1613 if (dirname) { 1614 Swig_pop_directory(); 1615 } 1616 if (import_all) { 1617 pop_imported(); 1618 } 1619 Delete(s2); 1620 } 1621 Delete(s1); 1622 Delete(fn); 1623 } 1624 } else if (Equal(id, kpp_pragma)) { 1625 if (Strncmp(value, "SWIG ", 5) == 0) { 1626 char *c = Char(value) + 5; 1627 while (*c && (isspace((int) *c))) 1628 c++; 1629 if (*c) { 1630 if (strncmp(c, "nowarn=", 7) == 0) { 1631 String *val = NewString(c + 7); 1632 String *nowarn = Preprocessor_replace(val); 1633 Swig_warnfilter(nowarn, 1); 1634 Delete(nowarn); 1635 Delete(val); 1636 } else if (strncmp(c, "cpperraswarn=", 13) == 0) { 1637 error_as_warning = atoi(c + 13); 1638 } else { 1639 Swig_error(Getfile(s), Getline(id), "Unknown SWIG pragma: %s\n", c); 1640 } 1641 } 1642 } 1643 } else if (Equal(id, kpp_level)) { 1644 Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level); 1645 } 1646 for (i = 0; i < cpp_lines; i++) 1647 Putc('\n', ns); 1648 state = 0; 1649 break; 1650 1651 /* Swig directives */ 1652 case 100: 1653 /* %{,%} block */ 1654 if (c == '{') { 1655 start_line = Getline(s); 1656 add_chunk(ns, chunk, allow); 1657 copy_location(s, chunk); 1658 Putc('%', chunk); 1659 Putc(c, chunk); 1660 state = 105; 1661 } 1662 /* %#cpp - an embedded C preprocessor directive (we strip off the %) */ 1663 else if (c == '#') { 1664 add_chunk(ns, chunk, allow); 1665 Putc(c, chunk); 1666 state = 107; 1667 } else if (isidentifier(c)) { 1668 Clear(decl); 1669 Putc('%', decl); 1670 Putc(c, decl); 1671 state = 110; 1672 } else { 1673 Putc('%', chunk); 1674 Putc(c, chunk); 1675 state = 1; 1676 } 1677 break; 1678 1679 case 105: 1680 Putc(c, chunk); 1681 if (c == '%') 1682 state = 106; 1683 break; 1684 1685 case 106: 1686 Putc(c, chunk); 1687 if (c == '}') { 1688 state = 1; 1689 addline(ns, chunk, allow); 1690 Clear(chunk); 1691 copy_location(s, chunk); 1692 } else { 1693 state = 105; 1694 } 1695 break; 1696 1697 case 107: 1698 Putc(c, chunk); 1699 if (c == '\n') { 1700 addline(ns, chunk, allow); 1701 Clear(chunk); 1702 state = 0; 1703 } else if (c == '\\') { 1704 state = 108; 1705 } 1706 break; 1707 1708 case 108: 1709 Putc(c, chunk); 1710 state = 107; 1711 break; 1712 1713 case 110: 1714 if (!isidchar(c)) { 1715 Ungetc(c, s); 1716 /* Look for common Swig directives */ 1717 if (Equal(decl, kpp_dinclude) || Equal(decl, kpp_dimport) || Equal(decl, kpp_dextern)) { 1718 /* Got some kind of file inclusion directive */ 1719 if (allow) { 1720 DOH *s1, *s2, *fn, *opt; 1721 int sysfile = 0; 1722 1723 if (Equal(decl, kpp_dextern)) { 1724 Swig_warning(WARN_DEPRECATED_EXTERN, Getfile(s), Getline(s), "%%extern is deprecated. Use %%import instead.\n"); 1725 Clear(decl); 1726 Append(decl, "%%import"); 1727 } 1728 opt = get_options(s); 1729 fn = get_filename(s, &sysfile); 1730 s1 = cpp_include(fn, sysfile); 1731 if (s1) { 1732 char *dirname; 1733 add_chunk(ns, chunk, allow); 1734 copy_location(s, chunk); 1735 Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_last_file()); 1736 if (Equal(decl, kpp_dimport)) { 1737 push_imported(); 1738 } 1739 dirname = Swig_file_dirname(Swig_last_file()); 1740 if (sysfile || !strlen(dirname)) 1741 dirname = 0; 1742 if (dirname) { 1743 dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */ 1744 Swig_push_directory(dirname); 1745 } 1746 s2 = Preprocessor_parse(s1); 1747 if (dirname) { 1748 Swig_pop_directory(); 1749 } 1750 if (Equal(decl, kpp_dimport)) { 1751 pop_imported(); 1752 } 1753 addline(ns, s2, allow); 1754 Append(ns, "\n]"); 1755 Delete(s2); 1756 Delete(s1); 1757 } 1758 Delete(fn); 1759 } 1760 state = 1; 1761 } else if (Equal(decl, kpp_dline)) { 1762 /* Got a line directive */ 1763 state = 1; 1764 } else if (Equal(decl, kpp_ddefine)) { 1765 /* Got a define directive */ 1766 dlevel++; 1767 add_chunk(ns, chunk, allow); 1768 copy_location(s, chunk); 1769 Clear(value); 1770 copy_location(s, value); 1771 state = 150; 1772 } else { 1773 Append(chunk, decl); 1774 state = 1; 1775 } 1776 } else { 1777 Putc(c, decl); 1778 } 1779 break; 1780 1781 /* Searching for the end of a %define statement */ 1782 case 150: 1783 Putc(c, value); 1784 if (c == '%') { 1785 const char *ed = "enddef"; 1786 const char *df = "define"; 1787 char statement[7]; 1788 int i = 0; 1789 for (i = 0; i < 6;) { 1790 c = Getc(s); 1791 Putc(c, value); 1792 statement[i++] = (char)c; 1793 if (strncmp(statement, ed, i) && strncmp(statement, df, i)) 1794 break; 1795 } 1796 c = Getc(s); 1797 Ungetc(c, s); 1798 if ((i == 6) && (isspace(c))) { 1799 if (strncmp(statement, df, i) == 0) { 1800 ++dlevel; 1801 } else { 1802 if (strncmp(statement, ed, i) == 0) { 1803 --dlevel; 1804 if (!dlevel) { 1805 /* Got the macro */ 1806 for (i = 0; i < 7; i++) { 1807 Delitem(value, DOH_END); 1808 } 1809 if (allow) { 1810 Seek(value, 0, SEEK_SET); 1811 Preprocessor_define(value, 1); 1812 } 1813 /* Putc('\n',ns); */ 1814 addline(ns, value, 0); 1815 state = 0; 1816 } 1817 } 1818 } 1819 } 1820 } 1821 break; 1822 default: 1823 Printf(stderr, "cpp: Invalid parser state %d\n", state); 1824 abort(); 1825 break; 1826 } 1827 } 1828 while (level > 0) { 1829 Swig_error(Getfile(s), -1, "Missing #endif for conditional starting on line %d\n", cond_lines[level - 1]); 1830 level--; 1831 } 1832 if (state == 150) { 1833 Seek(value, 0, SEEK_SET); 1834 Swig_error(Getfile(s), -1, "Missing %%enddef for macro starting on line %d\n", Getline(value)); 1835 } 1836 if ((state >= 105) && (state < 107)) { 1837 Swig_error(Getfile(s), -1, "Unterminated %%{ ... %%} block starting on line %d\n", start_line); 1838 } 1839 if ((state >= 30) && (state < 40)) { 1840 Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line); 1841 } 1842 add_chunk(ns, chunk, allow); 1843 copy_location(s, chunk); 1844 1845 /* DelScope(scp); */ 1846 Delete(decl); 1847 Delete(id); 1848 Delete(value); 1849 Delete(comment); 1850 Delete(chunk); 1851 1852 /* fprintf(stderr,"cpp: %d\n", Len(Getattr(cpp,"symbols"))); */ 1853 return ns; 1854} 1855