Line data Source code
1 : /*-
2 : * Copyright (c) 1985 Sun Microsystems, Inc.
3 : * Copyright (c) 1980, 1993
4 : * The Regents of the University of California. All rights reserved.
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. Neither the name of the University nor the names of its contributors
16 : * may be used to endorse or promote products derived from this software
17 : * without specific prior written permission.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : * SUCH DAMAGE.
30 : */
31 :
32 : #if 0
33 : #ifndef lint
34 : static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93";
35 : #endif /* not lint */
36 : #endif
37 :
38 : #include "c.h"
39 :
40 : #include <err.h>
41 : #include <stdio.h>
42 : #include <stdlib.h>
43 : #include <string.h>
44 : #include "indent_globs.h"
45 : #include "indent_codes.h"
46 : #include "indent.h"
47 : /*
48 : * NAME:
49 : * pr_comment
50 : *
51 : * FUNCTION:
52 : * This routine takes care of scanning and printing comments.
53 : *
54 : * ALGORITHM:
55 : * 1) Decide where the comment should be aligned, and if lines should
56 : * be broken.
57 : * 2) If lines should not be broken and filled, just copy up to end of
58 : * comment.
59 : * 3) If lines should be filled, then scan thru input_buffer copying
60 : * characters to com_buf. Remember where the last blank, tab, or
61 : * newline was. When line is filled, print up to last blank and
62 : * continue copying.
63 : *
64 : * HISTORY:
65 : * November 1976 D A Willcox of CAC Initial coding
66 : * 12/6/76 D A Willcox of CAC Modification to handle
67 : * UNIX-style comments
68 : *
69 : */
70 :
71 : /*
72 : * this routine processes comments. It makes an attempt to keep comments from
73 : * going over the max line length. If a line is too long, it moves everything
74 : * from the last blank to the next comment line. Blanks and tabs from the
75 : * beginning of the input line are removed
76 : */
77 :
78 : void
79 116 : pr_comment(void)
80 : {
81 : int now_col; /* column we are in now */
82 : int adj_max_col; /* Adjusted max_col for when we decide to
83 : * spill comments over the right margin */
84 : char *last_bl; /* points to the last blank in the output
85 : * buffer */
86 : char *t_ptr; /* used for moving string */
87 116 : int break_delim = comment_delimiter_on_blankline;
88 116 : int l_just_saw_decl = ps.just_saw_decl;
89 116 : adj_max_col = max_col;
90 116 : ps.just_saw_decl = 0;
91 116 : last_bl = NULL; /* no blanks found so far */
92 116 : ps.box_com = false; /* at first, assume that we are not in
93 : * a boxed comment or some other
94 : * comment that should not be touched */
95 116 : ++ps.out_coms; /* keep track of number of comments */
96 :
97 : /* Figure where to align and how to treat the comment */
98 :
99 116 : if (ps.col_1 && !format_col1_comments) { /* if comment starts in column
100 : * 1 it should not be touched */
101 0 : ps.box_com = true;
102 0 : break_delim = false;
103 0 : ps.com_col = 1;
104 : }
105 : else {
106 116 : if (*buf_ptr == '-' || *buf_ptr == '*' ||
107 108 : (*buf_ptr == '\n' && !format_block_comments)) {
108 8 : ps.box_com = true; /* A comment with a '-' or '*' immediately
109 : * after the /+* is assumed to be a boxed
110 : * comment. A comment with a newline
111 : * immediately after the /+* is assumed to
112 : * be a block comment and is treated as a
113 : * box comment unless format_block_comments
114 : * is nonzero (the default). */
115 8 : break_delim = false;
116 : }
117 116 : if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) {
118 : /* klg: check only if this line is blank */
119 : /*
120 : * If this (*and previous lines are*) blank, dont put comment way
121 : * out at left
122 : */
123 72 : ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
124 72 : adj_max_col = block_comment_max_col;
125 72 : if (ps.com_col <= 1)
126 48 : ps.com_col = 1 + !format_col1_comments;
127 : }
128 : else {
129 : int target_col;
130 44 : break_delim = false;
131 44 : if (s_code != e_code)
132 32 : target_col = count_spaces(compute_code_target(), s_code);
133 : else {
134 12 : target_col = 1;
135 12 : if (s_lab != e_lab)
136 12 : target_col = count_spaces(compute_label_target(), s_lab);
137 : }
138 44 : if (s_lab != e_lab && s_lab[1] == 'e' &&
139 6 : (strncmp(s_lab, "#endif", 6) == 0 ||
140 4 : strncmp(s_lab, "#else", 5) == 0))
141 4 : ps.com_col = else_endif_com_ind <= target_col
142 4 : ? target_col + 1 : else_endif_com_ind;
143 : else
144 62 : ps.com_col = ps.decl_on_line || ps.ind_level == 0
145 62 : ? ps.decl_com_ind : ps.com_ind;
146 44 : if (ps.com_col <= target_col)
147 10 : ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1;
148 44 : if (ps.com_col + 24 > adj_max_col)
149 2 : adj_max_col = ps.com_col + 24;
150 : }
151 : }
152 116 : if (ps.box_com) {
153 : /*
154 : * Find out how much indentation there was originally, because that
155 : * much will have to be ignored by pad_output() in dump_line(). This
156 : * is a box comment, so nothing changes -- not even indentation.
157 : *
158 : * The comment we're about to read usually comes from in_buffer,
159 : * unless it has been copied into save_com.
160 : */
161 : char *start;
162 :
163 8 : start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ?
164 16 : sc_buf : in_buffer;
165 8 : ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2);
166 : }
167 : else {
168 108 : ps.n_comment_delta = 0;
169 210 : while (*buf_ptr == ' ' || *buf_ptr == '\t')
170 102 : buf_ptr++;
171 : }
172 116 : ps.comment_delta = 0;
173 116 : *e_com++ = '/'; /* put '/' followed by '*' into buffer */
174 116 : *e_com++ = '*';
175 116 : if (*buf_ptr != ' ' && !ps.box_com)
176 108 : *e_com++ = ' ';
177 :
178 : /*
179 : * Don't put a break delimiter if this is a one-liner that won't wrap.
180 : */
181 116 : if (break_delim)
182 1264 : for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) {
183 1258 : if (t_ptr >= buf_end)
184 0 : fill_buffer();
185 1258 : if (t_ptr[0] == '*' && t_ptr[1] == '/') {
186 62 : if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2))
187 60 : break_delim = false;
188 62 : break;
189 : }
190 : }
191 :
192 116 : if (break_delim) {
193 8 : char *t = e_com;
194 8 : e_com = s_com + 2;
195 8 : *e_com = 0;
196 8 : if (blanklines_before_blockcomments && ps.last_token != lbrace)
197 0 : prefix_blankline_requested = 1;
198 8 : dump_line();
199 8 : e_com = s_com = t;
200 8 : if (!ps.box_com && star_comment_cont)
201 8 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
202 : }
203 :
204 : /* Start to copy the comment */
205 :
206 : while (1) { /* this loop will go until the comment is
207 : * copied */
208 426 : switch (*buf_ptr) { /* this checks for various spcl cases */
209 0 : case 014: /* check for a form feed */
210 0 : CHECK_SIZE_COM(3);
211 0 : if (!ps.box_com) { /* in a text comment, break the line here */
212 0 : ps.use_ff = true;
213 : /* fix so dump_line uses a form feed */
214 0 : dump_line();
215 0 : last_bl = NULL;
216 0 : if (!ps.box_com && star_comment_cont)
217 0 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
218 0 : while (*++buf_ptr == ' ' || *buf_ptr == '\t')
219 : ;
220 : }
221 : else {
222 0 : if (++buf_ptr >= buf_end)
223 0 : fill_buffer();
224 0 : *e_com++ = 014;
225 : }
226 0 : break;
227 :
228 40 : case '\n':
229 40 : if (had_eof) { /* check for unexpected eof */
230 0 : printf("Unterminated comment\n");
231 0 : dump_line();
232 0 : return;
233 : }
234 40 : last_bl = NULL;
235 40 : CHECK_SIZE_COM(4);
236 40 : if (ps.box_com || ps.last_nl) { /* if this is a boxed comment,
237 : * we dont ignore the newline */
238 22 : if (s_com == e_com)
239 0 : *e_com++ = ' ';
240 22 : if (!ps.box_com && e_com - s_com > 3) {
241 6 : dump_line();
242 6 : if (star_comment_cont)
243 6 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
244 : }
245 22 : dump_line();
246 22 : if (!ps.box_com && star_comment_cont)
247 6 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
248 : }
249 : else {
250 18 : ps.last_nl = 1;
251 18 : if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
252 8 : last_bl = e_com - 1;
253 : /*
254 : * if there was a space at the end of the last line, remember
255 : * where it was
256 : */
257 : else { /* otherwise, insert one */
258 10 : last_bl = e_com;
259 10 : *e_com++ = ' ';
260 : }
261 : }
262 40 : ++line_no; /* keep track of input line number */
263 40 : if (!ps.box_com) {
264 24 : int nstar = 1;
265 : do { /* flush any blanks and/or tabs at start of
266 : * next line */
267 88 : if (++buf_ptr >= buf_end)
268 24 : fill_buffer();
269 88 : if (*buf_ptr == '*' && --nstar >= 0) {
270 24 : if (++buf_ptr >= buf_end)
271 0 : fill_buffer();
272 24 : if (*buf_ptr == '/')
273 6 : goto end_of_comment;
274 : }
275 82 : } while (*buf_ptr == ' ' || *buf_ptr == '\t');
276 : }
277 16 : else if (++buf_ptr >= buf_end)
278 8 : fill_buffer();
279 34 : break; /* end of case for newline */
280 :
281 186 : case '*': /* must check for possibility of being at end
282 : * of comment */
283 186 : if (++buf_ptr >= buf_end) /* get to next char after * */
284 0 : fill_buffer();
285 186 : CHECK_SIZE_COM(4);
286 186 : if (*buf_ptr == '/') { /* it is the end!!! */
287 110 : end_of_comment:
288 116 : if (++buf_ptr >= buf_end)
289 0 : fill_buffer();
290 116 : if (break_delim) {
291 8 : if (e_com > s_com + 3) {
292 6 : dump_line();
293 : }
294 : else
295 2 : s_com = e_com;
296 8 : *e_com++ = ' ';
297 : }
298 116 : if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com)
299 0 : *e_com++ = ' '; /* ensure blank before end */
300 116 : *e_com++ = '*', *e_com++ = '/', *e_com = '\0';
301 116 : ps.just_saw_decl = l_just_saw_decl;
302 116 : return;
303 : }
304 : else /* handle isolated '*' */
305 76 : *e_com++ = '*';
306 76 : break;
307 200 : default: /* we have a random char */
308 200 : now_col = count_spaces_until(ps.com_col, s_com, e_com);
309 : do {
310 2562 : CHECK_SIZE_COM(1);
311 2562 : *e_com = *buf_ptr++;
312 2562 : if (buf_ptr >= buf_end)
313 0 : fill_buffer();
314 2562 : if (*e_com == ' ' || *e_com == '\t')
315 488 : last_bl = e_com; /* remember we saw a blank */
316 2562 : ++e_com;
317 2562 : now_col++;
318 2366 : } while (!memchr("*\n\r\b\t", *buf_ptr, 6) &&
319 2672 : (now_col <= adj_max_col || !last_bl));
320 200 : ps.last_nl = false;
321 200 : if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') {
322 : /*
323 : * the comment is too long, it must be broken up
324 : */
325 8 : if (last_bl == NULL) {
326 2 : dump_line();
327 2 : if (!ps.box_com && star_comment_cont)
328 2 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
329 2 : break;
330 : }
331 6 : *e_com = '\0';
332 6 : e_com = last_bl;
333 6 : dump_line();
334 6 : if (!ps.box_com && star_comment_cont)
335 6 : *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
336 6 : for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t';
337 0 : t_ptr++)
338 : ;
339 6 : last_bl = NULL;
340 : /*
341 : * t_ptr will be somewhere between e_com (dump_line() reset)
342 : * and l_com. So it's safe to copy byte by byte from t_ptr
343 : * to e_com without any CHECK_SIZE_COM().
344 : */
345 14 : while (*t_ptr != '\0') {
346 8 : if (*t_ptr == ' ' || *t_ptr == '\t')
347 0 : last_bl = e_com;
348 8 : *e_com++ = *t_ptr++;
349 : }
350 : }
351 198 : break;
352 : }
353 : }
354 : }
|