Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / indent / pr_comment.c
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. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * @(#)pr_comment.c     8.1 (Berkeley) 6/6/93
36  * $FreeBSD: src/usr.bin/indent/pr_comment.c,v 1.1.1.1.14.3 2001/12/06 19:28:47 schweikh Exp $
37  * $DragonFly: src/usr.bin/indent/pr_comment.c,v 1.2 2003/06/17 04:29:27 dillon Exp $
38  */
39 #if 0
40 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include "indent_globs.h"
44 #include "indent.h"
45 /*
46  * NAME:
47  *      pr_comment
48  *
49  * FUNCTION:
50  *      This routine takes care of scanning and printing comments.
51  *
52  * ALGORITHM:
53  *      1) Decide where the comment should be aligned, and if lines should
54  *         be broken.
55  *      2) If lines should not be broken and filled, just copy up to end of
56  *         comment.
57  *      3) If lines should be filled, then scan thru input_buffer copying
58  *         characters to com_buf.  Remember where the last blank, tab, or
59  *         newline was.  When line is filled, print up to last blank and
60  *         continue copying.
61  *
62  * HISTORY:
63  *      November 1976   D A Willcox of CAC      Initial coding
64  *      12/6/76         D A Willcox of CAC      Modification to handle
65  *                                              UNIX-style comments
66  *
67  */\f
68
69 /*
70  * this routine processes comments.  It makes an attempt to keep comments from
71  * going over the max line length.  If a line is too long, it moves everything
72  * from the last blank to the next comment line.  Blanks and tabs from the
73  * beginning of the input line are removed
74  */
75
76 void
77 pr_comment(void)
78 {
79     int         now_col;        /* column we are in now */
80     int         adj_max_col;    /* Adjusted max_col for when we decide to
81                                  * spill comments over the right margin */
82     char       *last_bl;        /* points to the last blank in the output
83                                  * buffer */
84     char       *t_ptr;          /* used for moving string */
85     int         unix_comment;   /* tri-state variable used to decide if it is
86                                  * a unix-style comment. 0 means only blanks
87                                  * since /+*, 1 means regular style comment, 2
88                                  * means unix style comment */
89     int         break_delim = comment_delimiter_on_blankline;
90     int         l_just_saw_decl = ps.just_saw_decl;
91     /*
92      * int         ps.last_nl = 0;       true iff the last significant thing
93      * weve seen is a newline
94      */
95     int         one_liner = 1;  /* true iff this comment is a one-liner */
96     adj_max_col = max_col;
97     ps.just_saw_decl = 0;
98     last_bl = 0;                /* no blanks found so far */
99     ps.box_com = false;         /* at first, assume that we are not in
100                                          * a boxed comment or some other
101                                          * comment that should not be touched */
102     ++ps.out_coms;              /* keep track of number of comments */
103     unix_comment = 1;           /* set flag to let us figure out if there is a
104                                  * unix-style comment ** DISABLED: use 0 to
105                                  * reenable this hack! */
106
107     /* Figure where to align and how to treat the comment */
108
109     if (ps.col_1 && !format_col1_comments) {    /* if comment starts in column
110                                                  * 1 it should not be touched */
111         ps.box_com = true;
112         ps.com_col = 1;
113     }
114     else {
115         if (*buf_ptr == '-' || *buf_ptr == '*' ||
116             (*buf_ptr == '\n' && !format_block_comments)) {
117             ps.box_com = true;  /* A comment with a '-' or '*' immediately
118                                  * after the /+* is assumed to be a boxed
119                                  * comment. A comment with a newline
120                                  * immediately after the /+* is assumed to
121                                  * be a block comment and is treated as a
122                                  * box comment unless format_block_comments
123                                  * is nonzero (the default). */
124             break_delim = 0;
125         }
126         if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) {
127             /* klg: check only if this line is blank */
128             /*
129              * If this (*and previous lines are*) blank, dont put comment way
130              * out at left
131              */
132             ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
133             adj_max_col = block_comment_max_col;
134             if (ps.com_col <= 1)
135                 ps.com_col = 1 + !format_col1_comments;
136         }
137         else {
138             register int target_col;
139             break_delim = 0;
140             if (s_code != e_code)
141                 target_col = count_spaces(compute_code_target(), s_code);
142             else {
143                 target_col = 1;
144                 if (s_lab != e_lab)
145                     target_col = count_spaces(compute_label_target(), s_lab);
146             }
147             ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind;
148             if (ps.com_col < target_col)
149                 ps.com_col = ((target_col + 7) & ~7) + 1;
150             if (ps.com_col + 24 > adj_max_col)
151                 adj_max_col = ps.com_col + 24;
152         }
153     }
154     if (ps.box_com) {
155         buf_ptr[-2] = 0;
156         ps.n_comment_delta = 1 - count_spaces(1, in_buffer);
157         buf_ptr[-2] = '/';
158     }
159     else {
160         ps.n_comment_delta = 0;
161         while (*buf_ptr == ' ' || *buf_ptr == '\t')
162             buf_ptr++;
163     }
164     ps.comment_delta = 0;
165     *e_com++ = '/';             /* put '/' followed by '*' into buffer */
166     *e_com++ = '*';
167     if (*buf_ptr != ' ' && !ps.box_com)
168         *e_com++ = ' ';
169
170     *e_com = '\0';
171     if (troff) {
172         now_col = 1;
173         adj_max_col = 80;
174     }
175     else
176         now_col = count_spaces(ps.com_col, s_com);      /* figure what column we
177                                                          * would be in if we
178                                                          * printed the comment
179                                                          * now */
180
181     /* Start to copy the comment */
182
183     while (1) {                 /* this loop will go until the comment is
184                                  * copied */
185         if (*buf_ptr > 040 && *buf_ptr != '*')
186             ps.last_nl = 0;
187         CHECK_SIZE_COM;
188         switch (*buf_ptr) {     /* this checks for various spcl cases */
189         case 014:               /* check for a form feed */
190             if (!ps.box_com) {  /* in a text comment, break the line here */
191                 ps.use_ff = true;
192                 /* fix so dump_line uses a form feed */
193                 dump_line();
194                 last_bl = 0;
195                 *e_com++ = ' ';
196                 *e_com++ = '*';
197                 *e_com++ = ' ';
198                 while (*++buf_ptr == ' ' || *buf_ptr == '\t');
199             }
200             else {
201                 if (++buf_ptr >= buf_end)
202                     fill_buffer();
203                 *e_com++ = 014;
204             }
205             break;
206
207         case '\n':
208             if (had_eof) {      /* check for unexpected eof */
209                 printf("Unterminated comment\n");
210                 *e_com = '\0';
211                 dump_line();
212                 return;
213             }
214             one_liner = 0;
215             if (ps.box_com || ps.last_nl) {     /* if this is a boxed comment,
216                                                  * we dont ignore the newline */
217                 if (s_com == e_com) {
218                     *e_com++ = ' ';
219                     *e_com++ = ' ';
220                 }
221                 *e_com = '\0';
222                 if (!ps.box_com && e_com - s_com > 3) {
223                     if (break_delim == 1 && s_com[0] == '/'
224                             && s_com[1] == '*' && s_com[2] == ' ') {
225                         char       *t = e_com;
226                         break_delim = 2;
227                         e_com = s_com + 2;
228                         *e_com = 0;
229                         if (blanklines_before_blockcomments)
230                             prefix_blankline_requested = 1;
231                         dump_line();
232                         e_com = t;
233                         s_com[0] = s_com[1] = s_com[2] = ' ';
234                     }
235                     dump_line();
236                     CHECK_SIZE_COM;
237                     *e_com++ = ' ';
238                     *e_com++ = ' ';
239                 }
240                 dump_line();
241                 now_col = ps.com_col;
242             }
243             else {
244                 ps.last_nl = 1;
245                 if (unix_comment != 1) {        /* we not are in unix_style
246                                                  * comment */
247                     if (unix_comment == 0 && s_code == e_code) {
248                         /*
249                          * if it is a UNIX-style comment, ignore the
250                          * requirement that previous line be blank for
251                          * unindention
252                          */
253                         ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
254                         if (ps.com_col <= 1)
255                             ps.com_col = 2;
256                     }
257                     unix_comment = 2;   /* permanently remember that we are in
258                                          * this type of comment */
259                     dump_line();
260                     ++line_no;
261                     now_col = ps.com_col;
262                     *e_com++ = ' ';
263                     /*
264                      * fix so that the star at the start of the line will line
265                      * up
266                      */
267                     do          /* flush leading white space */
268                         if (++buf_ptr >= buf_end)
269                             fill_buffer();
270                     while (*buf_ptr == ' ' || *buf_ptr == '\t');
271                     break;
272                 }
273                 if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
274                     last_bl = e_com - 1;
275                 /*
276                  * if there was a space at the end of the last line, remember
277                  * where it was
278                  */
279                 else {          /* otherwise, insert one */
280                     last_bl = e_com;
281                     CHECK_SIZE_COM;
282                     *e_com++ = ' ';
283                     ++now_col;
284                 }
285             }
286             ++line_no;          /* keep track of input line number */
287             if (!ps.box_com) {
288                 int         nstar = 1;
289                 do {            /* flush any blanks and/or tabs at start of
290                                  * next line */
291                     if (++buf_ptr >= buf_end)
292                         fill_buffer();
293                     if (*buf_ptr == '*' && --nstar >= 0) {
294                         if (++buf_ptr >= buf_end)
295                             fill_buffer();
296                         if (*buf_ptr == '/')
297                             goto end_of_comment;
298                     }
299                 } while (*buf_ptr == ' ' || *buf_ptr == '\t');
300             }
301             else if (++buf_ptr >= buf_end)
302                 fill_buffer();
303             break;              /* end of case for newline */
304
305         case '*':               /* must check for possibility of being at end
306                                  * of comment */
307             if (++buf_ptr >= buf_end)   /* get to next char after * */
308                 fill_buffer();
309
310             if (unix_comment == 0)      /* set flag to show we are not in
311                                          * unix-style comment */
312                 unix_comment = 1;
313
314             if (*buf_ptr == '/') {      /* it is the end!!! */
315         end_of_comment:
316                 if (++buf_ptr >= buf_end)
317                     fill_buffer();
318
319                 if (*(e_com - 1) != ' ' && !ps.box_com) {       /* insure blank before
320                                                                  * end */
321                     *e_com++ = ' ';
322                     ++now_col;
323                 }
324                 if (break_delim == 1 && !one_liner && s_com[0] == '/'
325                         && s_com[1] == '*' && s_com[2] == ' ') {
326                     char       *t = e_com;
327                     break_delim = 2;
328                     e_com = s_com + 2;
329                     *e_com = 0;
330                     if (blanklines_before_blockcomments)
331                         prefix_blankline_requested = 1;
332                     dump_line();
333                     e_com = t;
334                     s_com[0] = s_com[1] = s_com[2] = ' ';
335                 }
336                 if (break_delim == 2 && e_com > s_com + 3
337                          /* now_col > adj_max_col - 2 && !ps.box_com */ ) {
338                     *e_com = '\0';
339                     dump_line();
340                     now_col = ps.com_col;
341                 }
342                 CHECK_SIZE_COM;
343                 *e_com++ = '*';
344                 *e_com++ = '/';
345                 *e_com = '\0';
346                 ps.just_saw_decl = l_just_saw_decl;
347                 return;
348             }
349             else {              /* handle isolated '*' */
350                 *e_com++ = '*';
351                 ++now_col;
352             }
353             break;
354         default:                /* we have a random char */
355             if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t')
356                 unix_comment = 1;       /* we are not in unix-style comment */
357
358             *e_com = *buf_ptr++;
359             if (buf_ptr >= buf_end)
360                 fill_buffer();
361
362             if (*e_com == '\t') /* keep track of column */
363                 now_col = ((now_col - 1) & tabmask) + tabsize + 1;
364             else if (*e_com == '\b')    /* this is a backspace */
365                 --now_col;
366             else
367                 ++now_col;
368
369             if (*e_com == ' ' || *e_com == '\t')
370                 last_bl = e_com;
371             /* remember we saw a blank */
372
373             ++e_com;
374             if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') {
375                 /*
376                  * the comment is too long, it must be broken up
377                  */
378                 if (break_delim == 1 && s_com[0] == '/'
379                         && s_com[1] == '*' && s_com[2] == ' ') {
380                     char       *t = e_com;
381                     break_delim = 2;
382                     e_com = s_com + 2;
383                     *e_com = 0;
384                     if (blanklines_before_blockcomments)
385                         prefix_blankline_requested = 1;
386                     dump_line();
387                     e_com = t;
388                     s_com[0] = s_com[1] = s_com[2] = ' ';
389                 }
390                 if (last_bl == 0) {     /* we have seen no blanks */
391                     last_bl = e_com;    /* fake it */
392                     *e_com++ = ' ';
393                 }
394                 *e_com = '\0';  /* print what we have */
395                 *last_bl = '\0';
396                 while (last_bl > s_com && last_bl[-1] < 040)
397                     *--last_bl = 0;
398                 e_com = last_bl;
399                 dump_line();
400
401                 *e_com++ = ' '; /* add blanks for continuation */
402                 *e_com++ = ' ';
403                 *e_com++ = ' ';
404
405                 t_ptr = last_bl + 1;
406                 last_bl = 0;
407                 if (t_ptr >= e_com) {
408                     while (*t_ptr == ' ' || *t_ptr == '\t')
409                         t_ptr++;
410                     while (*t_ptr != '\0') {    /* move unprinted part of
411                                                  * comment down in buffer */
412                         if (*t_ptr == ' ' || *t_ptr == '\t')
413                             last_bl = e_com;
414                         *e_com++ = *t_ptr++;
415                     }
416                 }
417                 *e_com = '\0';
418                 now_col = count_spaces(ps.com_col, s_com);      /* recompute current
419                                                                  * position */
420             }
421             break;
422         }
423     }
424 }