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 /* NAME: pr_comment
22
23 FUNCTION: This routine takes care of scanning and printing comments.
24
25 ALGORITHM: 1) Decide where the comment should be aligned, and if lines should
26 be broken. 2) If lines should not be broken and filled, just copy up to
27 end of comment. 3) If lines should be filled, then scan thru input_buffer
28 copying characters to com_buf. Remember where the last blank, tab, or
29 newline was. When line is filled, print up to last blank and continue
30 copying.
31
32 HISTORY: November 1976 D A Willcox of CAC Initial coding 12/6/76
33 A Willcox of CAC Modification to handle UNIX-style comments
34
35 */
36
37 /* this routine processes comments. It makes an attempt to keep comments
38 from going over the max line length. If a line is too long, it moves
39 everything from the last blank to the next comment line. Blanks and tabs
40 from the beginning of the input line are removed */
41
42
43 #include "sys.h"
44 #include "indent.h"
45
46 /* Declared and documented in indent.h. */
47 int out_coms;
48
pr_comment()49 pr_comment ()
50 {
51 int now_col; /* column we are in now */
52 int adj_max_col; /* Adjusted max_col for when we decide to
53 spill comments over the right margin */
54 char *last_bl; /* points to the last blank in the output
55 buffer */
56 char *t_ptr; /* used for moving string */
57 int unix_comment; /* tri-state variable used to decide if it is
58 a unix-style comment. 0 means only blanks
59 since /*, 1 means regular style comment, 2
60 means unix style comment */
61 int break_delim = comment_delimiter_on_blankline;
62 int l_just_saw_decl = parser_state_tos->just_saw_decl;
63 /* int parser_state_tos->last_nl = 0; /* true iff the last
64 significant thing weve seen is a newline */
65 int one_liner = 1; /* true iff this comment is a one-liner */
66 adj_max_col = max_col;
67 parser_state_tos->just_saw_decl = 0;
68 last_bl = 0; /* no blanks found so far */
69 parser_state_tos->box_com = false; /* at first, assume that we are not
70 in a boxed comment or some other
71 comment that should not be touched */
72 ++out_coms; /* keep track of number of comments */
73 unix_comment = 1; /* set flag to let us figure out if there is
74 a unix-style comment ** DISABLED: use 0 to
75 reenable this hack! */
76
77 /* Figure where to align and how to treat the comment */
78
79 if (parser_state_tos->col_1 && !format_col1_comments)
80 { /* if comment starts in column 1 it should
81 not be touched */
82 parser_state_tos->box_com = true;
83 parser_state_tos->com_col = 1;
84 }
85 else
86 {
87 if (*buf_ptr == '-' || *buf_ptr == '*' || !format_comments)
88 {
89 parser_state_tos->box_com = true; /* a comment with a '-' or
90 '*' immediately after the
91 /* is assumed to be a
92 boxed comment */
93 break_delim = 0;
94 }
95
96
97 /* Used to also check that parser_state_tos->bl_line != 0 */
98 if ((s_lab == e_lab) && (s_code == e_code))
99 {
100 /* klg: check only if this line is blank */
101 /* If this (*and previous lines are*) blank, dont put comment way
102 out at left */
103 parser_state_tos->com_col
104 = (parser_state_tos->ind_level - unindent_displace) + 1;
105 adj_max_col = block_comment_max_col;
106 if (parser_state_tos->com_col <= 1)
107 parser_state_tos->com_col = 1 + !format_col1_comments;
108
109 /* If we have a comment in an old-style (pre-ANSI) parameter
110 declaration, indent it like we would the parameter declaration.
111 For example:
112 int destroy (what) / * N things to destroy. * / int what;
113 */
114 if (parser_state_tos->in_parameter_declaration
115 && indent_parameters != 0 && parser_state_tos->dec_nest == 0)
116 {
117 parser_state_tos->com_col = indent_parameters + 1;
118 parser_state_tos->ind_stmt = 0;
119 }
120 }
121 else
122 {
123 register target_col;
124 break_delim = 0;
125 if (s_code != e_code)
126 target_col = count_spaces (compute_code_target (), s_code);
127 else
128 {
129 target_col = 1;
130 if (s_lab != e_lab)
131 target_col = count_spaces (compute_label_target (), s_lab);
132 }
133 parser_state_tos->com_col = parser_state_tos->decl_on_line
134 || parser_state_tos->ind_level == 0 ? decl_com_ind : com_ind;
135 /* If we are already past the position for the comment, put it at
136 the next tab stop. */
137 if (parser_state_tos->com_col < target_col)
138 parser_state_tos->com_col = ((target_col + (tabsize - 1))
139 & ~(tabsize - 1)) + 1;
140 if (else_or_endif)
141 {
142 parser_state_tos->com_col = else_endif_col;
143 else_or_endif = false;
144 /* We want the comment to appear one space after the #else or
145 #endif. */
146 if (parser_state_tos->com_col < target_col)
147 parser_state_tos->com_col = target_col + 1;
148 }
149 if (parser_state_tos->com_col + 24 > adj_max_col)
150 adj_max_col = parser_state_tos->com_col + 24;
151 }
152 }
153 if (parser_state_tos->box_com)
154 {
155 parser_state_tos->n_comment_delta = 1 - parser_state_tos->com_col;
156 #if 0
157 buf_ptr[-2] = 0;
158 parser_state_tos->n_comment_delta = 1 - count_spaces (1, cur_line);
159 buf_ptr[-2] = '/';
160 #endif
161 }
162 else
163 {
164 parser_state_tos->n_comment_delta = 0;
165 while (*buf_ptr == ' ' || *buf_ptr == '\t')
166 buf_ptr++;
167 }
168 parser_state_tos->comment_delta = 0;
169 *e_com++ = '/'; /* put '/*' into buffer */
170 *e_com++ = '*';
171 if (*buf_ptr != ' ' && !parser_state_tos->box_com)
172 *e_com++ = ' ';
173
174 *e_com = '\0';
175 if (troff)
176 {
177 now_col = 1;
178 adj_max_col = 80;
179 }
180 else
181 /* figure what column we would be in if we printed the comment now */
182 now_col = count_spaces (parser_state_tos->com_col, s_com);
183
184 /* Start to copy the comment */
185
186 while (1)
187 { /* this loop will go until the comment is
188 copied */
189 if (*buf_ptr > 040 && *buf_ptr != '*')
190 parser_state_tos->last_nl = 0;
191 check_com_size;
192 switch (*buf_ptr)
193 { /* this checks for various spcl cases */
194 case 014: /* check for a form feed */
195 if (!parser_state_tos->box_com)
196 { /* in a text comment, break the line here */
197 parser_state_tos->use_ff = true;
198 /* fix so dump_line uses a form feed */
199 dump_line ();
200 last_bl = 0;
201 *e_com++ = ' ';
202 *e_com++ = '*';
203 *e_com++ = ' ';
204 while (*++buf_ptr == ' ' || *buf_ptr == '\t');
205 }
206 else
207 {
208 if (++buf_ptr >= buf_end)
209 fill_buffer ();
210 *e_com++ = 014;
211 }
212 break;
213
214 case '\n':
215 if (had_eof)
216 { /* check for unexpected eof */
217 printf ("Unterminated comment\n");
218 *e_com = '\0';
219 dump_line ();
220 return;
221 }
222 one_liner = 0;
223 if (parser_state_tos->box_com || parser_state_tos->last_nl)
224 { /* if this is a boxed comment, we dont ignore
225 the newline */
226 if (s_com == e_com)
227 {
228 *e_com++ = ' ';
229 *e_com++ = ' ';
230 }
231 *e_com = '\0';
232 if (!parser_state_tos->box_com && e_com - s_com > 3)
233 {
234 if (break_delim == 1 && s_com[0] == '/'
235 && s_com[1] == '*' && s_com[2] == ' ')
236 {
237 char *t = e_com;
238 break_delim = 2;
239 e_com = s_com + 2;
240 *e_com = 0;
241 if (blanklines_before_blockcomments)
242 prefix_blankline_requested = 1;
243 dump_line ();
244 e_com = t;
245 s_com[0] = s_com[1] = s_com[2] = ' ';
246 }
247 dump_line ();
248 check_com_size;
249 *e_com++ = ' ';
250 *e_com++ = ' ';
251 }
252 dump_line ();
253 now_col = parser_state_tos->com_col;
254 }
255 else
256 {
257 parser_state_tos->last_nl = 1;
258 if (unix_comment != 1)
259 { /* we not are in unix_style comment */
260 if (unix_comment == 0 && s_code == e_code)
261 {
262 /* if it is a UNIX-style comment, ignore the
263 requirement that previous line be blank for
264 unindention */
265 parser_state_tos->com_col
266 = ((parser_state_tos->ind_level - unindent_displace)
267 + ind_size);
268 if (parser_state_tos->com_col <= 1)
269 parser_state_tos->com_col = 2;
270 }
271 unix_comment = 2; /* permanently remember that we are
272 in this type of comment */
273 dump_line ();
274 ++line_no;
275 now_col = parser_state_tos->com_col;
276 *e_com++ = ' ';
277 /* fix so that the star at the start of the line will line
278 up */
279 do /* flush leading white space */
280 if (++buf_ptr >= buf_end)
281 fill_buffer ();
282 while (*buf_ptr == ' ' || *buf_ptr == '\t');
283 break;
284 }
285 if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
286 last_bl = e_com - 1;
287 /* if there was a space at the end of the last line, remember
288 where it was */
289 else
290 { /* otherwise, insert one */
291 last_bl = e_com;
292 check_com_size;
293 *e_com++ = ' ';
294 ++now_col;
295 }
296 }
297 ++line_no; /* keep track of input line number */
298 if (!parser_state_tos->box_com)
299 {
300 int nstar = 1;
301 do
302 { /* flush any blanks and/or tabs at start of
303 next line */
304 if (++buf_ptr >= buf_end)
305 fill_buffer ();
306 if (*buf_ptr == '*' && --nstar >= 0)
307 {
308 if (++buf_ptr >= buf_end)
309 fill_buffer ();
310 if (*buf_ptr == '/')
311 goto end_of_comment;
312 }
313 }
314 while (*buf_ptr == ' ' || *buf_ptr == '\t');
315 }
316 else if (++buf_ptr >= buf_end)
317 fill_buffer ();
318 break; /* end of case for newline */
319
320 case '*': /* must check for possibility of being at end
321 of comment */
322 if (++buf_ptr >= buf_end) /* get to next char after * */
323 fill_buffer ();
324
325 if (unix_comment == 0) /* set flag to show we are not in unix-style
326 comment */
327 unix_comment = 1;
328
329 if (*buf_ptr == '/')
330 { /* it is the end!!! */
331 end_of_comment:
332 if (++buf_ptr >= buf_end)
333 fill_buffer ();
334
335 if (*(e_com - 1) != ' ' && !parser_state_tos->box_com)
336 { /* insure blank before end */
337 *e_com++ = ' ';
338 ++now_col;
339 }
340 if (break_delim == 1 && !one_liner && s_com[0] == '/'
341 && s_com[1] == '*' && s_com[2] == ' ')
342 {
343 char *t = e_com;
344 break_delim = 2;
345 e_com = s_com + 2;
346 *e_com = 0;
347 if (blanklines_before_blockcomments)
348 prefix_blankline_requested = 1;
349 dump_line ();
350 e_com = t;
351 s_com[0] = s_com[1] = s_com[2] = ' ';
352 }
353 if (break_delim == 2 && e_com > s_com + 3
354 /* now_col > adj_max_col - 2 && !parser_state_tos->box_com */
355 )
356 {
357 *e_com = '\0';
358 dump_line ();
359 now_col = parser_state_tos->com_col;
360 }
361 check_com_size;
362 *e_com++ = '*';
363 *e_com++ = '/';
364 *e_com = '\0';
365 parser_state_tos->just_saw_decl = l_just_saw_decl;
366 return;
367 }
368 else
369 { /* handle isolated '*' */
370 *e_com++ = '*';
371 ++now_col;
372 }
373 break;
374 default: /* we have a random char */
375 if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t')
376 unix_comment = 1; /* we are not in unix-style comment */
377
378 *e_com = *buf_ptr++;
379 if (buf_ptr >= buf_end)
380 fill_buffer ();
381
382 if (*e_com == '\t') /* keep track of column */
383 now_col = now_col + tabsize - (now_col - 1) % tabsize;
384 else if (*e_com == '\b') /* this is a backspace */
385 --now_col;
386 else
387 ++now_col;
388
389 if (*e_com == ' ' || *e_com == '\t')
390 last_bl = e_com;
391 /* remember we saw a blank */
392
393 ++e_com;
394 if (now_col > adj_max_col
395 && !parser_state_tos->box_com
396 && unix_comment == 1 && e_com[-1] > ' ')
397 {
398 /* the comment is too long, it must be broken up */
399 if (break_delim == 1 && s_com[0] == '/'
400 && s_com[1] == '*' && s_com[2] == ' ')
401 {
402 char *t = e_com;
403 break_delim = 2;
404 e_com = s_com + 2;
405 *e_com = 0;
406 if (blanklines_before_blockcomments)
407 prefix_blankline_requested = 1;
408 dump_line ();
409 e_com = t;
410 s_com[0] = s_com[1] = s_com[2] = ' ';
411 }
412 if (last_bl == 0)
413 { /* we have seen no blanks */
414 last_bl = e_com; /* fake it */
415 *e_com++ = ' ';
416 }
417 *e_com = '\0'; /* print what we have */
418 *last_bl = '\0';
419 while (last_bl > s_com && last_bl[-1] < 040)
420 *--last_bl = 0;
421 e_com = last_bl;
422 dump_line ();
423
424 *e_com++ = ' '; /* add blanks for continuation */
425 *e_com++ = ' ';
426 *e_com++ = ' ';
427
428 t_ptr = last_bl + 1;
429 last_bl = 0;
430 if (t_ptr >= e_com)
431 {
432 while (*t_ptr == ' ' || *t_ptr == '\t')
433 t_ptr++;
434 while (*t_ptr != '\0')
435 { /* move unprinted part of comment down in
436 buffer */
437 if (*t_ptr == ' ' || *t_ptr == '\t')
438 last_bl = e_com;
439 *e_com++ = *t_ptr++;
440 }
441 }
442 *e_com = '\0';
443 /* recompute current position */
444 now_col = count_spaces (parser_state_tos->com_col, s_com);
445 }
446 break;
447 }
448 }
449 }
450