Annotation of GNUtools/cctools/as/app.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.