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