1/* This is the Assembler Pre-Processor 2 Copyright (C) 1987 Free Software Foundation, Inc. 3 4This file is part of GAS, the GNU Assembler. 5 6GAS is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 1, or (at your option) 9any later version. 10 11GAS is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GAS; see the file COPYING. If not, write to 18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 20/* App, the assembler pre-processor. This pre-processor strips out excess 21 spaces, turns single-quoted characters into a decimal constant, and turns 22 # <number> <filename> <garbage> into a .line <number>;.file <filename> pair. 23 This needs better error-handling. 24 */ 25#include <stdio.h> 26#include <string.h> 27#include "as.h" 28#include "md.h" 29#include "app.h" 30#include "messages.h" 31 32FILE *scrub_file = NULL; 33char *scrub_string = NULL; 34char *scrub_last_string = NULL; 35 36#ifdef NeXT_MOD /* .include feature */ 37/* These are moved out of do_scrub() so save_scrub_context() can save them */ 38static int state; 39#ifdef I386 40static int substate = 0; 41#endif 42static int old_state; 43static char *out_string; 44static char out_buf[20]; 45static int add_newlines = 0; 46#endif /* NeXT_MOD .include feature */ 47 48static char lex [256]; 49static char symbol_chars[] = 50 "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 51 52#define LEX_IS_SYMBOL_COMPONENT (1) 53#define LEX_IS_WHITESPACE (2) 54#define LEX_IS_LINE_SEPERATOR (4) 55#define LEX_IS_COMMENT_START (8) /* JF added these two */ 56#define LEX_IS_LINE_COMMENT_START (16) 57#define IS_SYMBOL_COMPONENT(c) (lex [c] & LEX_IS_SYMBOL_COMPONENT) 58#define IS_WHITESPACE(c) (lex [c] & LEX_IS_WHITESPACE) 59#define IS_LINE_SEPERATOR(c) (lex [c] & LEX_IS_LINE_SEPERATOR) 60#define IS_COMMENT(c) (lex [c] & LEX_IS_COMMENT_START) 61#define IS_LINE_COMMENT(c) (lex [c] & LEX_IS_LINE_COMMENT_START) 62 63void 64do_scrub_begin( 65void) 66{ 67 char *p; 68 const char *q; 69 70 memset(lex, '\0', sizeof(lex)); /* Trust NOBODY! */ 71 lex [' '] |= LEX_IS_WHITESPACE; 72 lex ['\t'] |= LEX_IS_WHITESPACE; 73 lex ['\r'] |= LEX_IS_WHITESPACE; 74 for (p =symbol_chars;*p;++p) 75 lex [(int)*p] |= LEX_IS_SYMBOL_COMPONENT; 76 lex ['\n'] |= LEX_IS_LINE_SEPERATOR; 77#ifdef PPC 78 if(flagseen[(int)'p'] == TRUE) 79 lex ['\r'] |= LEX_IS_LINE_SEPERATOR; 80#endif /* PPC */ 81#ifndef DONTDEF 82#ifdef NeXT_MOD 83 /* 84 * This DOES not cause ':' to be a LINE SEPERATOR but does make the 85 * second if logic after flushchar: in do_scrub_next_char() to handle 86 * "foo :" and strip the blanks. This is the way has always been and 87 * must be this way to work. 88 */ 89#endif /* NeXT_MOD */ 90 lex [':'] |= LEX_IS_LINE_SEPERATOR; 91#endif /* !defined(DONTDEF) */ 92 93#if defined(M88K) || defined(PPC) || defined(HPPA) 94#ifdef PPC 95 if(flagseen[(int)'p'] == FALSE) 96#endif /* PPC */ 97 lex ['@'] |= LEX_IS_LINE_SEPERATOR; 98#else 99 lex [';'] |= LEX_IS_LINE_SEPERATOR; 100#endif 101 for (q=md_comment_chars;*q;q++) 102 lex[(int)*q] |= LEX_IS_COMMENT_START; 103 for (q=md_line_comment_chars;*q;q++) 104 lex[(int)*q] |= LEX_IS_LINE_COMMENT_START; 105} 106 107static inline int 108scrub_from_string( 109void) 110{ 111 return scrub_string == scrub_last_string ? EOF : *scrub_string++; 112} 113 114static inline void 115scrub_to_string( 116int ch) 117{ 118 *--scrub_string = ch; 119} 120 121int 122do_scrub_next_char( 123FILE *fp) 124{ 125 /* State 0: beginning of normal line 126 1: After first whitespace on normal line (flush more white) 127 2: After first non-white on normal line (keep 1white) 128 3: after second white on normal line (flush white) 129 4: after putting out a .line, put out digits 130 5: parsing a string, then go to old-state 131 6: putting out \ escape in a "d string. 132 7: After putting out a .file, put out string. 133 8: After putting out a .file string, flush until newline. 134 FROM line 358 135 9: After seeing symbol char in state 3 (keep 1white after symchar) 136 10: After seeing whitespace in state 9 (keep white before symchar) 137 -1: output string in out_string and go to the state in old_state 138 -2: flush text until a '*' '/' is seen, then go to state old_state 139 */ 140 141 142 /* FROM line 379 */ 143 /* I added states 9 and 10 because the MIPS ECOFF assembler uses 144 constructs like ``.loc 1 20''. This was turning into ``.loc 145 120''. States 9 and 10 ensure that a space is never dropped in 146 between characters which could appear in an identifier. Ian 147 Taylor, ian@cygnus.com. */ 148 149#ifndef NeXT_MOD /* .include feature */ 150 static state; 151 static old_state; 152 static char *out_string; 153 static char out_buf[20]; 154 static add_newlines = 0; 155#endif /* NeXT_MOD .include feature */ 156 int ch; 157 158 if(state==-1) { 159 ch= *out_string++; 160 if(*out_string==0) { 161 state=old_state; 162 old_state=3; 163 } 164 return ch; 165 } 166 if(state==-2) { 167 for(;;) { 168 do ch=getc_unlocked(fp); 169 while(ch!=EOF && ch!='\n' && ch!='*'); 170 if(ch=='\n' || ch==EOF) 171 return ch; 172 ch=getc_unlocked(fp); 173 if(ch==EOF || ch=='/') 174 break; 175 ungetc(ch, fp); 176 } 177 state=old_state; 178 return ' '; 179 } 180 if(state==4) { 181 ch=getc_unlocked(fp); 182 if(ch==EOF || (ch>='0' && ch<='9')) 183 return ch; 184 else { 185 while(ch!=EOF && IS_WHITESPACE(ch)) 186 ch=getc_unlocked(fp); 187 if(ch=='"') { 188 ungetc(ch, fp); 189#if defined(M88K) || defined(PPC) || defined(HPPA) 190 out_string="@ .file "; 191#else 192 out_string="; .file "; 193#endif 194 old_state=7; 195 state= -1; 196 return *out_string++; 197 } else { 198 while(ch!=EOF && ch!='\n') 199 ch=getc_unlocked(fp); 200#ifdef NeXT_MOD 201 /* bug fix for bug #8918, which was when 202 * a full line comment line this: 203 * # 40 MP1 = M + 1 204 * got confused with a cpp output like: 205 * # 1 "hello.c" 1 206 */ 207 state = 0; 208#endif /* NeXT_MOD */ 209 return ch; 210 } 211 } 212 } 213 if(state==5) { 214 ch=getc_unlocked(fp); 215#ifdef PPC 216 if(flagseen[(int)'p'] == TRUE && ch=='\'') { 217 state=old_state; 218 return '\''; 219 } else 220#endif /* PPC */ 221 if(ch=='"') { 222 state=old_state; 223 return '"'; 224 } else if(ch=='\\') { 225 state=6; 226 return ch; 227 } else if(ch==EOF) { 228 state=old_state; 229 ungetc('\n', fp); 230#ifdef PPC 231 if(flagseen[(int)'p'] == TRUE){ 232 as_warn("End of file in string: inserted '\''"); 233 return '\''; 234 } 235#endif /* PPC */ 236 as_warn("End of file in string: inserted '\"'"); 237 return '"'; 238 } else { 239 return ch; 240 } 241 } 242 if(state==6) { 243 state=5; 244 ch=getc_unlocked(fp); 245 switch(ch) { 246 /* This is neet. Turn "string 247 more string" into "string\n more string" 248 */ 249 case '\n': 250 ungetc('n', fp); 251 add_newlines++; 252 return '\\'; 253 254 case '\'': 255 case '"': 256 case '\\': 257 case 'b': 258 case 'f': 259 case 'n': 260 case 'r': 261 case 't': 262 case '0': 263 case '1': 264 case '2': 265 case '3': 266 case '4': 267 case '5': 268 case '6': 269 case '7': 270 break; 271 default: 272 as_warn("Unknown escape '\\%c' in string: Ignored",ch); 273 break; 274 275 case EOF: 276 as_warn("End of file in string: '\"' inserted"); 277 return '"'; 278 } 279 return ch; 280 } 281 282 if(state==7) { 283 ch=getc_unlocked(fp); 284 state=5; 285 old_state=8; 286 return ch; 287 } 288 289 if(state==8) { 290 do ch= getc_unlocked(fp); 291 while(ch!='\n'); 292 state=0; 293#ifdef I386 294 substate = 0; 295#endif 296 return ch; 297 } 298 299 flushchar: 300 ch=getc_unlocked(fp); 301 switch(ch) { 302 case ' ': 303 case '\t': 304 do ch=getc_unlocked(fp); 305 while(ch!=EOF && IS_WHITESPACE(ch)); 306 if(ch==EOF) 307 return ch; 308 if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) { 309 ungetc(ch, fp); 310 goto flushchar; 311 } 312 ungetc(ch, fp); 313 if(state==0 || state==2) { 314#ifdef I386 315 if(state == 2){ 316 if(substate == 0){ 317 /* if in state 2 don't change to state 3 318 the first time, and leave white space 319 after the first two tokens */ 320 substate = 1; 321 return ' '; 322 } 323 substate = 0; 324 } 325#endif 326 state++; 327 return ' '; 328 } 329#ifdef PPC 330 if(flagseen[(int)'p'] == TRUE && state == 3){ 331 return ' '; 332 } 333#endif 334 /* FROM line 900 */ 335 if (state == 9) 336 state = 10; 337 goto flushchar; 338 339 case '/': 340 ch=getc_unlocked(fp); 341 if(ch=='*') { 342 for(;;) { 343 do { 344 ch=getc_unlocked(fp); 345 if(ch=='\n') 346 add_newlines++; 347 } while(ch!=EOF && ch!='*'); 348 ch=getc_unlocked(fp); 349 if(ch==EOF || ch=='/') 350 break; 351 ungetc(ch, fp); 352 } 353 if(ch==EOF) 354 as_warn("End of file in '/' '*' string: */ inserted"); 355 356 ungetc(' ', fp); 357 goto flushchar; 358 } else { 359#if defined(I860) || defined(M88K) || defined(PPC) || defined(I386) || \ 360 defined(HPPA) || defined (SPARC) 361 if (ch == '/') { 362 do { 363 ch=getc_unlocked(fp); 364 } while (ch != EOF && (ch != '\n')); 365 if (ch == EOF) 366 as_warn("End of file before newline in // comment"); 367 if ( ch == '\n' ) /* Push NL back so we can complete state */ 368 ungetc(ch, fp); 369 goto flushchar; 370 } 371#endif 372 if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) { 373 ungetc(ch, fp); 374 ch='/'; 375 goto deal_misc; 376 } 377 if(ch!=EOF) 378 ungetc(ch, fp); 379 return '/'; 380 } 381 break; 382 383 case '"': 384 old_state=state; 385 state=5; 386 return '"'; 387 break; 388 389 case '\'': 390#ifdef PPC 391 if(flagseen[(int)'p'] == TRUE){ 392 old_state=state; 393 state=5; 394 return '\''; 395 break; 396 } 397#endif 398 ch=getc_unlocked(fp); 399 if(ch==EOF) { 400 as_warn("End-of-file after a ': \\000 inserted"); 401 ch=0; 402 } 403 sprintf(out_buf,"(%d)",ch&0xff); 404 old_state=state; 405 state= -1; 406 out_string=out_buf; 407 return *out_string++; 408 409 case ':': 410 if(state!=3) { 411 state=0; 412#ifdef I386 413 substate = 0; 414#endif 415 } 416 return ch; 417 418 case '\n': 419 if(add_newlines) { 420 --add_newlines; 421 ungetc(ch, fp); 422 } 423 /* Fall through. */ 424#if defined(M88K) || defined(PPC) || defined(HPPA) 425 case '@': 426#else 427 case ';': 428#endif 429 state=0; 430#ifdef I386 431 substate = 0; 432#endif 433 return ch; 434 435 default: 436 deal_misc: 437 /* FROM line 1234 */ 438 if (IS_SYMBOL_COMPONENT (ch)) 439 { 440 if (state == 10) 441 { 442 /* This is a symbol character following another symbol 443 character, with whitespace in between. We skipped 444 the whitespace earlier, so output it now. */ 445 ungetc(ch, fp); 446 state = 3; 447 ch = ' '; 448 return ch; 449 } 450 451 if (state == 3) 452 state = 9; 453 } 454 /* FROM line 1321 */ 455 else if (state == 9) 456 { 457 /* FROM line 1324 */ 458 state = 3; 459 } 460 else if (state == 10) 461 /* FROM line 1345 */ 462 state = 3; 463 464 if(state==0 && IS_LINE_COMMENT(ch)) { 465 do ch=getc_unlocked(fp); 466 while(ch!=EOF && IS_WHITESPACE(ch)); 467 if(ch==EOF) { 468 as_warn("EOF in comment: Newline inserted"); 469 return '\n'; 470 } 471 if(ch<'0' || ch>'9') { 472 if(ch!='\n'){ 473 do ch=getc_unlocked(fp); 474 while(ch!=EOF && ch!='\n'); 475 } 476 if(ch==EOF) 477 as_warn("EOF in Comment: Newline inserted"); 478 state=0; 479#ifdef I386 480 substate = 0; 481#endif 482 return '\n'; 483 } 484 ungetc(ch, fp); 485 old_state=4; 486 state= -1; 487 out_string=".line "; 488 return *out_string++; 489 490 } else if(IS_COMMENT(ch)) { 491 do ch=getc_unlocked(fp); 492 while(ch!=EOF && ch!='\n'); 493 if(ch==EOF) 494 as_warn("EOF in comment: Newline inserted"); 495 state=0; 496#ifdef I386 497 substate = 0; 498#endif 499 return '\n'; 500 501 } else if(state==0) { 502 state=2; 503 return ch; 504 } else if(state==1) { 505 state=2; 506 return ch; 507 } else { 508 return ch; 509 510 } 511 case EOF: 512 if(state==0) 513 return ch; 514 as_warn("End-of-File not at end of a line"); 515 } 516 return -1; 517} 518 519int 520do_scrub_next_char_from_string() 521{ 522 /* State 0: beginning of normal line 523 1: After first whitespace on normal line (flush more white) 524 2: After first non-white on normal line (keep 1white) 525 3: after second white on normal line (flush white) 526 4: after putting out a .line, put out digits 527 5: parsing a string, then go to old-state 528 6: putting out \ escape in a "d string. 529 7: After putting out a .file, put out string. 530 8: After putting out a .file string, flush until newline. 531 -1: output string in out_string and go to the state in old_state 532 -2: flush text until a '*' '/' is seen, then go to state old_state 533 */ 534 535#ifndef NeXT_MOD /* .include feature */ 536 static state; 537 static old_state; 538 static char *out_string; 539 static char out_buf[20]; 540 static add_newlines = 0; 541#endif /* NeXT_MOD .include feature */ 542 int ch; 543 544 if(state==-1) { 545 ch= *out_string++; 546 if(*out_string==0) { 547 state=old_state; 548 old_state=3; 549 } 550 return ch; 551 } 552 if(state==-2) { 553 for(;;) { 554 do ch=scrub_from_string(); 555 while(ch!=EOF && ch!='\n' && ch!='*'); 556 if(ch=='\n' || ch==EOF) 557 return ch; 558 ch=scrub_from_string(); 559 if(ch==EOF || ch=='/') 560 break; 561 scrub_to_string(ch); 562 } 563 state=old_state; 564 return ' '; 565 } 566 if(state==4) { 567 ch=scrub_from_string(); 568 if(ch==EOF || (ch>='0' && ch<='9')) 569 return ch; 570 else { 571 while(ch!=EOF && IS_WHITESPACE(ch)) 572 ch=scrub_from_string(); 573 if(ch=='"') { 574 scrub_to_string(ch); 575#if defined(M88K) || defined(PPC) || defined(HPPA) 576 out_string="@ .file "; 577#else 578 out_string="; .file "; 579#endif 580 old_state=7; 581 state= -1; 582 return *out_string++; 583 } else { 584 while(ch!=EOF && ch!='\n') 585 ch=scrub_from_string(); 586#ifdef NeXT_MOD 587 /* bug fix for bug #8918, which was when 588 * a full line comment line this: 589 * # 40 MP1 = M + 1 590 * got confused with a cpp output like: 591 * # 1 "hello.c" 1 592 */ 593 state = 0; 594#endif /* NeXT_MOD */ 595 return ch; 596 } 597 } 598 } 599 if(state==5) { 600 ch=scrub_from_string(); 601#ifdef PPC 602 if(flagseen[(int)'p'] == TRUE && ch=='\'') { 603 state=old_state; 604 return '\''; 605 } else 606#endif /* PPC */ 607 if(ch=='"') { 608 state=old_state; 609 return '"'; 610 } else if(ch=='\\') { 611 state=6; 612 return ch; 613 } else if(ch==EOF) { 614 state=old_state; 615 scrub_to_string('\n'); 616#ifdef PPC 617 if(flagseen[(int)'p'] == TRUE){ 618 as_warn("End of file in string: inserted '\''"); 619 return '\''; 620 } 621#endif /* PPC */ 622 as_warn("End of file in string: inserted '\"'"); 623 return '"'; 624 } else { 625 return ch; 626 } 627 } 628 if(state==6) { 629 state=5; 630 ch=scrub_from_string(); 631 switch(ch) { 632 /* This is neet. Turn "string 633 more string" into "string\n more string" 634 */ 635 case '\n': 636 scrub_to_string('n'); 637 add_newlines++; 638 return '\\'; 639 640 case '"': 641 case '\\': 642 case 'b': 643 case 'f': 644 case 'n': 645 case 'r': 646 case 't': 647 case '0': 648 case '1': 649 case '2': 650 case '3': 651 case '4': 652 case '5': 653 case '6': 654 case '7': 655 break; 656 default: 657 as_warn("Unknown escape '\\%c' in string: Ignored",ch); 658 break; 659 660 case EOF: 661 as_warn("End of file in string: '\"' inserted"); 662 return '"'; 663 } 664 return ch; 665 } 666 667 if(state==7) { 668 ch=scrub_from_string(); 669 state=5; 670 old_state=8; 671 return ch; 672 } 673 674 if(state==8) { 675 do ch= scrub_from_string(); 676 while(ch!='\n'); 677 state=0; 678#ifdef I386 679 substate = 0; 680#endif 681 return ch; 682 } 683 684 flushchar: 685 ch=scrub_from_string(); 686 switch(ch) { 687 case ' ': 688 case '\t': 689 do ch=scrub_from_string(); 690 while(ch!=EOF && IS_WHITESPACE(ch)); 691 if(ch==EOF) 692 return ch; 693 if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) { 694 scrub_to_string(ch); 695 goto flushchar; 696 } 697 scrub_to_string(ch); 698 if(state==0 || state==2) { 699 state++; 700 return ' '; 701 } 702#ifdef PPC 703 if(flagseen[(int)'p'] == TRUE && state == 3){ 704 return ' '; 705 } 706#endif 707 else goto flushchar; 708 709 case '/': 710 ch=scrub_from_string(); 711 if(ch=='*') { 712 for(;;) { 713 do { 714 ch=scrub_from_string(); 715 if(ch=='\n') 716 add_newlines++; 717 } while(ch!=EOF && ch!='*'); 718 ch=scrub_from_string(); 719 if(ch==EOF || ch=='/') 720 break; 721 scrub_to_string(ch); 722 } 723 if(ch==EOF) 724 as_warn("End of file in '/' '*' string: */ inserted"); 725 726 scrub_to_string(' '); 727 goto flushchar; 728 } else { 729#if defined(I860) || defined(M88K) || defined(PPC) || defined(I386) || \ 730 defined(HPPA) || defined (SPARC) 731 if (ch == '/') { 732 do { 733 ch=scrub_from_string(); 734 } while (ch != EOF && (ch != '\n')); 735 if (ch == EOF) 736 as_warn("End of file before newline in // comment"); 737 if ( ch == '\n' ) /* Push NL back so we can complete state */ 738 scrub_to_string(ch); 739 goto flushchar; 740 } 741#endif 742 if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) { 743 scrub_to_string(ch); 744 ch='/'; 745 goto deal_misc; 746 } 747 if(ch!=EOF) 748 scrub_to_string(ch); 749 return '/'; 750 } 751 break; 752 753 case '"': 754 old_state=state; 755 state=5; 756 return '"'; 757 break; 758 759 case '\'': 760#ifdef PPC 761 if(flagseen[(int)'p'] == TRUE){ 762 old_state=state; 763 state=5; 764 return '\''; 765 break; 766 } 767#endif 768 ch=scrub_from_string(); 769 if(ch==EOF) { 770 as_warn("End-of-file after a ': \\000 inserted"); 771 ch=0; 772 } 773 sprintf(out_buf,"(%d)",ch&0xff); 774 old_state=state; 775 state= -1; 776 out_string=out_buf; 777 return *out_string++; 778 779 case ':': 780 if(state!=3) { 781 state=0; 782#ifdef I386 783 substate = 0; 784#endif 785 } 786 return ch; 787 788 case '\n': 789 if(add_newlines) { 790 --add_newlines; 791 scrub_to_string(ch); 792 } 793 /* Fall through. */ 794#if defined(M88K) || defined(PPC) || defined(HPPA) 795 case '@': 796#else 797 case ';': 798#endif 799 state=0; 800#ifdef I386 801 substate = 0; 802#endif 803 return ch; 804 805 default: 806 deal_misc: 807 if(state==0 && IS_LINE_COMMENT(ch)) { 808 do ch=scrub_from_string(); 809 while(ch!=EOF && IS_WHITESPACE(ch)); 810 if(ch==EOF) { 811 as_warn("EOF in comment: Newline inserted"); 812 return '\n'; 813 } 814 if(ch<'0' || ch>'9') { 815 if(ch!='\n'){ 816 do ch=scrub_from_string(); 817 while(ch!=EOF && ch!='\n'); 818 } 819 if(ch==EOF) 820 as_warn("EOF in Comment: Newline inserted"); 821 state=0; 822#ifdef I386 823 substate = 0; 824#endif 825 return '\n'; 826 } 827 scrub_to_string(ch); 828 old_state=4; 829 state= -1; 830 out_string=".line "; 831 return *out_string++; 832 833 } else if(IS_COMMENT(ch)) { 834 do ch=scrub_from_string(); 835 while(ch!=EOF && ch!='\n'); 836 if(ch==EOF) 837 as_warn("EOF in comment: Newline inserted"); 838 state=0; 839#ifdef I386 840 substate = 0; 841#endif 842 return '\n'; 843 844 } else if(state==0) { 845 state=2; 846 return ch; 847 } else if(state==1) { 848 state=2; 849 return ch; 850 } else { 851 return ch; 852 853 } 854 case EOF: 855 if(state==0) 856 return ch; 857 as_warn("End-of-File not at end of a line"); 858 } 859 return -1; 860} 861 862 863#ifdef NeXT_MOD /* .include feature */ 864void 865save_scrub_context( 866scrub_context_data *save_buffer_ptr) 867{ 868 save_buffer_ptr->last_scrub_file = scrub_file; 869 save_buffer_ptr->last_state = state; 870 save_buffer_ptr->last_old_state = old_state; 871 save_buffer_ptr->last_out_string = out_string; 872 memcpy(save_buffer_ptr->last_out_buf, out_buf, sizeof(out_buf)); 873 save_buffer_ptr->last_add_newlines = add_newlines; 874 875 state = 0; 876 old_state = 0; 877 out_string = NULL; 878 memset(out_buf, '\0', sizeof(out_buf)); 879 add_newlines = 0; 880} 881 882void 883restore_scrub_context( 884scrub_context_data *save_buffer_ptr) 885{ 886 scrub_file = save_buffer_ptr->last_scrub_file; 887 state = save_buffer_ptr->last_state; 888 old_state = save_buffer_ptr->last_old_state; 889 out_string = save_buffer_ptr->last_out_string; 890 memcpy(out_buf, save_buffer_ptr->last_out_buf, sizeof(out_buf)); 891 add_newlines = save_buffer_ptr->last_add_newlines; 892} 893#endif /* NeXT_MOD .include feature */ 894 895#ifdef TEST 896#include <stdarg.h> 897 898const char md_comment_chars[] = "|"; 899const char md_line_comment_chars[] = "#"; 900 901#ifdef PPC 902/* ['x'] TRUE if "-x" seen. */ 903char flagseen[128] = { 0 }; 904#endif 905 906int 907main( 908int argc, 909char *argv[], 910char *envp[]) 911{ 912 int ch; 913#ifdef PPC 914 if(argc > 1 && strncmp(argv[1], "-p", 2) == 0) 915 flagseen[(int)'p'] = TRUE; 916#endif 917 918 while((ch = do_scrub_next_char(stdin)) != EOF) 919 putc(ch, stdout); 920 return(0); 921} 922 923void 924as_warn( 925const char *format, 926...) 927{ 928 va_list ap; 929 930 va_start(ap, format); 931 vfprintf(stderr, format, ap); 932 fprintf(stderr, "\n"); 933 va_end(ap); 934} 935#endif /* TEST */ 936