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