home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Source / GNU / cctools / as / app.c next >
Encoding:
C/C++ Source or Header  |  1992-11-13  |  9.9 KB  |  476 lines

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