home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cc-61.0.1 / as / app.c next >
C/C++ Source or Header  |  1992-08-04  |  9KB  |  445 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.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  80.     for (p=comment_chars;*p;p++)
  81.         lex[*p] |= LEX_IS_COMMENT_START;
  82.     for (p=line_comment_chars;*p;p++)
  83.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  84. }
  85.  
  86. FILE *scrub_file;
  87.  
  88. int
  89. scrub_from_file()
  90. {
  91.     return getc(scrub_file);
  92. }
  93.  
  94. void
  95. scrub_to_file(ch)
  96. int ch;
  97. {
  98.     ungetc(ch,scrub_file);
  99. }
  100.  
  101. char *scrub_string;
  102. char *scrub_last_string;
  103.  
  104. int
  105. scrub_from_string()
  106. {
  107.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  108. }
  109.  
  110. void
  111. scrub_to_string(ch)
  112. int ch;
  113. {
  114.     *--scrub_string=ch;
  115. }
  116.  
  117. int
  118. do_scrub_next_char(get,unget)
  119. int (*get)();
  120. void (*unget)();
  121. /* FILE *fp; */
  122. {
  123.     /* State 0: beginning of normal line
  124.         1: After first whitespace on normal line (flush more white)
  125.         2: After first non-white on normal line (keep 1white)
  126.         3: after second white on normal line (flush white)
  127.         4: after putting out a .line, put out digits
  128.         5: parsing a string, then go to old-state
  129.         6: putting out \ escape in a "d string.
  130.         7: After putting out a .file, put out string.
  131.         8: After putting out a .file string, flush until newline.
  132.         -1: output string in out_string and go to the state in old_state
  133.         -2: flush text until a '*' '/' is seen, then go to state old_state
  134.     */
  135.  
  136. #ifndef NeXT    /* .include feature */
  137.     static state;
  138.     static old_state;
  139.     static char *out_string;
  140.     static char out_buf[20];
  141.     static add_newlines = 0;
  142. #endif NeXT    /* .include feature */
  143.     int ch;
  144.  
  145.     if(state==-1) {
  146.         ch= *out_string++;
  147.         if(*out_string==0) {
  148.             state=old_state;
  149.             old_state=3;
  150.         }
  151.         return ch;
  152.     }
  153.     if(state==-2) {
  154.         for(;;) {
  155.             do ch=(*get)();
  156.             while(ch!=EOF && ch!='\n' && ch!='*');
  157.             if(ch=='\n' || ch==EOF)
  158.                 return ch;
  159.              ch=(*get)();
  160.              if(ch==EOF || ch=='/')
  161.                  break;
  162.             (*unget)(ch);
  163.         }
  164.         state=old_state;
  165.         return ' ';
  166.     }
  167.     if(state==4) {
  168.         ch=(*get)();
  169.         if(ch==EOF || (ch>='0' && ch<='9'))
  170.             return ch;
  171.         else {
  172.             while(ch!=EOF && IS_WHITESPACE(ch))
  173.                 ch=(*get)();
  174.             if(ch=='"') {
  175.                 (*unget)(ch);
  176.                 out_string="; .file ";
  177.                 old_state=7;
  178.                 state= -1;
  179.                 return *out_string++;
  180.             } else {
  181.                 while(ch!=EOF && ch!='\n')
  182.                     ch=(*get)();
  183. #ifdef NeXT
  184.                 /* bug fix for bug #8918, which was when
  185.                  * a full line comment line this:
  186.                  * # 40 MP1 = M + 1
  187.                  * got confused with a cpp output like:
  188.                  * # 1 "hello.c" 1
  189.                  */
  190.                 state = 0;
  191. #endif NeXT
  192.                 return ch;
  193.             }
  194.         }
  195.     }
  196.     if(state==5) {
  197.         ch=(*get)();
  198.         if(ch=='"') {
  199.             state=old_state;
  200.             return '"';
  201.         } else if(ch=='\\') {
  202.             state=6;
  203.             return ch;
  204.         } else if(ch==EOF) {
  205.             as_warn("End of file in string: inserted '\"'");
  206.              state=old_state;
  207.             (*unget)('\n');
  208.             return '"';
  209.         } else {
  210.             return ch;
  211.         }
  212.     }
  213.     if(state==6) {
  214.         state=5;
  215.         ch=(*get)();
  216.         switch(ch) {
  217.             /* This is neet.  Turn "string
  218.                more string" into "string\n  more string"
  219.              */
  220.         case '\n':
  221.             (*unget)('n');
  222.             add_newlines++;
  223.             return '\\';
  224.  
  225.         case '"':
  226.         case '\\':
  227.         case 'b':
  228.         case 'f':
  229.         case 'n':
  230.         case 'r':
  231.         case 't':
  232.         case '0':
  233.         case '1':
  234.         case '2':
  235.         case '3':
  236.         case '4':
  237.         case '5':
  238.         case '6':
  239.         case '7':
  240.             break;
  241.         default:
  242.             as_warn("Unknown escape '\\%c' in string: Ignored",ch);
  243.             break;
  244.  
  245.         case EOF:
  246.             as_warn("End of file in string: '\"' inserted");
  247.             return '"';
  248.         }
  249.         return ch;
  250.     }
  251.  
  252.     if(state==7) {
  253.         ch=(*get)();
  254.         state=5;
  255.         old_state=8;
  256.         return ch;
  257.     }
  258.  
  259.     if(state==8) {
  260.         do ch= (*get)();
  261.         while(ch!='\n');
  262.         state=0;
  263.         return ch;
  264.     }
  265.  
  266.  flushchar:
  267.     ch=(*get)();
  268.     switch(ch) {
  269.     case ' ':
  270.     case '\t':
  271.         do ch=(*get)();
  272.         while(ch!=EOF && IS_WHITESPACE(ch));
  273.         if(ch==EOF)
  274.             return ch;
  275.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  276.             (*unget)(ch);
  277.             goto flushchar;
  278.         }
  279.         (*unget)(ch);
  280.         if(state==0 || state==2) {
  281.             state++;
  282.             return ' ';
  283.         } else goto flushchar;
  284.  
  285.     case '/':
  286.         ch=(*get)();
  287.         if(ch=='*') {
  288.             for(;;) {
  289.                 do {
  290.                     ch=(*get)();
  291.                     if(ch=='\n')
  292.                         add_newlines++;
  293.                 } while(ch!=EOF && ch!='*');
  294.                 ch=(*get)();
  295.                 if(ch==EOF || ch=='/')
  296.                     break;
  297.                 (*unget)(ch);
  298.             }
  299.             if(ch==EOF)
  300.                 as_warn("End of file in '/' '*' string: */ inserted");
  301.  
  302.             (*unget)(' ');
  303.             goto flushchar;
  304.         } else {
  305.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  306.                 (*unget)(ch);
  307.                 ch='/';
  308.                 goto deal_misc;
  309.             }
  310.             if(ch!=EOF)
  311.                 (*unget)(ch);
  312.             return '/';
  313.         }
  314.         break;
  315.  
  316.     case '"':
  317.         old_state=state;
  318.         state=5;
  319.         return '"';
  320.         break;
  321.  
  322.     case '\'':
  323.         ch=(*get)();
  324.         if(ch==EOF) {
  325.             as_warn("End-of-file after a ': \000 inserted");
  326.             ch=0;
  327.         }
  328.         sprintf(out_buf,"(%d)",ch&0xff);
  329.         old_state=state;
  330.         state= -1;
  331.         out_string=out_buf;
  332.         return *out_string++;
  333.  
  334.     case ':':
  335.         if(state!=3)
  336.             state=0;
  337.         return ch;
  338.  
  339.     case '\n':
  340.         if(add_newlines) {
  341.             --add_newlines;
  342.             (*unget)(ch);
  343.         }
  344.     /* Fall through.  */
  345.     case ';':
  346.         state=0;
  347.         return ch;
  348.  
  349.     default:
  350.     deal_misc:
  351.         if(state==0 && IS_LINE_COMMENT(ch)) {
  352.             do ch=(*get)();
  353.             while(ch!=EOF && IS_WHITESPACE(ch));
  354.             if(ch==EOF) {
  355.                 as_warn("EOF in comment:  Newline inserted");
  356.                 return '\n';
  357.             }
  358.             if(ch<'0' || ch>'9') {
  359.                 do ch=(*get)();
  360.                 while(ch!=EOF && ch!='\n');
  361.                 if(ch==EOF)
  362.                     as_warn("EOF in Comment: Newline inserted");
  363.                 state=0;
  364.                 return '\n';
  365.             }
  366.             (*unget)(ch);
  367.             old_state=4;
  368.             state= -1;
  369.             out_string=".line ";
  370.             return *out_string++;
  371.  
  372.         } else if(IS_COMMENT(ch)) {
  373.             do ch=(*get)();
  374.             while(ch!=EOF && ch!='\n');
  375.             if(ch==EOF)
  376.                 as_warn("EOF in comment:  Newline inserted");
  377.             state=0;
  378.             return '\n';
  379.  
  380.         } else if(state==0) {
  381.             state=2;
  382.             return ch;
  383.         } else if(state==1) {
  384.             state=2;
  385.             return ch;
  386.         } else {
  387.             return ch;
  388.  
  389.         }
  390.     case EOF:
  391.         if(state==0)
  392.             return ch;
  393.         as_warn("End-of-File not at end of a line");
  394.     }
  395.     return -1;
  396. }
  397.  
  398. #ifdef NeXT    /* .include feature */
  399. void
  400. save_scrub_context (save_buffer_ptr)
  401.     scrub_context_data    * save_buffer_ptr;
  402. {
  403.     save_buffer_ptr->last_scrub_file = scrub_file;
  404.     save_buffer_ptr->last_state = state;
  405.     save_buffer_ptr->last_old_state = old_state;
  406.     save_buffer_ptr->last_out_string = out_string;
  407.     bcopy(out_buf, save_buffer_ptr->last_out_buf, sizeof(out_buf));
  408.     save_buffer_ptr->last_add_newlines = add_newlines;
  409. }
  410.  
  411. void
  412. restore_scrub_context (save_buffer_ptr)
  413.     scrub_context_data    * save_buffer_ptr;
  414. {
  415.     scrub_file = save_buffer_ptr->last_scrub_file;
  416.     state = save_buffer_ptr->last_state;
  417.     old_state = save_buffer_ptr->last_old_state;
  418.     out_string = save_buffer_ptr->last_out_string;
  419.     bcopy(save_buffer_ptr->last_out_buf, out_buf, sizeof(out_buf));
  420.     add_newlines = save_buffer_ptr->last_add_newlines;
  421. }
  422. #endif NeXT    /* .include feature */
  423.  
  424. #ifdef TEST
  425.  
  426. char comment_chars[] = "|";
  427. char line_comment_chars[] = "#";
  428.  
  429. main()
  430. {
  431.     int    ch;
  432.  
  433.     app_begin();
  434.     while((ch=do_scrub_next_char(stdin))!=EOF)
  435.         putc(ch,stdout);
  436. }
  437.  
  438. as_warn(str)
  439. char *str;
  440. {
  441.     fputs(str,stderr);
  442.     putc('\n',stderr);
  443. }
  444. #endif
  445.