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