Sun Mar 14 01:34:13 2021 UTC ()
indent: fix off-by-one error in comment wrapping

The manual page says that the default maximum length of a comment line
is 78.  The test 'comments.0' wrongly assumed that this 78 would refer
to the maximum _column_ allowed, which is off by one.

Fix the wording in the test 'comments.0' and remove the (now satisfied)
expectation comments in the test 'token-comment.0'.

Several other tests just happened to hit that limit, fix these as well.


(rillig)
diff -r1.1 -r1.2 src/tests/usr.bin/indent/comments.0
diff -r1.1 -r1.2 src/tests/usr.bin/indent/comments.0.stdout
diff -r1.1 -r1.2 src/tests/usr.bin/indent/opt-bap+sob.0.stdout
diff -r1.1 -r1.2 src/tests/usr.bin/indent/token-keyword_do_else.0.stdout
diff -r1.2 -r1.3 src/tests/usr.bin/indent/opt-P.0.stdout
diff -r1.2 -r1.3 src/tests/usr.bin/indent/token-comment.0.stdout
diff -r1.31 -r1.32 src/usr.bin/indent/pr_comment.c

cvs diff -r1.1 -r1.2 src/tests/usr.bin/indent/Attic/comments.0 (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/comments.0 2019/04/04 15:27:35 1.1
+++ src/tests/usr.bin/indent/Attic/comments.0 2021/03/14 01:34:13 1.2
@@ -1,53 +1,54 @@ @@ -1,53 +1,54 @@
1/* $NetBSD: comments.0,v 1.1 2019/04/04 15:27:35 kamil Exp $ */ 1/* $NetBSD: comments.0,v 1.2 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD: head/usr.bin/indent/tests/comments.0 321383 2017-07-23 15:07:52Z pstef $ */ 2/* $FreeBSD: head/usr.bin/indent/tests/comments.0 321383 2017-07-23 15:07:52Z pstef $ */
3typedef enum x { 3typedef enum x {
4 aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ 4 aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */
5 bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ 5 bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */
6 cccccccccccccc = 1 << 1, /* test c */ 6 cccccccccccccc = 1 << 1, /* test c */
7 dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ 7 dddddddddddddddddddddddddddddd = 1 << 2 /* test d */
8} x; 8} x;
9 9
10/* See r303597, r303598, r309219, and r309343 */ 10/* See r303597, r303598, r309219, and r309343 */
11void t(void) { 11void t(void) {
12 /* 12 /*
13 * Old indent wrapped the URL near where this sentence ends. 13 * Old indent wrapped the URL near where this sentence ends.
14 * 14 *
15 * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html 15 * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html
16 */ 16 */
17  17
18 /* 18 /*
19 * Old indent did not wrap to column 78 19 * The default maximum line length for comments is 78, and the 'kk' at
20 *  20 * the end makes the line exactly 78 bytes long.
 21 *
21 * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk 22 * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk
22 */ 23 */
23  24
24 /* 25 /*
25 * Old indent unnecessarily removed the star comment continuation on the next line. 26 * Old indent unnecessarily removed the star comment continuation on the next line.
26 *  27 *
27 * *test* 28 * *test*
28 */ 29 */
29  30
30 /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */ 31 /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */
31  32
32 /* r309343 */ 33 /* r309343 */
33} 34}
34 35
35int c(void) 36int c(void)
36{ 37{
37 if (1) { /*- a christmas tree * 38 if (1) { /*- a christmas tree *
38 *** 39 ***
39 ***** */ 40 ***** */
40 /*- another one * 41 /*- another one *
41 *** 42 ***
42 ***** */ 43 ***** */
43 7; 44 7;
44 } 45 }
45 46
46 if (1) /*- a christmas tree * 47 if (1) /*- a christmas tree *
47 *** 48 ***
48 ***** */ 49 ***** */
49 /*- another one * 50 /*- another one *
50 *** 51 ***
51 ***** */ 52 ***** */
52 1; 53 1;
53} 54}

cvs diff -r1.1 -r1.2 src/tests/usr.bin/indent/Attic/comments.0.stdout (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/comments.0.stdout 2019/04/04 15:27:35 1.1
+++ src/tests/usr.bin/indent/Attic/comments.0.stdout 2021/03/14 01:34:13 1.2
@@ -1,61 +1,61 @@ @@ -1,61 +1,61 @@
1/* $NetBSD: comments.0.stdout,v 1.1 2019/04/04 15:27:35 kamil Exp $ */ 1/* $NetBSD: comments.0.stdout,v 1.2 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD: head/usr.bin/indent/tests/comments.0.stdout 334563 2018-06-03 15:28:55Z pstef $ */ 2/* $FreeBSD: head/usr.bin/indent/tests/comments.0.stdout 334563 2018-06-03 15:28:55Z pstef $ */
3typedef enum x { 3typedef enum x {
4 aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ 4 aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */
5 bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ 5 bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */
6 cccccccccccccc = 1 << 1, /* test c */ 6 cccccccccccccc = 1 << 1, /* test c */
7 dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ 7 dddddddddddddddddddddddddddddd = 1 << 2 /* test d */
8} x; 8} x;
9 9
10/* See r303597, r303598, r309219, and r309343 */ 10/* See r303597, r303598, r309219, and r309343 */
11void 11void
12t(void) 12t(void)
13{ 13{
14 /* 14 /*
15 * Old indent wrapped the URL near where this sentence ends. 15 * Old indent wrapped the URL near where this sentence ends.
16 * 16 *
17 * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html 17 * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html
18 */ 18 */
19 19
20 /* 20 /*
21 * Old indent did not wrap to column 78 21 * The default maximum line length for comments is 78, and the 'kk' at
 22 * the end makes the line exactly 78 bytes long.
22 * 23 *
23 * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj 24 * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk
24 * kk 
25 */ 25 */
26 26
27 /* 27 /*
28 * Old indent unnecessarily removed the star comment continuation on 28 * Old indent unnecessarily removed the star comment continuation on
29 * the next line. 29 * the next line.
30 * 30 *
31 * *test* 31 * *test*
32 */ 32 */
33 33
34 /* 34 /*
35 * r309219 Go through linked list, freeing from the malloced (t[-1]) 35 * r309219 Go through linked list, freeing from the malloced (t[-1])
36 * address. 36 * address.
37 */ 37 */
38 38
39 /* r309343 */ 39 /* r309343 */
40} 40}
41 41
42int 42int
43c(void) 43c(void)
44{ 44{
45 if (1) { /*- a christmas tree * 45 if (1) { /*- a christmas tree *
46 *** 46 ***
47 ***** */ 47 ***** */
48 /*- another one * 48 /*- another one *
49 *** 49 ***
50 ***** */ 50 ***** */
51 7; 51 7;
52 } 52 }
53 53
54 if (1) /*- a christmas tree * 54 if (1) /*- a christmas tree *
55 *** 55 ***
56 ***** */ 56 ***** */
57 /*- another one * 57 /*- another one *
58 *** 58 ***
59 ***** */ 59 ***** */
60 1; 60 1;
61} 61}

cvs diff -r1.1 -r1.2 src/tests/usr.bin/indent/Attic/opt-bap+sob.0.stdout (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/opt-bap+sob.0.stdout 2021/03/08 22:13:05 1.1
+++ src/tests/usr.bin/indent/Attic/opt-bap+sob.0.stdout 2021/03/14 01:34:13 1.2
@@ -1,20 +1,20 @@ @@ -1,20 +1,20 @@
1/* $NetBSD: opt-bap+sob.0.stdout,v 1.1 2021/03/08 22:13:05 rillig Exp $ */ 1/* $NetBSD: opt-bap+sob.0.stdout,v 1.2 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD$ */ 2/* $FreeBSD$ */
3 3
4/* 4/*
5 * As of 2021-03-08, the combination of -bap and -sob, which occurs in the 5 * As of 2021-03-08, the combination of -bap and -sob, which occurs in the
6 * example indent.pro from NetBSD, removes the empty line above the 6 * example indent.pro from NetBSD, removes the empty line above the separator.
7 * separator. Seen in games/cgram/cgram.c. 7 * Seen in games/cgram/cgram.c.
8 */ 8 */
9 9
10void 10void
11function1(void) 11function1(void)
12{ 12{
13} 13}
14/* $ FIXME: Keep the empty line between the '}' and the '//'. */ 14/* $ FIXME: Keep the empty line between the '}' and the '//'. */
15///// separator ///// 15///// separator /////
16 16
17void 17void
18function2(void) 18function2(void)
19{ 19{
20} 20}

cvs diff -r1.1 -r1.2 src/tests/usr.bin/indent/Attic/token-keyword_do_else.0.stdout (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/token-keyword_do_else.0.stdout 2021/03/12 00:13:06 1.1
+++ src/tests/usr.bin/indent/Attic/token-keyword_do_else.0.stdout 2021/03/14 01:34:13 1.2
@@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
1/* $NetBSD: token-keyword_do_else.0.stdout,v 1.1 2021/03/12 00:13:06 rillig Exp $ */ 1/* $NetBSD: token-keyword_do_else.0.stdout,v 1.2 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD$ */ 2/* $FreeBSD$ */
3 3
4/* 4/*
5 * Tests for the keyword 'do' or 'else'. These two keywords are followed by 5 * Tests for the keyword 'do' or 'else'. These two keywords are followed by a
6 * a space. In contrast to 'for', 'if' and 'while', the space is not 6 * space. In contrast to 'for', 'if' and 'while', the space is not followed
7 * followed by a parenthesized expression. 7 * by a parenthesized expression.
8 */ 8 */
9 9
10/* TODO: Add some code to be formatted. */ 10/* TODO: Add some code to be formatted. */

cvs diff -r1.2 -r1.3 src/tests/usr.bin/indent/Attic/opt-P.0.stdout (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/opt-P.0.stdout 2021/03/07 10:12:18 1.2
+++ src/tests/usr.bin/indent/Attic/opt-P.0.stdout 2021/03/14 01:34:13 1.3
@@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
1/* $NetBSD: opt-P.0.stdout,v 1.2 2021/03/07 10:12:18 rillig Exp $ */ 1/* $NetBSD: opt-P.0.stdout,v 1.3 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD$ */ 2/* $FreeBSD$ */
3 3
4/* 4/*
5 * Mentioning another profile via -P has no effect since only a single 5 * Mentioning another profile via -P has no effect since only a single profile
6 * profile can be specified on the command line, and there is no 'include' 6 * can be specified on the command line, and there is no 'include' option.
7 * option. 
8 */ 7 */

cvs diff -r1.2 -r1.3 src/tests/usr.bin/indent/Attic/token-comment.0.stdout (switch to unified diff)

--- src/tests/usr.bin/indent/Attic/token-comment.0.stdout 2021/03/14 00:50:39 1.2
+++ src/tests/usr.bin/indent/Attic/token-comment.0.stdout 2021/03/14 01:34:13 1.3
@@ -1,25 +1,21 @@ @@ -1,25 +1,21 @@
1/* $NetBSD: token-comment.0.stdout,v 1.2 2021/03/14 00:50:39 rillig Exp $ */ 1/* $NetBSD: token-comment.0.stdout,v 1.3 2021/03/14 01:34:13 rillig Exp $ */
2/* $FreeBSD$ */ 2/* $FreeBSD$ */
3 3
4/* 4/*
5 * Tests for formatting comments. C99 defines block comments and end-of-line 5 * Tests for formatting comments. C99 defines block comments and end-of-line
6 * comments. Indent further distinguishes box comments that are a special 6 * comments. Indent further distinguishes box comments that are a special
7 * kind of block comments. 7 * kind of block comments.
8 */ 8 */
9 9
10/* TODO: Add some code to be formatted. */ 10/* TODO: Add some code to be formatted. */
11 11
12/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 */ 12/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 */
13/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 123456 */ 13/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 123456 */
14/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 1234567 */ 14/* 456789 123456789 123456789 123456789 123456789 123456789 123456789 1234567 */
15/* $ XXX: The '12345678' should be kept on the main line since it adds up */ 
16/* $ XXX: to a line length of exactly 78, which according to the manual */ 
17/* $ XXX: page should be ok. */ 
18/* 15/*
19 * 456789 123456789 123456789 123456789 123456789 123456789 123456789 16 * 456789 123456789 123456789 123456789 123456789 123456789 123456789 12345678
20 * 12345678 
21 */ 17 */
22/* 18/*
23 * 456789 123456789 123456789 123456789 123456789 123456789 123456789 19 * 456789 123456789 123456789 123456789 123456789 123456789 123456789
24 * 123456789 20 * 123456789
25 */ 21 */

cvs diff -r1.31 -r1.32 src/usr.bin/indent/pr_comment.c (switch to unified diff)

--- src/usr.bin/indent/pr_comment.c 2021/03/14 00:22:16 1.31
+++ src/usr.bin/indent/pr_comment.c 2021/03/14 01:34:13 1.32
@@ -1,378 +1,383 @@ @@ -1,378 +1,383 @@
1/* $NetBSD: pr_comment.c,v 1.31 2021/03/14 00:22:16 rillig Exp $ */ 1/* $NetBSD: pr_comment.c,v 1.32 2021/03/14 01:34:13 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-4-Clause 4 * SPDX-License-Identifier: BSD-4-Clause
5 * 5 *
6 * Copyright (c) 1985 Sun Microsystems, Inc. 6 * Copyright (c) 1985 Sun Microsystems, Inc.
7 * Copyright (c) 1980, 1993 7 * Copyright (c) 1980, 1993
8 * The Regents of the University of California. All rights reserved. 8 * The Regents of the University of California. All rights reserved.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software 19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement: 20 * must display the following acknowledgement:
21 * This product includes software developed by the University of 21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors. 22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors 23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software 24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission. 25 * without specific prior written permission.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE. 37 * SUCH DAMAGE.
38 */ 38 */
39 39
40#if 0 40#if 0
41#ifndef lint 41#ifndef lint
42static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; 42static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93";
43#endif /* not lint */ 43#endif /* not lint */
44#endif 44#endif
45 45
46#include <sys/cdefs.h> 46#include <sys/cdefs.h>
47#ifndef lint 47#ifndef lint
48#if defined(__NetBSD__) 48#if defined(__NetBSD__)
49__RCSID("$NetBSD: pr_comment.c,v 1.31 2021/03/14 00:22:16 rillig Exp $"); 49__RCSID("$NetBSD: pr_comment.c,v 1.32 2021/03/14 01:34:13 rillig Exp $");
50#elif defined(__FreeBSD__) 50#elif defined(__FreeBSD__)
51__FBSDID("$FreeBSD: head/usr.bin/indent/pr_comment.c 334927 2018-06-10 16:44:18Z pstef $"); 51__FBSDID("$FreeBSD: head/usr.bin/indent/pr_comment.c 334927 2018-06-10 16:44:18Z pstef $");
52#endif 52#endif
53#endif 53#endif
54 54
55#include <err.h> 55#include <err.h>
56#include <stdio.h> 56#include <stdio.h>
57#include <stdlib.h> 57#include <stdlib.h>
58#include <string.h> 58#include <string.h>
59 59
60#include "indent.h" 60#include "indent.h"
61 61
62static void 62static void
63check_size_comment(size_t desired_size, char **last_bl_ptr) 63check_size_comment(size_t desired_size, char **last_bl_ptr)
64{ 64{
65 if (e_com + (desired_size) < l_com) 65 if (e_com + (desired_size) < l_com)
66 return; 66 return;
67 67
68 size_t nsize = l_com - s_com + 400 + desired_size; 68 size_t nsize = l_com - s_com + 400 + desired_size;
69 size_t com_len = e_com - s_com; 69 size_t com_len = e_com - s_com;
70 ssize_t blank_pos = *last_bl_ptr != NULL ? *last_bl_ptr - combuf : -1; 70 ssize_t blank_pos = *last_bl_ptr != NULL ? *last_bl_ptr - combuf : -1;
71 combuf = realloc(combuf, nsize); 71 combuf = realloc(combuf, nsize);
72 if (combuf == NULL) 72 if (combuf == NULL)
73 err(1, NULL); 73 err(1, NULL);
74 e_com = combuf + com_len + 1; 74 e_com = combuf + com_len + 1;
75 if (blank_pos > 0) 75 if (blank_pos > 0)
76 *last_bl_ptr = combuf + blank_pos; 76 *last_bl_ptr = combuf + blank_pos;
77 l_com = combuf + nsize - 5; 77 l_com = combuf + nsize - 5;
78 s_com = combuf + 1; 78 s_com = combuf + 1;
79} 79}
80 80
81/* 81/*
82 * Scan, reformat and output a single comment, which is either a block comment 82 * Scan, reformat and output a single comment, which is either a block comment
83 * starting with '/' '*' or an end-of-line comment starting with '//'. 83 * starting with '/' '*' or an end-of-line comment starting with '//'.
84 * 84 *
85 * Try to keep comments from going over the maximum line length. If a line is 85 * Try to keep comments from going over the maximum line length. If a line is
86 * too long, move everything starting from the last blank to the next comment 86 * too long, move everything starting from the last blank to the next comment
87 * line. Blanks and tabs from the beginning of the input line are removed. 87 * line. Blanks and tabs from the beginning of the input line are removed.
88 * 88 *
89 * ALGORITHM: 89 * ALGORITHM:
90 * 1) Decide where the comment should be aligned, and if lines should 90 * 1) Decide where the comment should be aligned, and if lines should
91 * be broken. 91 * be broken.
92 * 2) If lines should not be broken and filled, just copy up to end of 92 * 2) If lines should not be broken and filled, just copy up to end of
93 * comment. 93 * comment.
94 * 3) If lines should be filled, then scan through the input buffer, 94 * 3) If lines should be filled, then scan through the input buffer,
95 * copying characters to com_buf. Remember where the last blank, 95 * copying characters to com_buf. Remember where the last blank,
96 * tab, or newline was. When line is filled, print up to last blank 96 * tab, or newline was. When line is filled, print up to last blank
97 * and continue copying. 97 * and continue copying.
98 */ 98 */
99void 99void
100process_comment(void) 100process_comment(void)
101{ 101{
102 int adj_max_line_length; /* Adjusted max_line_length for comments 102 int adj_max_line_length; /* Adjusted max_line_length for comments
103 * that spill over the right margin */ 103 * that spill over the right margin */
104 char *last_bl; /* points to the last blank in the output 104 char *last_bl; /* points to the last blank in the output
105 * buffer */ 105 * buffer */
106 char *t_ptr; /* used for moving string */ 106 char *t_ptr; /* used for moving string */
107 int break_delim = opt.comment_delimiter_on_blankline; 107 int break_delim = opt.comment_delimiter_on_blankline;
108 int l_just_saw_decl = ps.just_saw_decl; 108 int l_just_saw_decl = ps.just_saw_decl;
109 109
110 adj_max_line_length = opt.max_line_length; 110 adj_max_line_length = opt.max_line_length;
111 ps.just_saw_decl = 0; 111 ps.just_saw_decl = 0;
112 last_bl = NULL; /* no blanks found so far */ 112 last_bl = NULL; /* no blanks found so far */
113 ps.box_com = false; /* at first, assume that we are not in 113 ps.box_com = false; /* at first, assume that we are not in
114 * a boxed comment or some other 114 * a boxed comment or some other
115 * comment that should not be touched */ 115 * comment that should not be touched */
116 ++ps.out_coms; /* keep track of number of comments */ 116 ++ps.out_coms; /* keep track of number of comments */
117 117
118 /* Figure where to align and how to treat the comment */ 118 /* Figure where to align and how to treat the comment */
119 119
120 if (ps.col_1 && !opt.format_col1_comments) { /* if the comment starts in 120 if (ps.col_1 && !opt.format_col1_comments) { /* if the comment starts in
121 * column 1, it should not be touched */ 121 * column 1, it should not be touched */
122 ps.box_com = true; 122 ps.box_com = true;
123 break_delim = false; 123 break_delim = false;
124 ps.com_col = 1; 124 ps.com_col = 1;
125 } else { 125 } else {
126 if (*buf_ptr == '-' || *buf_ptr == '*' || e_token[-1] == '/' || 126 if (*buf_ptr == '-' || *buf_ptr == '*' || e_token[-1] == '/' ||
127 (*buf_ptr == '\n' && !opt.format_block_comments)) { 127 (*buf_ptr == '\n' && !opt.format_block_comments)) {
128 ps.box_com = true; /* A comment with a '-' or '*' immediately 128 ps.box_com = true; /* A comment with a '-' or '*' immediately
129 * after the /+* is assumed to be a boxed 129 * after the /+* is assumed to be a boxed
130 * comment. A comment with a newline 130 * comment. A comment with a newline
131 * immediately after the /+* is assumed to 131 * immediately after the /+* is assumed to
132 * be a block comment and is treated as a 132 * be a block comment and is treated as a
133 * box comment unless format_block_comments 133 * box comment unless format_block_comments
134 * is nonzero (the default). */ 134 * is nonzero (the default). */
135 break_delim = false; 135 break_delim = false;
136 } 136 }
137 if ( /* ps.bl_line && */ s_lab == e_lab && s_code == e_code) { 137 if ( /* ps.bl_line && */ s_lab == e_lab && s_code == e_code) {
138 /* klg: check only if this line is blank */ 138 /* klg: check only if this line is blank */
139 /* 139 /*
140 * If this (*and previous lines are*) blank, dont put comment way 140 * If this (*and previous lines are*) blank, dont put comment way
141 * out at left 141 * out at left
142 */ 142 */
143 ps.com_col = (ps.ind_level - opt.unindent_displace) * opt.indent_size + 1; 143 ps.com_col = (ps.ind_level - opt.unindent_displace) * opt.indent_size + 1;
144 adj_max_line_length = opt.block_comment_max_line_length; 144 adj_max_line_length = opt.block_comment_max_line_length;
145 if (ps.com_col <= 1) 145 if (ps.com_col <= 1)
146 ps.com_col = 1 + !opt.format_col1_comments; 146 ps.com_col = 1 + !opt.format_col1_comments;
147 } else { 147 } else {
148 int target_col; 148 int target_col;
149 break_delim = false; 149 break_delim = false;
150 if (s_code != e_code) 150 if (s_code != e_code)
151 target_col = 1 + indentation_after(compute_code_indent(), s_code); 151 target_col = 1 + indentation_after(compute_code_indent(), s_code);
152 else { 152 else {
153 target_col = 1; 153 target_col = 1;
154 if (s_lab != e_lab) 154 if (s_lab != e_lab)
155 target_col = 1 + indentation_after(compute_label_indent(), s_lab); 155 target_col = 1 + indentation_after(compute_label_indent(), s_lab);
156 } 156 }
157 ps.com_col = ps.decl_on_line || ps.ind_level == 0 157 ps.com_col = ps.decl_on_line || ps.ind_level == 0
158 ? opt.decl_comment_column : opt.comment_column; 158 ? opt.decl_comment_column : opt.comment_column;
159 if (ps.com_col <= target_col) 159 if (ps.com_col <= target_col)
160 ps.com_col = opt.tabsize * (1 + (target_col - 1) / opt.tabsize) + 1; 160 ps.com_col = opt.tabsize * (1 + (target_col - 1) / opt.tabsize) + 1;
161 if (ps.com_col + 24 > adj_max_line_length) 161 if (ps.com_col + 24 > adj_max_line_length)
162 /* XXX: mismatch between column and length */ 162 /* XXX: mismatch between column and length */
163 adj_max_line_length = ps.com_col + 24; 163 adj_max_line_length = ps.com_col + 24;
164 } 164 }
165 } 165 }
166 if (ps.box_com) { 166 if (ps.box_com) {
167 /* 167 /*
168 * Find out how much indentation there was originally, because that 168 * Find out how much indentation there was originally, because that
169 * much will have to be ignored by pad_output() in dump_line(). This 169 * much will have to be ignored by pad_output() in dump_line(). This
170 * is a box comment, so nothing changes -- not even indentation. 170 * is a box comment, so nothing changes -- not even indentation.
171 * 171 *
172 * The comment we're about to read usually comes from in_buffer, 172 * The comment we're about to read usually comes from in_buffer,
173 * unless it has been copied into save_com. 173 * unless it has been copied into save_com.
174 */ 174 */
175 char *start; 175 char *start;
176 176
177 /* 177 /*
178 * XXX: ordered comparison between pointers from different objects 178 * XXX: ordered comparison between pointers from different objects
179 * invokes undefined behavior (C99 6.5.8). 179 * invokes undefined behavior (C99 6.5.8).
180 */ 180 */
181 start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? 181 start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ?
182 sc_buf : in_buffer; 182 sc_buf : in_buffer;
183 ps.n_comment_delta = -indentation_after_range(0, start, buf_ptr - 2); 183 ps.n_comment_delta = -indentation_after_range(0, start, buf_ptr - 2);
184 } else { 184 } else {
185 ps.n_comment_delta = 0; 185 ps.n_comment_delta = 0;
186 while (*buf_ptr == ' ' || *buf_ptr == '\t') 186 while (*buf_ptr == ' ' || *buf_ptr == '\t')
187 buf_ptr++; 187 buf_ptr++;
188 } 188 }
189 ps.comment_delta = 0; 189 ps.comment_delta = 0;
190 *e_com++ = '/'; 190 *e_com++ = '/';
191 *e_com++ = e_token[-1]; 191 *e_com++ = e_token[-1];
192 if (*buf_ptr != ' ' && !ps.box_com) 192 if (*buf_ptr != ' ' && !ps.box_com)
193 *e_com++ = ' '; 193 *e_com++ = ' ';
194 194
195 /* 195 /*
196 * Don't put a break delimiter if this is a one-liner that won't wrap. 196 * Don't put a break delimiter if this is a one-liner that won't wrap.
197 */ 197 */
198 if (break_delim) 198 if (break_delim)
199 for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { 199 for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) {
200 if (t_ptr >= buf_end) 200 if (t_ptr >= buf_end)
201 fill_buffer(); 201 fill_buffer();
202 if (t_ptr[0] == '*' && t_ptr[1] == '/') { 202 if (t_ptr[0] == '*' && t_ptr[1] == '/') {
 203 /*
 204 * XXX: This computation ignores the leading " * ", as well
 205 * as the trailing ' ' '*' '/'. In simple cases, these cancel
 206 * out since they are equally long.
 207 */
203 int right_margin = indentation_after_range(ps.com_col - 1, 208 int right_margin = indentation_after_range(ps.com_col - 1,
204 buf_ptr, t_ptr + 2); 209 buf_ptr, t_ptr + 2);
205 if (right_margin < adj_max_line_length) 210 if (right_margin < adj_max_line_length)
206 break_delim = false; 211 break_delim = false;
207 break; 212 break;
208 } 213 }
209 } 214 }
210 215
211 if (break_delim) { 216 if (break_delim) {
212 char *t = e_com; 217 char *t = e_com;
213 e_com = s_com + 2; 218 e_com = s_com + 2;
214 *e_com = 0; 219 *e_com = 0;
215 if (opt.blanklines_before_blockcomments && ps.last_token != lbrace) 220 if (opt.blanklines_before_blockcomments && ps.last_token != lbrace)
216 prefix_blankline_requested = 1; 221 prefix_blankline_requested = 1;
217 dump_line(); 222 dump_line();
218 e_com = s_com = t; 223 e_com = s_com = t;
219 if (!ps.box_com && opt.star_comment_cont) 224 if (!ps.box_com && opt.star_comment_cont)
220 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 225 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
221 } 226 }
222 227
223 /* Start to copy the comment */ 228 /* Start to copy the comment */
224 229
225 for (;;) { /* this loop will go until the comment is 230 for (;;) { /* this loop will go until the comment is
226 * copied */ 231 * copied */
227 switch (*buf_ptr) { /* this checks for various special cases */ 232 switch (*buf_ptr) { /* this checks for various special cases */
228 case 014: /* check for a form feed */ 233 case 014: /* check for a form feed */
229 check_size_comment(3, &last_bl); 234 check_size_comment(3, &last_bl);
230 if (!ps.box_com) { /* in a text comment, break the line here */ 235 if (!ps.box_com) { /* in a text comment, break the line here */
231 ps.use_ff = true; 236 ps.use_ff = true;
232 /* fix so dump_line uses a form feed */ 237 /* fix so dump_line uses a form feed */
233 dump_line(); 238 dump_line();
234 last_bl = NULL; 239 last_bl = NULL;
235 if (!ps.box_com && opt.star_comment_cont) 240 if (!ps.box_com && opt.star_comment_cont)
236 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 241 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
237 while (*++buf_ptr == ' ' || *buf_ptr == '\t') 242 while (*++buf_ptr == ' ' || *buf_ptr == '\t')
238 ; 243 ;
239 } else { 244 } else {
240 if (++buf_ptr >= buf_end) 245 if (++buf_ptr >= buf_end)
241 fill_buffer(); 246 fill_buffer();
242 *e_com++ = 014; 247 *e_com++ = 014;
243 } 248 }
244 break; 249 break;
245 250
246 case '\n': 251 case '\n':
247 if (e_token[-1] == '/') { 252 if (e_token[-1] == '/') {
248 ++line_no; 253 ++line_no;
249 goto end_of_comment; 254 goto end_of_comment;
250 } 255 }
251 if (had_eof) { /* check for unexpected eof */ 256 if (had_eof) { /* check for unexpected eof */
252 printf("Unterminated comment\n"); 257 printf("Unterminated comment\n");
253 dump_line(); 258 dump_line();
254 return; 259 return;
255 } 260 }
256 last_bl = NULL; 261 last_bl = NULL;
257 check_size_comment(4, &last_bl); 262 check_size_comment(4, &last_bl);
258 if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, 263 if (ps.box_com || ps.last_nl) { /* if this is a boxed comment,
259 * we dont ignore the newline */ 264 * we dont ignore the newline */
260 if (s_com == e_com) 265 if (s_com == e_com)
261 *e_com++ = ' '; 266 *e_com++ = ' ';
262 if (!ps.box_com && e_com - s_com > 3) { 267 if (!ps.box_com && e_com - s_com > 3) {
263 dump_line(); 268 dump_line();
264 if (opt.star_comment_cont) 269 if (opt.star_comment_cont)
265 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 270 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
266 } 271 }
267 dump_line(); 272 dump_line();
268 if (!ps.box_com && opt.star_comment_cont) 273 if (!ps.box_com && opt.star_comment_cont)
269 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 274 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
270 } else { 275 } else {
271 ps.last_nl = 1; 276 ps.last_nl = 1;
272 if (e_com[-1] == ' ' || e_com[-1] == '\t') 277 if (e_com[-1] == ' ' || e_com[-1] == '\t')
273 last_bl = e_com - 1; 278 last_bl = e_com - 1;
274 /* 279 /*
275 * if there was a space at the end of the last line, remember 280 * if there was a space at the end of the last line, remember
276 * where it was 281 * where it was
277 */ 282 */
278 else { /* otherwise, insert one */ 283 else { /* otherwise, insert one */
279 last_bl = e_com; 284 last_bl = e_com;
280 *e_com++ = ' '; 285 *e_com++ = ' ';
281 } 286 }
282 } 287 }
283 ++line_no; /* keep track of input line number */ 288 ++line_no; /* keep track of input line number */
284 if (!ps.box_com) { 289 if (!ps.box_com) {
285 int nstar = 1; 290 int nstar = 1;
286 do { /* flush any blanks and/or tabs at start of 291 do { /* flush any blanks and/or tabs at start of
287 * next line */ 292 * next line */
288 if (++buf_ptr >= buf_end) 293 if (++buf_ptr >= buf_end)
289 fill_buffer(); 294 fill_buffer();
290 if (*buf_ptr == '*' && --nstar >= 0) { 295 if (*buf_ptr == '*' && --nstar >= 0) {
291 if (++buf_ptr >= buf_end) 296 if (++buf_ptr >= buf_end)
292 fill_buffer(); 297 fill_buffer();
293 if (*buf_ptr == '/') 298 if (*buf_ptr == '/')
294 goto end_of_comment; 299 goto end_of_comment;
295 } 300 }
296 } while (*buf_ptr == ' ' || *buf_ptr == '\t'); 301 } while (*buf_ptr == ' ' || *buf_ptr == '\t');
297 } else if (++buf_ptr >= buf_end) 302 } else if (++buf_ptr >= buf_end)
298 fill_buffer(); 303 fill_buffer();
299 break; /* end of case for newline */ 304 break; /* end of case for newline */
300 305
301 case '*': /* must check for possibility of being at end 306 case '*': /* must check for possibility of being at end
302 * of comment */ 307 * of comment */
303 if (++buf_ptr >= buf_end) /* get to next char after * */ 308 if (++buf_ptr >= buf_end) /* get to next char after * */
304 fill_buffer(); 309 fill_buffer();
305 check_size_comment(4, &last_bl); 310 check_size_comment(4, &last_bl);
306 if (*buf_ptr == '/') { /* it is the end!!! */ 311 if (*buf_ptr == '/') { /* it is the end!!! */
307 end_of_comment: 312 end_of_comment:
308 if (++buf_ptr >= buf_end) 313 if (++buf_ptr >= buf_end)
309 fill_buffer(); 314 fill_buffer();
310 if (break_delim) { 315 if (break_delim) {
311 if (e_com > s_com + 3) 316 if (e_com > s_com + 3)
312 dump_line(); 317 dump_line();
313 else 318 else
314 s_com = e_com; 319 s_com = e_com;
315 *e_com++ = ' '; 320 *e_com++ = ' ';
316 } 321 }
317 if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) 322 if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com)
318 *e_com++ = ' '; /* ensure blank before end */ 323 *e_com++ = ' '; /* ensure blank before end */
319 if (e_token[-1] == '/') 324 if (e_token[-1] == '/')
320 *e_com++ = '\n', *e_com = '\0'; 325 *e_com++ = '\n', *e_com = '\0';
321 else 326 else
322 *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; 327 *e_com++ = '*', *e_com++ = '/', *e_com = '\0';
323 ps.just_saw_decl = l_just_saw_decl; 328 ps.just_saw_decl = l_just_saw_decl;
324 return; 329 return;
325 } else /* handle isolated '*' */ 330 } else /* handle isolated '*' */
326 *e_com++ = '*'; 331 *e_com++ = '*';
327 break; 332 break;
328 default: /* we have a random char */ 333 default: /* we have a random char */
329 ; 334 ;
330 int now_len = indentation_after_range(ps.com_col - 1, s_com, e_com); 335 int now_len = indentation_after_range(ps.com_col - 1, s_com, e_com);
331 do { 336 do {
332 check_size_comment(1, &last_bl); 337 check_size_comment(1, &last_bl);
333 *e_com = *buf_ptr++; 338 *e_com = *buf_ptr++;
334 if (buf_ptr >= buf_end) 339 if (buf_ptr >= buf_end)
335 fill_buffer(); 340 fill_buffer();
336 if (*e_com == ' ' || *e_com == '\t') 341 if (*e_com == ' ' || *e_com == '\t')
337 last_bl = e_com; /* remember we saw a blank */ 342 last_bl = e_com; /* remember we saw a blank */
338 ++e_com; 343 ++e_com;
339 now_len++; 344 now_len++;
340 } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && 345 } while (!memchr("*\n\r\b\t", *buf_ptr, 6) &&
341 (now_len < adj_max_line_length || !last_bl)); 346 (now_len < adj_max_line_length || !last_bl));
342 ps.last_nl = false; 347 ps.last_nl = false;
343 /* XXX: signed character comparison '>' does not work for UTF-8 */ 348 /* XXX: signed character comparison '>' does not work for UTF-8 */
344 if (now_len >= adj_max_line_length && 349 if (now_len > adj_max_line_length &&
345 !ps.box_com && e_com[-1] > ' ') { 350 !ps.box_com && e_com[-1] > ' ') {
346 /* 351 /*
347 * the comment is too long, it must be broken up 352 * the comment is too long, it must be broken up
348 */ 353 */
349 if (last_bl == NULL) { 354 if (last_bl == NULL) {
350 dump_line(); 355 dump_line();
351 if (!ps.box_com && opt.star_comment_cont) 356 if (!ps.box_com && opt.star_comment_cont)
352 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 357 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
353 break; 358 break;
354 } 359 }
355 *e_com = '\0'; 360 *e_com = '\0';
356 e_com = last_bl; 361 e_com = last_bl;
357 dump_line(); 362 dump_line();
358 if (!ps.box_com && opt.star_comment_cont) 363 if (!ps.box_com && opt.star_comment_cont)
359 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; 364 *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
360 for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; 365 for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t';
361 t_ptr++) 366 t_ptr++)
362 ; 367 ;
363 last_bl = NULL; 368 last_bl = NULL;
364 /* 369 /*
365 * t_ptr will be somewhere between e_com (dump_line() reset) 370 * t_ptr will be somewhere between e_com (dump_line() reset)
366 * and l_com. So it's safe to copy byte by byte from t_ptr 371 * and l_com. So it's safe to copy byte by byte from t_ptr
367 * to e_com without any check_size_comment(). 372 * to e_com without any check_size_comment().
368 */ 373 */
369 while (*t_ptr != '\0') { 374 while (*t_ptr != '\0') {
370 if (*t_ptr == ' ' || *t_ptr == '\t') 375 if (*t_ptr == ' ' || *t_ptr == '\t')
371 last_bl = e_com; 376 last_bl = e_com;
372 *e_com++ = *t_ptr++; 377 *e_com++ = *t_ptr++;
373 } 378 }
374 } 379 }
375 break; 380 break;
376 } 381 }
377 } 382 }
378} 383}