|
|
1.1 ! root 1: /* This is the Assembler Pre-Processor ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the 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: ! 32: FILE *scrub_file = NULL; ! 33: char *scrub_string = NULL; ! 34: char *scrub_last_string = NULL; ! 35: ! 36: #ifdef NeXT /* .include feature */ ! 37: /* These are moved out of do_scrub() so save_scrub_context() can save them */ ! 38: static state; ! 39: static old_state; ! 40: static char *out_string; ! 41: static char out_buf[20]; ! 42: static add_newlines = 0; ! 43: #endif /* NeXT .include feature */ ! 44: ! 45: static char lex [256]; ! 46: static char symbol_chars[] = ! 47: "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; ! 48: ! 49: #define LEX_IS_SYMBOL_COMPONENT (1) ! 50: #define LEX_IS_WHITESPACE (2) ! 51: #define LEX_IS_LINE_SEPERATOR (4) ! 52: #define LEX_IS_COMMENT_START (8) /* JF added these two */ ! 53: #define LEX_IS_LINE_COMMENT_START (16) ! 54: #define IS_SYMBOL_COMPONENT(c) (lex [c] & LEX_IS_SYMBOL_COMPONENT) ! 55: #define IS_WHITESPACE(c) (lex [c] & LEX_IS_WHITESPACE) ! 56: #define IS_LINE_SEPERATOR(c) (lex [c] & LEX_IS_LINE_SEPERATOR) ! 57: #define IS_COMMENT(c) (lex [c] & LEX_IS_COMMENT_START) ! 58: #define IS_LINE_COMMENT(c) (lex [c] & LEX_IS_LINE_COMMENT_START) ! 59: ! 60: void ! 61: do_scrub_begin( ! 62: void) ! 63: { ! 64: char *p; ! 65: const char *q; ! 66: ! 67: memset(lex, '\0', sizeof(lex)); /* Trust NOBODY! */ ! 68: lex [' '] |= LEX_IS_WHITESPACE; ! 69: lex ['\t'] |= LEX_IS_WHITESPACE; ! 70: for (p =symbol_chars;*p;++p) ! 71: lex [(int)*p] |= LEX_IS_SYMBOL_COMPONENT; ! 72: lex ['\n'] |= LEX_IS_LINE_SEPERATOR; ! 73: #ifndef DONTDEF ! 74: #ifdef NeXT ! 75: /* ! 76: * This DOES not cause ':' to be a LINE SEPERATOR but does make the ! 77: * second if logic after flushchar: in do_scrub_next_char() to handle ! 78: * "foo :" and strip the blanks. This is the way has always been and ! 79: * must be this way to work. ! 80: */ ! 81: #endif /* NeXT */ ! 82: lex [':'] |= LEX_IS_LINE_SEPERATOR; ! 83: #endif /* !defined(DONTDEF) */ ! 84: ! 85: #if defined(M88K) || defined(M98K) || defined(HPPA) ! 86: lex ['@'] |= LEX_IS_LINE_SEPERATOR; ! 87: #else ! 88: lex [';'] |= LEX_IS_LINE_SEPERATOR; ! 89: #endif ! 90: for (q=md_comment_chars;*q;q++) ! 91: lex[(int)*q] |= LEX_IS_COMMENT_START; ! 92: for (q=md_line_comment_chars;*q;q++) ! 93: lex[(int)*q] |= LEX_IS_LINE_COMMENT_START; ! 94: } ! 95: ! 96: int ! 97: scrub_from_file( ! 98: void) ! 99: { ! 100: return getc(scrub_file); ! 101: } ! 102: ! 103: void ! 104: scrub_to_file( ! 105: int ch) ! 106: { ! 107: ungetc(ch, scrub_file); ! 108: } ! 109: ! 110: int ! 111: scrub_from_string( ! 112: void) ! 113: { ! 114: return scrub_string == scrub_last_string ? EOF : *scrub_string++; ! 115: } ! 116: ! 117: void ! 118: scrub_to_string( ! 119: int ch) ! 120: { ! 121: *--scrub_string = ch; ! 122: } ! 123: ! 124: int ! 125: do_scrub_next_char( ! 126: int (*get)(void), ! 127: void (*unget)(int ch)) ! 128: /* FILE *fp; */ ! 129: { ! 130: /* State 0: beginning of normal line ! 131: 1: After first whitespace on normal line (flush more white) ! 132: 2: After first non-white on normal line (keep 1white) ! 133: 3: after second white on normal line (flush white) ! 134: 4: after putting out a .line, put out digits ! 135: 5: parsing a string, then go to old-state ! 136: 6: putting out \ escape in a "d string. ! 137: 7: After putting out a .file, put out string. ! 138: 8: After putting out a .file string, flush until newline. ! 139: -1: output string in out_string and go to the state in old_state ! 140: -2: flush text until a '*' '/' is seen, then go to state old_state ! 141: */ ! 142: ! 143: #ifndef NeXT /* .include feature */ ! 144: static state; ! 145: static old_state; ! 146: static char *out_string; ! 147: static char out_buf[20]; ! 148: static add_newlines = 0; ! 149: #endif /* NeXT .include feature */ ! 150: int ch; ! 151: ! 152: if(state==-1) { ! 153: ch= *out_string++; ! 154: if(*out_string==0) { ! 155: state=old_state; ! 156: old_state=3; ! 157: } ! 158: return ch; ! 159: } ! 160: if(state==-2) { ! 161: for(;;) { ! 162: do ch=(*get)(); ! 163: while(ch!=EOF && ch!='\n' && ch!='*'); ! 164: if(ch=='\n' || ch==EOF) ! 165: return ch; ! 166: ch=(*get)(); ! 167: if(ch==EOF || ch=='/') ! 168: break; ! 169: (*unget)(ch); ! 170: } ! 171: state=old_state; ! 172: return ' '; ! 173: } ! 174: if(state==4) { ! 175: ch=(*get)(); ! 176: if(ch==EOF || (ch>='0' && ch<='9')) ! 177: return ch; ! 178: else { ! 179: while(ch!=EOF && IS_WHITESPACE(ch)) ! 180: ch=(*get)(); ! 181: if(ch=='"') { ! 182: (*unget)(ch); ! 183: #if defined(M88K) || defined(M98K) || defined(HPPA) ! 184: out_string="@ .file "; ! 185: #else ! 186: out_string="; .file "; ! 187: #endif ! 188: old_state=7; ! 189: state= -1; ! 190: return *out_string++; ! 191: } else { ! 192: while(ch!=EOF && ch!='\n') ! 193: ch=(*get)(); ! 194: #ifdef NeXT ! 195: /* bug fix for bug #8918, which was when ! 196: * a full line comment line this: ! 197: * # 40 MP1 = M + 1 ! 198: * got confused with a cpp output like: ! 199: * # 1 "hello.c" 1 ! 200: */ ! 201: state = 0; ! 202: #endif /* NeXT */ ! 203: return ch; ! 204: } ! 205: } ! 206: } ! 207: if(state==5) { ! 208: ch=(*get)(); ! 209: if(ch=='"') { ! 210: state=old_state; ! 211: return '"'; ! 212: } else if(ch=='\\') { ! 213: state=6; ! 214: return ch; ! 215: } else if(ch==EOF) { ! 216: as_warn("End of file in string: inserted '\"'"); ! 217: state=old_state; ! 218: (*unget)('\n'); ! 219: return '"'; ! 220: } else { ! 221: return ch; ! 222: } ! 223: } ! 224: if(state==6) { ! 225: state=5; ! 226: ch=(*get)(); ! 227: switch(ch) { ! 228: /* This is neet. Turn "string ! 229: more string" into "string\n more string" ! 230: */ ! 231: case '\n': ! 232: (*unget)('n'); ! 233: add_newlines++; ! 234: return '\\'; ! 235: ! 236: case '"': ! 237: case '\\': ! 238: case 'b': ! 239: case 'f': ! 240: case 'n': ! 241: case 'r': ! 242: case 't': ! 243: case '0': ! 244: case '1': ! 245: case '2': ! 246: case '3': ! 247: case '4': ! 248: case '5': ! 249: case '6': ! 250: case '7': ! 251: break; ! 252: default: ! 253: as_warn("Unknown escape '\\%c' in string: Ignored",ch); ! 254: break; ! 255: ! 256: case EOF: ! 257: as_warn("End of file in string: '\"' inserted"); ! 258: return '"'; ! 259: } ! 260: return ch; ! 261: } ! 262: ! 263: if(state==7) { ! 264: ch=(*get)(); ! 265: state=5; ! 266: old_state=8; ! 267: return ch; ! 268: } ! 269: ! 270: if(state==8) { ! 271: do ch= (*get)(); ! 272: while(ch!='\n'); ! 273: state=0; ! 274: return ch; ! 275: } ! 276: ! 277: flushchar: ! 278: ch=(*get)(); ! 279: switch(ch) { ! 280: case ' ': ! 281: case '\t': ! 282: do ch=(*get)(); ! 283: while(ch!=EOF && IS_WHITESPACE(ch)); ! 284: if(ch==EOF) ! 285: return ch; ! 286: if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) { ! 287: (*unget)(ch); ! 288: goto flushchar; ! 289: } ! 290: (*unget)(ch); ! 291: if(state==0 || state==2) { ! 292: state++; ! 293: return ' '; ! 294: } else goto flushchar; ! 295: ! 296: case '/': ! 297: ch=(*get)(); ! 298: if(ch=='*') { ! 299: for(;;) { ! 300: do { ! 301: ch=(*get)(); ! 302: if(ch=='\n') ! 303: add_newlines++; ! 304: } while(ch!=EOF && ch!='*'); ! 305: ch=(*get)(); ! 306: if(ch==EOF || ch=='/') ! 307: break; ! 308: (*unget)(ch); ! 309: } ! 310: if(ch==EOF) ! 311: as_warn("End of file in '/' '*' string: */ inserted"); ! 312: ! 313: (*unget)(' '); ! 314: goto flushchar; ! 315: } else { ! 316: #if defined(I860) || defined(M88K) || defined(M98K) || defined(I386) || \ ! 317: defined(HPPA) || defined (SPARC) ! 318: if (ch == '/') { ! 319: do { ! 320: ch=(*get)(); ! 321: } while (ch != EOF && (ch != '\n')); ! 322: if (ch == EOF) ! 323: as_warn("End of file before newline in // comment"); ! 324: if ( ch == '\n' ) /* Push NL back so we can complete state */ ! 325: (*unget)(ch); ! 326: goto flushchar; ! 327: } ! 328: #endif ! 329: if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) { ! 330: (*unget)(ch); ! 331: ch='/'; ! 332: goto deal_misc; ! 333: } ! 334: if(ch!=EOF) ! 335: (*unget)(ch); ! 336: return '/'; ! 337: } ! 338: break; ! 339: ! 340: case '"': ! 341: old_state=state; ! 342: state=5; ! 343: return '"'; ! 344: break; ! 345: ! 346: case '\'': ! 347: ch=(*get)(); ! 348: if(ch==EOF) { ! 349: as_warn("End-of-file after a ': \\000 inserted"); ! 350: ch=0; ! 351: } ! 352: sprintf(out_buf,"(%d)",ch&0xff); ! 353: old_state=state; ! 354: state= -1; ! 355: out_string=out_buf; ! 356: return *out_string++; ! 357: ! 358: case ':': ! 359: if(state!=3) ! 360: state=0; ! 361: return ch; ! 362: ! 363: case '\n': ! 364: if(add_newlines) { ! 365: --add_newlines; ! 366: (*unget)(ch); ! 367: } ! 368: /* Fall through. */ ! 369: #if defined(M88K) || defined(M98K) || defined(HPPA) ! 370: case '@': ! 371: #else ! 372: case ';': ! 373: #endif ! 374: state=0; ! 375: return ch; ! 376: ! 377: default: ! 378: deal_misc: ! 379: if(state==0 && IS_LINE_COMMENT(ch)) { ! 380: do ch=(*get)(); ! 381: while(ch!=EOF && IS_WHITESPACE(ch)); ! 382: if(ch==EOF) { ! 383: as_warn("EOF in comment: Newline inserted"); ! 384: return '\n'; ! 385: } ! 386: if(ch<'0' || ch>'9') { ! 387: do ch=(*get)(); ! 388: while(ch!=EOF && ch!='\n'); ! 389: if(ch==EOF) ! 390: as_warn("EOF in Comment: Newline inserted"); ! 391: state=0; ! 392: return '\n'; ! 393: } ! 394: (*unget)(ch); ! 395: old_state=4; ! 396: state= -1; ! 397: out_string=".line "; ! 398: return *out_string++; ! 399: ! 400: } else if(IS_COMMENT(ch)) { ! 401: do ch=(*get)(); ! 402: while(ch!=EOF && ch!='\n'); ! 403: if(ch==EOF) ! 404: as_warn("EOF in comment: Newline inserted"); ! 405: state=0; ! 406: return '\n'; ! 407: ! 408: } else if(state==0) { ! 409: state=2; ! 410: return ch; ! 411: } else if(state==1) { ! 412: state=2; ! 413: return ch; ! 414: } else { ! 415: return ch; ! 416: ! 417: } ! 418: case EOF: ! 419: if(state==0) ! 420: return ch; ! 421: as_warn("End-of-File not at end of a line"); ! 422: } ! 423: return -1; ! 424: } ! 425: ! 426: #ifdef NeXT /* .include feature */ ! 427: void ! 428: save_scrub_context( ! 429: scrub_context_data *save_buffer_ptr) ! 430: { ! 431: save_buffer_ptr->last_scrub_file = scrub_file; ! 432: save_buffer_ptr->last_state = state; ! 433: save_buffer_ptr->last_old_state = old_state; ! 434: save_buffer_ptr->last_out_string = out_string; ! 435: memcpy(save_buffer_ptr->last_out_buf, out_buf, sizeof(out_buf)); ! 436: save_buffer_ptr->last_add_newlines = add_newlines; ! 437: ! 438: state = 0; ! 439: old_state = 0; ! 440: out_string = NULL; ! 441: memset(out_buf, '\0', sizeof(out_buf)); ! 442: add_newlines = 0; ! 443: } ! 444: ! 445: void ! 446: restore_scrub_context( ! 447: scrub_context_data *save_buffer_ptr) ! 448: { ! 449: scrub_file = save_buffer_ptr->last_scrub_file; ! 450: state = save_buffer_ptr->last_state; ! 451: old_state = save_buffer_ptr->last_old_state; ! 452: out_string = save_buffer_ptr->last_out_string; ! 453: memcpy(out_buf, save_buffer_ptr->last_out_buf, sizeof(out_buf)); ! 454: add_newlines = save_buffer_ptr->last_add_newlines; ! 455: } ! 456: #endif /* NeXT .include feature */ ! 457: ! 458: #ifdef TEST ! 459: ! 460: const char md_comment_chars[] = "|"; ! 461: const char md_line_comment_chars[] = "#"; ! 462: ! 463: int ! 464: get( ! 465: void) ! 466: { ! 467: return(getc(stdin)); ! 468: } ! 469: ! 470: void ! 471: unget( ! 472: int ch) ! 473: { ! 474: ungetc(ch, stdin); ! 475: } ! 476: ! 477: void ! 478: main( ! 479: int argc, ! 480: char *argv[], ! 481: char *envp[]) ! 482: { ! 483: int ch; ! 484: ! 485: while((ch = do_scrub_next_char(get, unget)) != EOF) ! 486: putc(ch, stdout); ! 487: } ! 488: ! 489: void ! 490: as_warn( ! 491: const char *format, ! 492: ...) ! 493: { ! 494: va_list ap; ! 495: ! 496: va_start(ap, format); ! 497: vfprintf(stderr, format, ap); ! 498: fprintf(stderr, "\n"); ! 499: va_end(ap); ! 500: } ! 501: #endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.