home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / preproc / pout.c < prev    next >
C/C++ Source or Header  |  2001-12-12  |  8KB  |  231 lines

  1. #include "../preproc/preproc.h"
  2. #include "../preproc/ptoken.h"
  3. #include "../preproc/pproto.h"
  4.  
  5. int line_cntrl;
  6.  
  7. /*
  8.  * output - output preprocessed tokens for the current file.
  9.  */
  10. void output(out_file)
  11. FILE *out_file;
  12.    {
  13.    struct token *t, *t1;
  14.    struct token *saved_whsp;
  15.    char *fname;
  16.    char *s;
  17.    int line;
  18.    int nxt_line;
  19.    int trail_nl;  /* flag: trailing character in output is a new-line */
  20.    int  blank_ln;  /* flag: output ends with blank line */
  21.  
  22.    fname = "";
  23.    line = -1;
  24.  
  25.    /*
  26.     * Suppress an initial new-line in the output.
  27.     */
  28.    trail_nl = 1;
  29.    blank_ln = 1;
  30.  
  31.    while ((t = preproc()) != NULL) {
  32.       if (t->flag & LineChk) {
  33.          /*
  34.           * This token is significant with respect to outputting #line
  35.           *  directives.
  36.           */
  37.          nxt_line = t->line;
  38.          if (fname != t->fname  || line != nxt_line) {
  39.             /*
  40.              * We need a #line directive. Make sure it is preceeded by a
  41.              *  blank line.
  42.              */
  43.             if (!trail_nl) {
  44.                putc('\n', out_file);
  45.                ++line;
  46.                trail_nl = 1;
  47.                }
  48.             if (!blank_ln && (line != nxt_line || fname != t->fname)) {
  49.                putc('\n', out_file);
  50.                ++line;
  51.                blank_ln = 1;
  52.                }
  53.             /*
  54.              * Eliminate extra new-lines from the subsequent text before
  55.              *  inserting line directive. This make the output look better.
  56.              *  The line number for the directive will change if new-lines
  57.              *  are eliminated.
  58.              */
  59.             saved_whsp = NULL;
  60.             s = t->image;
  61.             while (t->tok_id == WhiteSpace && (*s == ' ' || *s == '\n' ||
  62.                  *s == '\t')) {
  63.                if (*s == '\n') {
  64.                   /*
  65.                    * Discard any white space before the new-line and update
  66.                    *  the line number.
  67.                    */
  68.                   free_t(saved_whsp);
  69.                   saved_whsp = NULL;
  70.                   t->image = s + 1;
  71.                   ++t->line;
  72.                   ++nxt_line;
  73.                   }
  74.                ++s;
  75.                if (*s == '\0') {
  76.                   /*
  77.                    * The end of the current white space token has been
  78.                    *  reached, see if the next token is also white space.
  79.                    */
  80.                   free_t(saved_whsp);
  81.                   t1 = preproc();
  82.                   if (t1 == NULL) {
  83.                      /*
  84.                       * We are at the end of the input. Don't output
  85.                       *  a #line directive, just make sure the output
  86.                       *  ends with a new-line.
  87.                       */
  88.                      free_t(t);
  89.                      if (!trail_nl)
  90.                         putc('\n', out_file);
  91.                      return;
  92.                      }
  93.                   /*
  94.                    * The previous token may contain non-new-line white
  95.                    *  space, if the new token is on the same line, save
  96.                    *  that previous token in case we want to print the
  97.                    *  white space (this will correctly indent the new
  98.                    *  token).
  99.                    */
  100.                   if (*(t->image) != '\0' && t->line == t1->line &&
  101.                        t->fname == t1->fname)
  102.                      saved_whsp = t;
  103.                   else {
  104.                      free_t(t);
  105.                      saved_whsp = NULL;
  106.                      }
  107.                   t = t1;
  108.                   s = t->image;
  109.                   nxt_line = t->line;
  110.                   }
  111.                }
  112.             if (line_cntrl) {
  113.                /*
  114.                 * We are supposed to insert #line directives where needed.
  115.                 *  However, one or two blank lines look better when they
  116.                 *  are enough to reestablish the correct line number.
  117.                 */
  118.                if (fname != t->fname  || line > nxt_line ||
  119.                     line + 2 < nxt_line) {
  120.                   /*
  121.                    * Normally a blank line is put after the #line
  122.                    *  directive; However, this requires decrementing
  123.                    *  the line number and a line number of 0 is not
  124.                    *  valid.
  125.                    */
  126.                   if (nxt_line > 1)
  127.                      fprintf(out_file, "#line %d \"", nxt_line - 1);
  128.                   else
  129.                      fprintf(out_file, "#line %d \"", nxt_line);
  130.                   for (s = t->fname; *s != '\0'; ++s) {
  131.                      if (*s == '"' || *s == '\\')
  132.                         putc('\\',out_file);
  133.                      putc(*s, out_file);
  134.                      }
  135.                   fprintf(out_file, "\"\n");
  136.                   if (nxt_line > 1)
  137.                      fprintf(out_file, "\n"); /* blank line after directive */
  138.                   trail_nl = 1;
  139.                   blank_ln = 1;
  140.                   }
  141.                else  /* adjust line number with blank lines */
  142.                   while (line < nxt_line) {
  143.                      putc('\n', out_file);
  144.                      ++line;
  145.                      if (trail_nl)
  146.                         blank_ln = 1;
  147.                      trail_nl = 1;
  148.                      }
  149.                }
  150.             /*
  151.              * See if we need to indent the next token with white space
  152.              *  saved while eliminating extra new-lines.
  153.              */
  154.             if (saved_whsp != NULL) {
  155.                fprintf(out_file, "%s", saved_whsp->image);
  156.                free_t(saved_whsp);
  157.                if (trail_nl) {
  158.                   blank_ln = 1;
  159.                   trail_nl = 0;
  160.                   }
  161.                }
  162.             line = t->line;
  163.             fname = t->fname;
  164.             }
  165.          }
  166.  
  167.       /*
  168.        * Print the image of the token.
  169.        */
  170.       if (t->tok_id == WhiteSpace) {
  171.          /*
  172.           * Keep track of trailing blank lines and new-lines. This
  173.           *  information is used to make the insertion of #line
  174.           *  directives more intelligent and to insure that the output
  175.           *  file ends with a new-line.
  176.           */
  177.          for (s = t->image; *s != '\0'; ++s) {
  178.             putc(*s, out_file);
  179.             switch (*s) {
  180.                case '\n':
  181.                   if (trail_nl)
  182.                      blank_ln = 1;
  183.                   trail_nl = 1;
  184.                   ++line;
  185.                   break;
  186.  
  187.                case ' ':
  188.                case '\t':
  189.                   if (trail_nl)
  190.                      blank_ln = 1;
  191.                   trail_nl = 0;
  192.                   break;
  193.  
  194.                default:
  195.                   trail_nl = 0;
  196.                }
  197.             }
  198.          }
  199.       else {
  200.          /*
  201.           * Add delimiters to string and character literals.
  202.           */
  203.          switch (t->tok_id) {
  204.             case StrLit:
  205.                fprintf(out_file, "\"%s\"", t->image);
  206.                break;
  207.             case LStrLit:
  208.                fprintf(out_file, "L\"%s\"", t->image);
  209.                break;
  210.             case CharConst:
  211.                fprintf(out_file, "'%s'", t->image);
  212.                break;
  213.             case LCharConst:
  214.                fprintf(out_file, "L'%s'", t->image);
  215.                break;
  216.             default:
  217.                fprintf(out_file, "%s", t->image);
  218.             }
  219.          trail_nl = 0;
  220.          blank_ln = 0;
  221.          }
  222.       free_t(t);
  223.       }
  224.  
  225.    /*
  226.     * Make sure output file ends with a new-line.
  227.     */
  228.    if (!trail_nl)
  229.       putc('\n', out_file);
  230.    }
  231.