📄 pr_comme.c
字号:
/* Copyright (c) 1993, Joseph Arceneaux. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. If you do not have a copy of the GNU General Public License, you may obtain a copy by writing to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "sys.h"#include "indent.h"/* Check the limits of the comment buffer, and expand as neccessary. */#define CHECK_COM_SIZE \ if (e_com >= l_com) \ { \ register nsize = l_com-s_com+400; \ combuf = (char *) xrealloc (combuf, nsize); \ e_com = combuf + (e_com-s_com) + 1; \ l_com = combuf + nsize - 5; \ s_com = combuf + 1; \ }/* The number of comments handled so far. */int out_coms;/* Output a comment. `buf_ptr' is pointing to the character after the beginning comment delimiter when this is called. This handles both C and C++ comments. As far as indent is concerned, there are basically two types of comments -- those on lines by themselves and those which are on lines with other code. Variables (and the options specifying them) affecting the printing of comments are: `format_comments' ("fca"): Ignore newlines in the comment and perform filling up to `max_col'. Double newlines indicate paragraph breaks. `format_col1_comments' ("fc1"): Format comments which begin in column 1. `unindent_displace' ("d"): The hanging indentation for comments which do not appear to the right of code. `comment_delimiter_on_blankline' ("cdb"): If set, place the comment delimiters on lines by themselves. This only affects comments which are not to the right of code. `com_ind' ("c"): The column in which to begin comments that are to the right of code. `decl_com_ind' ("cd"): The column in which to begin comments that are to the right of declarations. `else_endif_col' ("cp"): The column in which to begin comments to the right of preprocessor directives. `star_comment_cont' ("sc"): Place a star ('*') to the left of the comment body. `max_col' ("l"): The length of a line. Formatted comments which extend past this column will be continued on the following line. `block_comment_max_col' ("lc"): Unused. `blanklines_before_blockcomments'("nbbb"): Unused. */voidprint_comment (){ register int column, format; enum codes comment_type; int start_column, save_length, found_column; int first_comment_line, right_margin; int boxed_comment, stars, blankline_delims, paragraph_break, merge_blank_comment_lines; char *line_break_ptr = 0; char *save_ptr = 0; char *text_on_line = 0; char *start_delim, *end_delim; char *line_preamble; int line_preamble_length, visible_preamble; /* Increment the parser stack, as we will store some things there for dump_line to use. */ inc_pstack (); /* Have to do it this way because this piece of shit program doesn't always place the last token code on the stack. */ if (*(token + 1) == '/') comment_type = cplus_comment; else comment_type = comment; /* First, decide what kind of comment this is: C++, C, or boxed C. Even if this appears to be a normal C comment, we may change our minds if we find a star in the right column of the second line, in which case that's a boxed comment too. */ if (comment_type == cplus_comment) { start_delim = "//"; line_preamble = "// "; line_preamble_length = 3; visible_preamble = 1; boxed_comment = 0; stars = 0; blankline_delims = 0; } else if (*buf_ptr == '*' || *buf_ptr == '-' || *buf_ptr == '=' || *buf_ptr == '_') /* Boxed comment */ { start_delim = "/*"; end_delim = "*/"; line_preamble = " "; line_preamble_length = 1; visible_preamble = 0; boxed_comment = 1; stars = 0; blankline_delims = 0; } else { start_delim = "/*"; end_delim = "*/"; line_preamble = 0; line_preamble_length = 0; visible_preamble = 0; boxed_comment = 0; stars = star_comment_cont; blankline_delims = comment_delimiter_on_blankline; } paragraph_break = 0; merge_blank_comment_lines = 0; first_comment_line = com_lines; right_margin = max_col; /* Now, compute the correct indentation for this comment and whether or not it should be formatted. */ found_column = current_column () - 2; if (boxed_comment) { start_column = found_column; format = 0; blankline_delims = 0; } else { /* First handle comments which begin the line. */ if ((s_lab == e_lab) && (s_code == e_code)) { /* This is a top-level comment, not within some code. */ if (parser_state_tos->ind_level <= 0) { if (parser_state_tos->col_1) { format = format_col1_comments; start_column = 1; } else { format = format_comments; start_column = found_column; } } /* Here for comments starting a line, in the middle of code. */ else { if (parser_state_tos->col_1) { format = format_col1_comments; start_column = 1; } else { format = format_comments; start_column = (parser_state_tos->ind_level - unindent_displace + 1); if (start_column < 0) start_column = 1; } } } else /* This comment follows code of some sort. */ { int target; /* First, compute where the comment SHOULD go. */ if (parser_state_tos->decl_on_line) target = decl_com_ind; else if (else_or_endif) target = else_endif_col; else target = com_ind; /* Now determine if the code on the line is short enough to allow the comment to begin where it should. */ if (s_code != e_code) start_column = count_columns (compute_code_target (), s_code); else /* s_lab != e_lab : there is a label here. */ start_column = count_columns (compute_label_target (), s_lab); if (start_column < target) start_column = target; else { /* If the too-long code is a pre-processor command, start the comment 1 space afterwards, otherwise start at the next tab mark. */ if (else_or_endif) { start_column++; else_or_endif = false; } else start_column += (tabsize - (start_column % tabsize) + 1); } format = format_comments; } } if (! line_preamble) { line_preamble_length = 3; if (stars) { line_preamble = " * "; visible_preamble = 1; } else { line_preamble = " "; visible_preamble = 0; } } /* These are the parser stack variables used to communicate formatting information to dump_line (). */ parser_state_tos->com_col = start_column; parser_state_tos->box_com = boxed_comment; if (boxed_comment) { stars = 0; blankline_delims = 0; } /* Output the beginning comment delimiter. They are both two characters long. */ memcpy (e_com, start_delim, 2); e_com += 2; column = start_column + 2; /* If the user specified -cdb, put the delimiter on one line. */ if (blankline_delims) { char *p = buf_ptr; *e_com = '\0'; dump_line (); /* Check if the delimiter was already on a line by itself, and skip whitespace if formating. */ while ((*p == ' ' || *p == TAB) && p < buf_end) p++; if (*p == EOL) buf_ptr = p + 1; else if (format) buf_ptr = p; if (buf_ptr >= buf_end) fill_buffer (); column = start_column; goto begin_line; } else if (format) { *e_com++ = ' '; column = start_column + 3; while (*buf_ptr == ' ' || *buf_ptr == TAB) buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); } /* Iterate through the lines of the comment */ while (1) { /* Iterate through the characters on one line */ while (1) { CHECK_COM_SIZE; switch (*buf_ptr) { case ' ': case TAB: /* If formatting, and previous break marker is nonexistant, or before text on line, reset it to here. */ if (format && line_break_ptr < text_on_line) line_break_ptr = e_com; if (*buf_ptr == ' ') { *e_com++ = ' '; column++; } else { /* Convert the tab to the appropriate number of spaces, based on the column we found the comment in, not the one we're printing in. */ int tab_width = (tabsize - ((column + found_column - start_column - 1) % tabsize)); column += tab_width; while (tab_width--) *e_com++ = ' '; } break; case EOL: /* We may be at the end of a C++ comment */ if (comment_type == cplus_comment) { dump_line (); buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); parser_state_tos->tos--; parser_state_tos->com_col = start_column; return; } if (format) { /* Newline and null are the two characters which end an input line, so check here if we need to get the next line. */ buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); /* If this is "\n\n", it's a paragraph break. */ if (*buf_ptr == EOL || ! text_on_line) { paragraph_break = 1; goto end_line; } /* This is a single newline. Transform it, and any following whitespace into a single blank. */ line_break_ptr = e_com; *e_com++ = ' '; column++; while (*buf_ptr == TAB || *buf_ptr == ' ') buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); continue; } else /* We are printing this line "as is", so output it and continue on to the next line. */ goto end_line; break; case '*': /* Check if we've reached the end of the comment. */ if (comment_type == comment) { if (*(buf_ptr + 1) == '/') { /* If it's not a boxed comment, put some whitespace before the ending delimiter. Otherwise, simply insert the delimiter. */ if (! boxed_comment) { if (text_on_line) { if (blankline_delims) { *e_com = '\0'; dump_line (); *e_com++ = ' '; } else /* Here I also tried some code to ensure that the ending delimiter didn't exceed max_col of formatted comments. But it's not worth the hassle. */ if (*(e_com - 1) != ' ') *e_com++ = ' '; } else e_com = s_com + 1; } *e_com++ = '*'; *e_com++ = '/'; *e_com = '\0'; /* Skip any whitespace following the comment. If there is only whitespace after it, print the line. */ buf_ptr += 2; while (*buf_ptr == ' ' || *buf_ptr == TAB) buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); parser_state_tos->tos--; parser_state_tos->com_col = start_column; return; } /* If this star is on the second line of the comment in the same column as the star of the beginning delimiter, then consider it a boxed comment. */ if (first_comment_line == com_lines - 1 && e_com == s_com + line_preamble_length && current_column () == start_column + 1) { line_preamble = " "; line_preamble_length = 1; boxed_comment = 1; format = 0; blankline_delims = 0; *s_com = ' '; *(s_com + 1) = '*'; e_com = s_com + 2; column++; break; } } /* If it was not the end of the comment, drop through and insert the star on the line. */ default: /* Some textual character. */ text_on_line = e_com; *e_com++ = *buf_ptr; column++; break; } /* If we are formatting, check that we haven't exceeded the line length. If we haven't set line_break_ptr, keep going. */ if (format && column > right_margin && line_break_ptr) { if (line_break_ptr < e_com - 1) { *line_break_ptr = '\0'; save_ptr = line_break_ptr + 1; save_length = e_com - save_ptr; e_com = line_break_ptr; /* If we had to go past `right_margin' to print stuff out, extend `right_margin' out to this point. */ if ((column - save_length) > right_margin) right_margin = column - save_length; } else *e_com = '\0'; goto end_line; } buf_ptr++; } end_line: /* Compress pure whitespace lines into newlines. */ if (! text_on_line && ! visible_preamble && ! (first_comment_line == com_lines)) e_com = s_com; *e_com = '\0'; dump_line (); /* If formatting (paragraph_break is only used for formatted comments) and user wants blank lines merged, kill all white space after the "\n\n" indicating a paragraph break. */ if (paragraph_break) { if (merge_blank_comment_lines) while (*buf_ptr == EOL || *buf_ptr == ' ' || *buf_ptr == TAB) if (++buf_ptr >= buf_end) fill_buffer (); paragraph_break = 0; } else { /* If it was a paragraph break (`if' clause), we scanned ahead one character. So, here in the `else' clause, advance buf_ptr. */ buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); } begin_line: /* Indent the line properly. If it's a boxed comment, align with the '*' in the beginning slash-star and start inserting there. Otherwise, insert blanks for alignment, or a star if the user specified -sc. */ if (line_preamble) { memcpy (e_com, line_preamble, line_preamble_length); e_com += line_preamble_length; column = start_column + line_preamble_length; } else column = start_column; line_break_ptr = 0; /* If we have broken the line before the end for formatting, copy the text after the break onto the beginning of this new comment line. */ if (save_ptr) { while ((*save_ptr == ' ' || *save_ptr == TAB) && save_length) { save_ptr++; save_length--; } memcpy (e_com, save_ptr, save_length); text_on_line = e_com; e_com += save_length; /* We only break if formatting, in which cases there are no tabs, only spaces.*/ column += save_length; save_ptr = 0; } else { while (*buf_ptr == ' ' || *buf_ptr == TAB) buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); text_on_line = 0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -