home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / indent / pr_comment.c < prev    next >
C/C++ Source or Header  |  1999-06-05  |  26KB  |  968 lines

  1. /* Copyright (c) 1992, Free Software Foundation, Inc.  All rights reserved.
  2.  
  3.    Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  4.    of the University of California. Copyright (c) 1976 Board of Trustees of
  5.    the University of Illinois. All rights reserved.
  6.  
  7.    Redistribution and use in source and binary forms are permitted
  8.    provided that
  9.    the above copyright notice and this paragraph are duplicated in all such
  10.    forms and that any documentation, advertising materials, and other
  11.    materials related to such distribution and use acknowledge that the
  12.    software was developed by the University of California, Berkeley, the
  13.    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  14.    either University or Sun Microsystems may not be used to endorse or
  15.    promote products derived from this software without specific prior written
  16.    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  18.    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
  19.  
  20.  
  21. #define CHECK_COM_SIZE \
  22.     if (e_com >= l_com) { \
  23.         register nsize = l_com-s_com+400; \
  24.         combuf = (char *) xrealloc (combuf, nsize); \
  25.         e_com = combuf + (e_com-s_com) + 1; \
  26.         l_com = combuf + nsize - 5; \
  27.         s_com = combuf + 1; \
  28.     }
  29.  
  30. /* NAME: pr_comment
  31.  
  32. FUNCTION: This routine takes care of scanning and printing comments.
  33.  
  34. ALGORITHM: 1) Decide where the comment should be aligned, and if lines should
  35.    be broken. 2) If lines should not be broken and filled, just copy up to
  36.    end of comment. 3) If lines should be filled, then scan thru input_buffer
  37.    copying characters to com_buf.  Remember where the last blank, tab, or
  38.    newline was.  When line is filled, print up to last blank and continue
  39.    copying.
  40.  
  41. HISTORY: November 1976    D A Willcox of CAC    Initial coding 12/6/76
  42.     A Willcox of CAC    Modification to handle UNIX-style comments
  43.  
  44. */
  45.  
  46. /* this routine processes comments.  It makes an attempt to keep comments
  47.    from going over the max line length.  If a line is too long, it moves
  48.    everything from the last blank to the next comment line.  Blanks and tabs
  49.    from the beginning of the input line are removed */
  50.  
  51.  
  52. #include "sys.h"
  53. #include "indent.h"
  54.  
  55. int debug_comments;
  56.  
  57. /* Declared and documented in indent.h.  */
  58. int out_coms;
  59.  
  60. #ifndef NEW_COMMENTS
  61.  
  62. print_comment ()
  63. {
  64.   int now_col;            /* column we are in now */
  65.   int adj_max_col;        /* Adjusted max_col for when we decide to
  66.                    spill comments over the right margin */
  67.   char *last_bl;        /* points to the last blank in the output
  68.                    buffer */
  69.   char *t_ptr;            /* used for moving string */
  70.   int unix_comment;        /* tri-state variable used to decide if it is
  71.                    a unix-style comment. 0 means only blanks
  72.                    since /*, 1 means regular style comment, 2
  73.                    means unix style comment */
  74.  
  75.   int break_delim = comment_delimiter_on_blankline;
  76.  
  77.   int one_liner = 1;        /* true iff this comment is a one-liner */
  78.  
  79.   adj_max_col = max_col;
  80.   parser_state_tos->just_saw_decl = 0;
  81.   last_bl = 0;
  82.   parser_state_tos->box_com = false;
  83.   ++out_coms;
  84.   unix_comment = 1;
  85.  
  86.   if (parser_state_tos->col_1 && !format_col1_comments)
  87.     {
  88.       parser_state_tos->box_com = true;
  89.       parser_state_tos->com_col = 1;
  90.     }
  91.   else
  92.     {
  93.       /* Don't format the comment if it is a "boxed" comment. */
  94.       if (*buf_ptr == '-' || *buf_ptr == '*' || !format_comments)
  95.     {
  96.       parser_state_tos->box_com = true;
  97.       break_delim = 0;
  98.     }
  99.  
  100.       if ((s_lab == e_lab) && (s_code == e_code))
  101.     {
  102.       /* klg: check only if this line is blank */
  103.       /* If this (*and previous lines are*) blank, dont put comment way
  104.          out at left */
  105.       parser_state_tos->com_col
  106.         = (parser_state_tos->ind_level - unindent_displace) + 1;
  107.       adj_max_col = block_comment_max_col;
  108.       if (parser_state_tos->com_col <= 1)
  109.         parser_state_tos->com_col = 1 + !format_col1_comments;
  110.  
  111.       /* If we have a comment in an old-style (pre-ANSI) parameter
  112.          declaration, indent it like we would the parameter declaration.
  113.          For example:
  114.            int destroy (what) / * N things to destroy.  * / int what;
  115.       */
  116.       if (parser_state_tos->in_parameter_declaration
  117.           && indent_parameters != 0
  118.           && parser_state_tos->dec_nest == 0)
  119.         {
  120.           parser_state_tos->com_col = indent_parameters + 1;
  121.           parser_state_tos->ind_stmt = 0;
  122.         }
  123.     }
  124.       else
  125.     {
  126.       register target_col;
  127.       break_delim = 0;
  128.       if (s_code != e_code)
  129.         target_col = count_spaces (compute_code_target (), s_code);
  130.       else
  131.         {
  132.           target_col = 1;
  133.           if (s_lab != e_lab)
  134.         target_col = count_spaces (compute_label_target (), s_lab);
  135.         }
  136.       parser_state_tos->com_col = parser_state_tos->decl_on_line
  137.         || parser_state_tos->ind_level == 0 ? decl_com_ind : com_ind;
  138.       /* If we are already past the position for the comment, put it at
  139.          the next tab stop.  */
  140.       if (parser_state_tos->com_col < target_col)
  141.         parser_state_tos->com_col = ((target_col + (tabsize - 1))
  142.                      & ~(tabsize - 1)) + 1;
  143.       if (else_or_endif)
  144.         {
  145.           parser_state_tos->com_col = else_endif_col;
  146.           else_or_endif = false;
  147.           /* We want the comment to appear one space after the #else or
  148.              #endif.  */
  149.           if (parser_state_tos->com_col < target_col)
  150.         parser_state_tos->com_col = target_col + 1;
  151.         }
  152.       if (parser_state_tos->com_col + 24 > adj_max_col)
  153.         adj_max_col = parser_state_tos->com_col + 24;
  154.     }
  155.     }
  156.  
  157.   if (parser_state_tos->box_com)
  158.     {
  159.       parser_state_tos->n_comment_delta = 1 - parser_state_tos->com_col;
  160. #if 0
  161.       buf_ptr[-2] = 0;
  162.       parser_state_tos->n_comment_delta = 1 - count_spaces (1, cur_line);
  163.       buf_ptr[-2] = '/';
  164. #endif
  165.     }
  166.   else
  167.     {
  168.       parser_state_tos->n_comment_delta = 0;
  169.       while (*buf_ptr == ' ' || *buf_ptr == TAB)
  170.     buf_ptr++;
  171.     }
  172.  
  173.   parser_state_tos->comment_delta = 0;
  174.   *e_com++ = '/';        /* put '/*' into buffer */
  175.   *e_com++ = '*';
  176.   if (*buf_ptr != ' ' && !parser_state_tos->box_com)
  177.     *e_com++ = ' ';
  178.  
  179.   *e_com = '\0';
  180.   if (troff)
  181.     {
  182.       now_col = 1;
  183.       adj_max_col = 80;
  184.     }
  185.   else
  186.     /* figure what column we would be in if we printed the comment now */
  187.     now_col = count_spaces (parser_state_tos->com_col, s_com);
  188.  
  189.   /* Start to copy the comment */
  190.  
  191.   while (1)
  192.     {                /* this loop will go until the comment is
  193.                    copied */
  194.       if (*buf_ptr > 040 && *buf_ptr != '*')
  195.     parser_state_tos->last_nl = 0;
  196.  
  197.       CHECK_COM_SIZE;
  198.       switch (*buf_ptr)
  199.     {            /* this checks for various spcl cases */
  200.     case 014:        /* check for a form feed */
  201.       if (!parser_state_tos->box_com)
  202.         {            /* in a text comment, break the line here */
  203.           parser_state_tos->use_ff = true;
  204.           /* fix so dump_line uses a form feed */
  205.           dump_line ();
  206.           last_bl = 0;
  207.           *e_com++ = ' ';
  208.           *e_com++ = '*';
  209.           *e_com++ = ' ';
  210.           while (*++buf_ptr == ' ' || *buf_ptr == TAB);
  211.         }
  212.       else
  213.         {
  214.           if (++buf_ptr >= buf_end)
  215.         fill_buffer ();
  216.           *e_com++ = 014;
  217.         }
  218.       break;
  219.  
  220.     case EOL:
  221.       if (had_eof)
  222.         {            /* check for unexpected eof */
  223.           printf ("Unterminated comment\n");
  224.           *e_com = '\0';
  225.           dump_line ();
  226.           return;
  227.         }
  228.  
  229.       one_liner = 0;
  230.       if (parser_state_tos->box_com || parser_state_tos->last_nl)
  231.         {            /* if this is a boxed comment, we dont ignore
  232.                    the newline */
  233.           if (s_com == e_com)
  234.         {
  235.           *e_com++ = ' ';
  236.           *e_com++ = ' ';
  237.         }
  238.           *e_com = '\0';
  239.           if (!parser_state_tos->box_com && e_com - s_com > 3)
  240.         {
  241.           if (break_delim == 1 && s_com[0] == '/'
  242.               && s_com[1] == '*' && s_com[2] == ' ')
  243.             {
  244.               char *t = e_com;
  245.               break_delim = 2;
  246.               e_com = s_com + 2;
  247.               *e_com = 0;
  248.               if (blanklines_before_blockcomments)
  249.             prefix_blankline_requested = 1;
  250.               dump_line ();
  251.               e_com = t;
  252.               s_com[0] = s_com[1] = s_com[2] = ' ';
  253.             }
  254.           dump_line ();
  255.           CHECK_COM_SIZE;
  256.           *e_com++ = ' ';
  257.           *e_com++ = ' ';
  258.         }
  259.           dump_line ();
  260.           now_col = parser_state_tos->com_col;
  261.         }
  262.       else
  263.         {
  264.           parser_state_tos->last_nl = 1;
  265.           if (unix_comment != 1)
  266.         {        /* we not are in unix_style comment */
  267.           if (unix_comment == 0 && s_code == e_code)
  268.             {
  269.               /* if it is a UNIX-style comment, ignore the
  270.                  requirement that previous line be blank for
  271.                  unindention */
  272.               parser_state_tos->com_col
  273.             = ((parser_state_tos->ind_level - unindent_displace)
  274.                + ind_size);
  275.               if (parser_state_tos->com_col <= 1)
  276.             parser_state_tos->com_col = 2;
  277.             }
  278.           unix_comment = 2;    /* permanently remember that we are
  279.                        in this type of comment */
  280.           dump_line ();
  281.           ++line_no;
  282.           now_col = parser_state_tos->com_col;
  283.           *e_com++ = ' ';
  284.           /* fix so that the star at the start of the line will line
  285.              up */
  286.           do        /* flush leading white space */
  287.             if (++buf_ptr >= buf_end)
  288.               fill_buffer ();
  289.           while (*buf_ptr == ' ' || *buf_ptr == TAB);
  290.           break;
  291.         }
  292.           if (*(e_com - 1) == ' ' || *(e_com - 1) == TAB)
  293.         last_bl = e_com - 1;
  294.           /* if there was a space at the end of the last line, remember
  295.              where it was */
  296.           else
  297.         {        /* otherwise, insert one */
  298.           last_bl = e_com;
  299.           CHECK_COM_SIZE;
  300.           *e_com++ = ' ';
  301.           ++now_col;
  302.         }
  303.         }
  304.  
  305.       ++line_no;        /* keep track of input line number */
  306.  
  307.       /* Disregard any leading whitespace. */
  308.       if (!parser_state_tos->box_com)
  309.         {
  310.           int nstar = 1;
  311.           do
  312.         {
  313.           if (++buf_ptr >= buf_end)
  314.             fill_buffer ();
  315.           if (*buf_ptr == '*' && --nstar >= 0)
  316.             {
  317.               if (++buf_ptr >= buf_end)
  318.             fill_buffer ();
  319.               if (*buf_ptr == '/')
  320.             goto end_of_comment;
  321.             }
  322.         }
  323.           while (*buf_ptr == ' ' || *buf_ptr == TAB);
  324.         }
  325.       else if (++buf_ptr >= buf_end)
  326.         fill_buffer ();
  327.       break;        /* end of case for newline */
  328.  
  329.     case '*':        /* must check for possibility of being at end
  330.                    of comment */
  331.       if (++buf_ptr >= buf_end)    /* get to next char after * */
  332.         fill_buffer ();
  333.  
  334.       if (unix_comment == 0)/* set flag to show we are not in unix-style
  335.                    comment */
  336.         unix_comment = 1;
  337.  
  338.       if (*buf_ptr == '/')
  339.         {            /* it is the end!!! */
  340.         end_of_comment:
  341.           if (++buf_ptr >= buf_end)
  342.         fill_buffer ();
  343.  
  344.           if (*(e_com - 1) != ' ' && !parser_state_tos->box_com)
  345.         {        /* insure blank before end */
  346.           *e_com++ = ' ';
  347.           ++now_col;
  348.         }
  349.  
  350.           if (break_delim == 1 && !one_liner && s_com[0] == '/'
  351.           && s_com[1] == '*' && s_com[2] == ' ')
  352.         {
  353.           char *t = e_com;
  354.           break_delim = 2;
  355.           e_com = s_com + 2;
  356.           *e_com = 0;
  357.           if (blanklines_before_blockcomments)
  358.             prefix_blankline_requested = 1;
  359.           dump_line ();
  360.           e_com = t;
  361.           s_com[0] = s_com[1] = s_com[2] = ' ';
  362.         }
  363.  
  364.           if (break_delim == 2 && e_com > s_com + 3
  365.           /* now_col > adj_max_col - 2 && !parser_state_tos->box_com */ )
  366.         {
  367.           *e_com = '\0';
  368.           dump_line ();
  369.           now_col = parser_state_tos->com_col;
  370.         }
  371.  
  372.           CHECK_COM_SIZE;
  373.           *e_com++ = '*';
  374.           *e_com++ = '/';
  375.           *e_com = '\0';
  376.           return;
  377.         }
  378.       else
  379.         {            /* handle isolated '*' */
  380.           *e_com++ = '*';
  381.           ++now_col;
  382.         }
  383.       break;
  384.  
  385.     default:        /* we have a random char */
  386.       if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != TAB)
  387.         unix_comment = 1;    /* we are not in unix-style comment */
  388.  
  389.       *e_com = *buf_ptr++;
  390.       if (buf_ptr >= buf_end)
  391.         fill_buffer ();
  392.  
  393.       if (*e_com == TAB)    /* keep track of column */
  394.         now_col = now_col + tabsize - (now_col - 1) % tabsize;
  395.       else if (*e_com == '\b')    /* this is a backspace */
  396.         --now_col;
  397.       else
  398.         ++now_col;
  399.  
  400.       if (*e_com == ' ' || *e_com == TAB)
  401.         last_bl = e_com;
  402.       /* remember we saw a blank */
  403.  
  404.       ++e_com;
  405.       if (now_col > adj_max_col
  406.           && !parser_state_tos->box_com
  407.           && unix_comment == 1
  408.           && e_com[-1] > ' ')
  409.         {
  410.           /* the comment is too long, it must be broken up */
  411.           if (break_delim == 1 && s_com[0] == '/'
  412.           && s_com[1] == '*' && s_com[2] == ' ')
  413.         {
  414.           char *t = e_com;
  415.           break_delim = 2;
  416.           e_com = s_com + 2;
  417.           *e_com = 0;
  418.           if (blanklines_before_blockcomments)
  419.             prefix_blankline_requested = 1;
  420.           dump_line ();
  421.           e_com = t;
  422.           s_com[0] = s_com[1] = s_com[2] = ' ';
  423.         }
  424.           if (last_bl == 0)
  425.         {        /* we have seen no blanks */
  426.           last_bl = e_com;    /* fake it */
  427.           *e_com++ = ' ';
  428.         }
  429.           *e_com = '\0';    /* print what we have */
  430.           *last_bl = '\0';
  431.           while (last_bl > s_com && last_bl[-1] < 040)
  432.         *--last_bl = 0;
  433.           e_com = last_bl;
  434.           dump_line ();
  435.  
  436.           *e_com++ = ' ';    /* add blanks for continuation */
  437.           *e_com++ = ' ';
  438.           *e_com++ = ' ';
  439.  
  440.           t_ptr = last_bl + 1;
  441.           last_bl = 0;
  442.           if (t_ptr >= e_com)
  443.         {
  444.           while (*t_ptr == ' ' || *t_ptr == TAB)
  445.             t_ptr++;
  446.           while (*t_ptr != '\0')
  447.             {        /* move unprinted part of comment down in
  448.                    buffer */
  449.               if (*t_ptr == ' ' || *t_ptr == TAB)
  450.             last_bl = e_com;
  451.               *e_com++ = *t_ptr++;
  452.             }
  453.         }
  454.           *e_com = '\0';
  455.           /* recompute current position */
  456.           now_col = count_spaces (parser_state_tos->com_col, s_com);
  457.         }
  458.       break;
  459.     }
  460.     }
  461. }
  462.  
  463. #else  /* New Comment code -- UNDER CONSTRUCTION */
  464.  
  465. /* Output a comment.  `buf_ptr' is pointing to the character after
  466.    the beginning comment delimiter when this is called.  This handles
  467.    both C and C++ comments.
  468.  
  469.    As far as indent is concerned, there are basically two types
  470.    of comments -- those on lines by themselves and those which are
  471.    on lines with other code.  Variables (and the options specifying them)
  472.    affecting the printing of comments are:
  473.  
  474.    `format_comments'                ("fca"):  Ignore newlines in the
  475.        comment and perform filling up to `max_col'.  Double newlines
  476.        indicate paragraph breaks.
  477.  
  478.    `format_col1_comments'           ("fc1"):  Format comments which
  479.        begin in column 1.
  480.  
  481.    `unindent_displace'              ("d"):  The hanging indentation for
  482.        comments which do not appear to the right of code.
  483.  
  484.    `comment_delimiter_on_blankline' ("cdb"):  If set, place the comment
  485.        delimiters on lines by themselves.  This only affects comments
  486.        which are not to the right of code.
  487.  
  488.    `com_ind'                        ("c"):  The column in which to begin
  489.        comments that are to the right of code.
  490.  
  491.    `decl_com_ind'                   ("cd"):  The column in which to begin
  492.        comments that are to the right of declarations.
  493.  
  494.    `else_endif_col'                 ("cp"):  The column in which to begin
  495.        comments to the right of preprocessor directives.
  496.  
  497.    `star_comment_cont'              ("sc"):  Place a star ('*') to the
  498.        left of the comment body.
  499.  
  500.    `max_col'                        ("l"):  The length of a line.  Formatted
  501.        comments which extend past this column will be continued on the
  502.        following line.
  503.  
  504.    `block_comment_max_col'          ("lc"): Unused.
  505.  
  506.    `blanklines_before_blockcomments'("nbbb"): Unused.
  507.  
  508.    */
  509.  
  510. void
  511. print_comment ()
  512. {
  513.   register int tab_increment;
  514.   register int column, format;
  515.   enum codes comment_type;
  516.  
  517.   int start_column, save_length, found_column;
  518.   int first_comment_line, right_margin;
  519.   int boxed_comment, stars, blankline_delims, paragraph_break,
  520.       merge_blank_comment_lines;
  521.   char *line_break_ptr = 0;
  522.   char *save_ptr = 0;
  523.   char *text_on_line = 0;
  524.   char *start_delim, *end_delim;
  525.  
  526.   char *line_preamble;
  527.   int line_preamble_length;
  528.  
  529.   /* Increment the parser stack, as we will store some things
  530.      there for dump_line to use. */
  531.   inc_pstack ();
  532.  
  533.   /* Have to do it this way because this piece of shit program doesn't
  534.      always place the last token code on the stack. */
  535.   if (*(token + 1) == '/')
  536.     comment_type = cplus_comment;
  537.   else
  538.     comment_type = comment;
  539.  
  540.   /* First, decide what kind of comment this is: C++, C, or boxed C.
  541.      Even if this appears to be a normal C comment, we may change our
  542.      minds if we find a star in the right column of the second line,
  543.      in which case that's a boxed comment too. */
  544.   if (comment_type == cplus_comment)
  545.     {
  546.       start_delim = "//";
  547.       line_preamble = "// ";
  548.       line_preamble_length = 3;
  549.       boxed_comment = 0;
  550.       stars = 0;
  551.       blankline_delims = 0;
  552.     }
  553.   else if (*buf_ptr == '*' || *buf_ptr == '-')
  554.     {
  555.       start_delim = "/*";
  556.       end_delim = "*/";
  557.       line_preamble = " ";
  558.       line_preamble_length = 1;
  559.       boxed_comment = 1;
  560.       stars = 0;
  561.       blankline_delims = 0;
  562.     }
  563.   else
  564.     {
  565.       start_delim = "/*";
  566.       end_delim = "*/";
  567.       line_preamble = 0;
  568.       line_preamble_length = 0;
  569.       boxed_comment = 0;
  570.       stars = star_comment_cont;
  571.       blankline_delims = comment_delimiter_on_blankline;
  572.     }
  573.  
  574.   paragraph_break = 0;
  575.   merge_blank_comment_lines = 0;
  576.   first_comment_line = com_lines;
  577.   right_margin = max_col;
  578.  
  579.   /* Now, compute the correct indentation for this comment
  580.      and whether or not it should be formatted. */
  581.   found_column = current_column () - 2;
  582.   if (boxed_comment)
  583.     {
  584.       start_column = found_column;
  585.       format = 0;
  586.       blankline_delims = 0;
  587.     }
  588.   else
  589.     {
  590.       /* First handle comments which begin the line. */
  591.       if ((s_lab == e_lab) && (s_code == e_code))
  592.     {
  593.       /* This is a top-level comment, not within some code. */
  594.       if (parser_state_tos->ind_level <= 0)
  595.         {
  596.           if (parser_state_tos->col_1)
  597.         {
  598.           format = format_col1_comments;
  599.           start_column = 1;
  600.         }
  601.           else
  602.         {
  603.           format = format_comments;
  604.           start_column = found_column;
  605.         }
  606.         }
  607.       /* Here for comments starting a line, in the middle of code. */
  608.       else
  609.         {
  610.           if (parser_state_tos->col_1)
  611.         {
  612.           format = format_col1_comments;
  613.           start_column = 1;
  614.         }
  615.           else
  616.         {
  617.           format = format_comments;
  618.           start_column = (parser_state_tos->ind_level
  619.                   - unindent_displace + 1);
  620.           if (start_column < 0)
  621.             start_column = 1;
  622.         }
  623.         }
  624.     }
  625.       else
  626.     /* This comment follows code of some sort. */
  627.     {
  628.       int target;
  629.  
  630.       /* First, computer where the comment SHOULD go. */
  631.       if (parser_state_tos->decl_on_line)
  632.         target = decl_com_ind;
  633.       else if (else_or_endif)
  634.         target = else_endif_col;
  635.       else
  636.         target = com_ind;
  637.  
  638.       /* Now determine if the code on the line is short enough
  639.          to allow the comment to begin where it should. */
  640.       if (s_code != e_code)
  641.         start_column = count_spaces (compute_code_target (), s_code);
  642.       else
  643.         /* s_lab != e_lab : there is a label here. */
  644.         start_column = count_spaces (compute_label_target (), s_lab);
  645.  
  646.       if (start_column < target)
  647.         start_column = target;
  648.       else
  649.         {
  650.           /* If the too-long code is a pre-processor command,
  651.          start the comment 1 space afterwards, otherwise
  652.          start at the next tab mark. */
  653.           if (else_or_endif)
  654.         {
  655.           start_column++;
  656.           else_or_endif = false;
  657.         }
  658.           else
  659.         start_column += (tabsize - (start_column % tabsize) + 1);
  660.         }
  661.  
  662.       format = format_comments;
  663.     }
  664.     }
  665.  
  666.   if (! line_preamble)
  667.     {
  668.       line_preamble_length = 3;
  669.       if (stars)
  670.     line_preamble = " * ";
  671.       else
  672.     line_preamble = "   ";
  673.     }
  674.  
  675.   /* These are the parser stack variables used to communicate
  676.      formatting information to dump_line (). */
  677.   parser_state_tos->com_col = start_column;
  678.   parser_state_tos->box_com = boxed_comment;
  679.   parser_state_tos->comment_delta = 0;
  680.   parser_state_tos->n_comment_delta = 0;
  681.   if (boxed_comment)
  682.     {
  683.       stars = 0;
  684.       blankline_delims = 0;
  685.     }
  686.  
  687.   /* Output the beginning comment delimiter.  They are both two
  688.      characters long. */
  689.   memcpy (e_com, start_delim, 2);
  690.   e_com += 2;
  691.   column = start_column + 2;
  692.  
  693.   /* If the user specified -cdb, put the delimiter on one line. */
  694.   if (blankline_delims)
  695.     {
  696.       char *p = buf_ptr;
  697.  
  698.       *e_com = '\0';
  699.       dump_line ();
  700.  
  701.       /* Check if the delimiter was already on a line by itself,
  702.      and skip whitespace if formating. */
  703.       while ((*p == ' ' || *p == TAB) && p < buf_end)
  704.     p++;
  705.       if (*p == EOL)
  706.     buf_ptr = p + 1;
  707.       else if (format)
  708.     buf_ptr = p;
  709.       if (buf_ptr >= buf_end)
  710.     fill_buffer ();
  711.  
  712.       column = start_column;
  713.       goto begin_line;
  714.     }
  715.   else if (format)
  716.     {
  717.       *e_com++ = ' ';
  718.       column = start_column + 3;
  719.       while (*buf_ptr == ' ' || *buf_ptr == TAB)
  720.     if (++buf_ptr >= buf_end)
  721.       fill_buffer ();
  722.     }
  723.  
  724.   /* Iterate through the lines of the comment */
  725.   while (1)
  726.     {
  727.       /* Iterate through the characters on one line */
  728.       while (1)
  729.     {
  730.       CHECK_COM_SIZE;
  731.  
  732.       switch (*buf_ptr)
  733.         {
  734.         case ' ':
  735.         case TAB:
  736.           /* If formatting, and previous break marker is
  737.              nonexistant, or before text on line, reset
  738.          it to here. */
  739.           if (format && line_break_ptr < text_on_line)
  740.         line_break_ptr = e_com;
  741.  
  742.           if (*buf_ptr == ' ')
  743.         {
  744.           *e_com++ = ' ';
  745.           column++;
  746.         }
  747.           else
  748.         {
  749.           /* Convert the tab to the appropriate number of spaces,
  750.              based on the column we found the comment in, not
  751.              the one we're printing in. */
  752.           int tab_width
  753.             = (tabsize - ((column + found_column - start_column - 1)
  754.                   % tabsize));
  755.           column += tab_width;
  756.           while (tab_width--)
  757.             *e_com++ = ' ';
  758.         }
  759.           break;
  760.  
  761.         case EOL:
  762.           /* We may be at the end of a C++ comment */
  763.           if (comment_type == cplus_comment)
  764.         {
  765.           dump_line ();
  766.           buf_ptr++;
  767.           if (buf_ptr == buf_end)
  768.             fill_buffer ();
  769.  
  770.           parser_state_tos->tos--;
  771.           parser_state_tos->com_col = start_column;
  772.           return;
  773.         }
  774.  
  775.           if (format)
  776.         {
  777.           /* Newline and null are the two characters which
  778.              end a line, so check here if we need to
  779.              advance to the next line. */
  780.           if (++buf_ptr == buf_end)
  781.             fill_buffer ();
  782.           if (*buf_ptr == EOL)
  783.             {
  784.               paragraph_break = 1;
  785.               postfix_blankline_requested = 1;
  786.               goto end_line;
  787.             }
  788.  
  789.           /* This is a single newline.  Transform it, and any
  790.              following whitespace into a single blank. */
  791.           line_break_ptr = e_com;
  792.           *e_com++ = ' ';
  793.           column++;
  794.           while (*buf_ptr == TAB || *buf_ptr == ' ')
  795.             if (++buf_ptr == buf_end)
  796.               fill_buffer ();
  797.           continue;
  798.         }
  799.           else
  800.         /* We are printing this line "as is", so output it
  801.            and continue on to the next line. */
  802.         goto end_line;
  803.           break;
  804.  
  805.         case '*':
  806.           /* Check if we've reached the end of the comment. */
  807.           if (comment_type == comment)
  808.         {
  809.           if (*(buf_ptr + 1) == '/')
  810.             {
  811.               /* If it's a boxed comment, skip this and simply
  812.              insert the delimiter on the line.  Otherwise, put
  813.              some whitespace before the delimiter. */
  814.               if (! boxed_comment)
  815.             {
  816.               if (text_on_line)
  817.                 {
  818.                   if (blankline_delims)
  819.                 {
  820.                   *e_com = '\0';
  821.                   dump_line ();
  822.                   *e_com++ = ' ';
  823.                 }
  824.                   else
  825.                 if (*(e_com - 1) != ' ')
  826.                   *e_com++ = ' ';
  827.                 }
  828.               else
  829.                 e_com = s_com + 1;
  830.             }
  831.  
  832.               *e_com++ = '*';
  833.               *e_com++ = '/';
  834.               *e_com = '\0';
  835.  
  836.               /* Skip any whitespace following the comment.  If
  837.              there is only whitespace after it, print the line. */
  838.               buf_ptr += 2;
  839.               while (*buf_ptr == ' ' || *buf_ptr == TAB)
  840.             buf_ptr++;
  841.               if (buf_ptr >= buf_end)
  842.             fill_buffer ();
  843.  
  844.               parser_state_tos->tos--;
  845.               parser_state_tos->com_col = start_column;
  846.               return;
  847.             }
  848.  
  849.           /* If this star is on the second line of the
  850.              comment in the same column as the star of the
  851.              beginning delimiter, then consider it
  852.              a boxed comment. */
  853.           if (first_comment_line == com_lines - 1
  854.               && e_com == s_com + line_preamble_length
  855.               && current_column () == start_column + 1)
  856.             {
  857.               line_preamble = " ";
  858.               line_preamble_length = 1;
  859.               boxed_comment = 1;
  860.               format = 0;
  861.               blankline_delims = 0;
  862.               *s_com = ' ';
  863.               *(s_com + 1) = '*';
  864.               e_com = s_com + 2;
  865.               column++;
  866.               break;
  867.             }
  868.         }
  869.           /* If it was not the end of the comment, drop through
  870.              and insert the star on the line. */
  871.  
  872.         default:
  873.           /* Some textual character. */
  874.           text_on_line = e_com;
  875.           *e_com++ = *buf_ptr;
  876.           column++;
  877.           break;
  878.         }
  879.  
  880.       /* If we are formatting, check that we haven't exceeded the
  881.          line length.  If we haven't set line_break_ptr, keep going. */
  882.       if (format && column >= right_margin && line_break_ptr)
  883.         {
  884.           if (line_break_ptr < e_com - 1)
  885.         {
  886.           *line_break_ptr = '\0';
  887.           save_ptr = line_break_ptr + 1;
  888.           save_length = e_com - save_ptr;
  889.           e_com = line_break_ptr;
  890.  
  891.           /* If we had to go past `right_margin' to print stuff out,
  892.              extend `right_margin' out to this point. */
  893.           if ((column - save_length) > right_margin)
  894.             right_margin = column - save_length;
  895.         }
  896.           else
  897.         *e_com = '\0';
  898.           goto end_line;
  899.         }
  900.  
  901.       buf_ptr++;
  902.     }
  903.  
  904.  
  905.     end_line:
  906.       buf_ptr++;
  907.       if (buf_ptr >= buf_end)
  908.     fill_buffer ();
  909.       *e_com = '\0';
  910.       dump_line ();
  911.  
  912.       /* If formatting (paragraph_break is only used for formatted
  913.      comments) and user wants blank lines merged, kill all white
  914.      space after the "\n\n" indicating a paragraph break. */
  915.       if (paragraph_break)
  916.     {
  917.       if (merge_blank_comment_lines)
  918.         while (*buf_ptr == EOL || *buf_ptr == ' ' || *buf_ptr == TAB)
  919.           if (++buf_ptr >= buf_end)
  920.         fill_buffer ();
  921.       paragraph_break = 0;
  922.     }
  923.  
  924.  
  925.     begin_line:
  926.       /* Indent the line properly.  If it's a boxed comment, align with
  927.      the '*' in the beginning slash-star and start inserting there.
  928.      Otherwise, insert blanks for alignment, or a star if the
  929.      user specified -sc. */
  930.       if (line_preamble)
  931.     {
  932.       memcpy (e_com, line_preamble, line_preamble_length);
  933.       e_com += line_preamble_length;
  934.       column = start_column + line_preamble_length;
  935.     }
  936.       else
  937.     column = start_column;
  938.       line_break_ptr = 0;
  939.  
  940.       /* If we have broken the line before the end for formatting,
  941.          copy the text after the break onto the beginning of this
  942.      new comment line. */
  943.       if (save_ptr)
  944.     {
  945.       while ((*save_ptr == ' ' || *save_ptr == TAB) && save_length)
  946.         {
  947.           save_ptr++;
  948.           save_length--;
  949.         }
  950.       memcpy (e_com, save_ptr, save_length);
  951.       text_on_line = e_com;
  952.       e_com += save_length;
  953.       /* We only break if formatting, in which cases there
  954.          are no tabs, only spaces.*/
  955.       column += save_length;
  956.       save_ptr = 0;
  957.     }
  958.       else
  959.     {
  960.       while (*buf_ptr == ' ' || *buf_ptr == TAB)
  961.         if (++buf_ptr >= buf_end)
  962.           fill_buffer ();
  963.       text_on_line = 0;
  964.     }
  965.     }
  966. }
  967. #endif /* New comment code */
  968.