Sat May 20 10:09:03 2023 UTC ()
indent: implement blank lines around conditional compilation


(rillig)
diff -r1.11 -r1.12 src/tests/usr.bin/indent/opt_bacc.c
diff -r1.15 -r1.16 src/usr.bin/indent/debug.c
diff -r1.296 -r1.297 src/usr.bin/indent/indent.c
diff -r1.152 -r1.153 src/usr.bin/indent/indent.h
diff -r1.178 -r1.179 src/usr.bin/indent/io.c

cvs diff -r1.11 -r1.12 src/tests/usr.bin/indent/opt_bacc.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/opt_bacc.c 2023/05/11 18:13:55 1.11
+++ src/tests/usr.bin/indent/opt_bacc.c 2023/05/20 10:09:03 1.12
@@ -1,54 +1,47 @@ @@ -1,54 +1,47 @@
1/* $NetBSD: opt_bacc.c,v 1.11 2023/05/11 18:13:55 rillig Exp $ */ 1/* $NetBSD: opt_bacc.c,v 1.12 2023/05/20 10:09:03 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the options '-bacc' and '-nbacc' ("blank line around conditional 4 * Tests for the options '-bacc' and '-nbacc' ("blank line around conditional
5 * compilation"). 5 * compilation").
6 * 6 *
7 * The option '-bacc' forces a blank line around every conditional compilation 7 * The option '-bacc' forces a blank line around every conditional compilation
8 * block. For example, in front of every #ifdef and after every #endif. 8 * block. For example, in front of every #ifdef and after every #endif.
9 * Other blank lines surrounding such blocks are swallowed. 9 * Other blank lines surrounding such blocks are swallowed.
10 * 10 *
11 * The option '-nbacc' TODO. 11 * The option '-nbacc' leaves the vertical spacing as-is.
12 */ 12 */
13 13
14 14
15/* Example code without surrounding blank lines. */ 15/* Example code without surrounding blank lines. */
16//indent input 16//indent input
17int a; 17int a;
18#if 0 18#if 0
19int b; 19int b;
20#endif 20#endif
21int c; 21int c;
22//indent end 22//indent end
23 23
24/* 
25 * XXX: As of 2021-11-19, the option -bacc has no effect on declarations since 
26 * process_type resets out.blank_line_before unconditionally. 
27 */ 
28//indent run -bacc 24//indent run -bacc
29int a; 25int a;
30/* $ FIXME: expecting a blank line here */ 26
31#if 0 27#if 0
32int b; 28int b;
33#endif 29#endif
34/* $ FIXME: expecting a blank line here */ 30
35int c; 31int c;
36//indent end 32//indent end
37 33
38/* 34/* The option '-nbacc' does not remove anything. */
39 * With '-nbacc' the code is unchanged since there are no blank lines to 
40 * remove. 
41 */ 
42//indent run-equals-input -nbacc 35//indent run-equals-input -nbacc
43 36
44 37
45/* Example code containing blank lines. */ 38/* Example code containing blank lines. */
46//indent input 39//indent input
47int space_a; 40int space_a;
48 41
49#if 0 42#if 0
50 43
51int space_b; 44int space_b;
52 45
53#endif 46#endif
54 47
@@ -70,33 +63,33 @@ os_name(void) @@ -70,33 +63,33 @@ os_name(void)
70{ 63{
71#if defined(__NetBSD__) || defined(__FreeBSD__) 64#if defined(__NetBSD__) || defined(__FreeBSD__)
72 return "BSD"; 65 return "BSD";
73#else 66#else
74 return "unknown"; 67 return "unknown";
75#endif 68#endif
76} 69}
77//indent end 70//indent end
78 71
79//indent run -bacc 72//indent run -bacc
80const char * 73const char *
81os_name(void) 74os_name(void)
82{ 75{
83/* $ FIXME: expecting a blank line here. */ 76
84#if defined(__NetBSD__) || defined(__FreeBSD__) 77#if defined(__NetBSD__) || defined(__FreeBSD__)
85 return "BSD"; 78 return "BSD";
86#else 79#else
87 return "unknown"; 80 return "unknown";
88#endif 81#endif
89/* $ FIXME: expecting a blank line here. */ 82
90} 83}
91//indent end 84//indent end
92 85
93//indent run-equals-input -nbacc 86//indent run-equals-input -nbacc
94 87
95 88
96/* 89/*
97 * Test nested preprocessor directives. 90 * Test nested preprocessor directives.
98 */ 91 */
99//indent input 92//indent input
100#if outer 93#if outer
101#if inner 94#if inner
102int decl; 95int decl;
@@ -112,16 +105,26 @@ int decl; @@ -112,16 +105,26 @@ int decl;
112/* 105/*
113 * Test nested preprocessor directives that are interleaved with declarations. 106 * Test nested preprocessor directives that are interleaved with declarations.
114 */ 107 */
115//indent input 108//indent input
116#ifdef outer 109#ifdef outer
117int outer_above; 110int outer_above;
118#ifdef inner 111#ifdef inner
119int inner; 112int inner;
120#endif 113#endif
121int outer_below; 114int outer_below;
122#endif 115#endif
123//indent end 116//indent end
124 117
125//indent run-equals-input -di0 -bacc 118//indent run -di0 -bacc
 119#ifdef outer
 120int outer_above;
 121
 122#ifdef inner
 123int inner;
 124#endif
 125
 126int outer_below;
 127#endif
 128//indent end
126 129
127//indent run-equals-input -di0 -nbacc 130//indent run-equals-input -di0 -nbacc

cvs diff -r1.15 -r1.16 src/usr.bin/indent/debug.c (expand / switch to unified diff)

--- src/usr.bin/indent/debug.c 2023/05/20 02:47:35 1.15
+++ src/usr.bin/indent/debug.c 2023/05/20 10:09:02 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: debug.c,v 1.15 2023/05/20 02:47:35 rillig Exp $ */ 1/* $NetBSD: debug.c,v 1.16 2023/05/20 10:09:02 rillig Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2023 The NetBSD Foundation, Inc. 4 * Copyright (c) 2023 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland Illig <rillig@NetBSD.org>. 8 * by Roland Illig <rillig@NetBSD.org>.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__RCSID("$NetBSD: debug.c,v 1.15 2023/05/20 02:47:35 rillig Exp $"); 33__RCSID("$NetBSD: debug.c,v 1.16 2023/05/20 10:09:02 rillig Exp $");
34 34
35#include <stdarg.h> 35#include <stdarg.h>
36 36
37#include "indent.h" 37#include "indent.h"
38 38
39#ifdef debug 39#ifdef debug
40 40
41/*- 41/*-
42 * false show only the changes to the parser state 42 * false show only the changes to the parser state
43 * true show unchanged parts of the parser state as well 43 * true show unchanged parts of the parser state as well
44 */ 44 */
45static bool debug_full_parser_state = true; 45static bool debug_full_parser_state = true;
46 46
@@ -107,26 +107,32 @@ static const char *const declaration_nam @@ -107,26 +107,32 @@ static const char *const declaration_nam
107static const char *const in_enum_name[] = { 107static const char *const in_enum_name[] = {
108 "no", 108 "no",
109 "enum", 109 "enum",
110 "type", 110 "type",
111 "brace", 111 "brace",
112}; 112};
113 113
114const char *const paren_level_cast_name[] = { 114const char *const paren_level_cast_name[] = {
115 "(unknown cast)", 115 "(unknown cast)",
116 "(maybe cast)", 116 "(maybe cast)",
117 "(no cast)", 117 "(no cast)",
118}; 118};
119 119
 120static const char *const line_kind_name[] = {
 121 "other",
 122 "#if",
 123 "#endif",
 124};
 125
120void 126void
121debug_printf(const char *fmt, ...) 127debug_printf(const char *fmt, ...)
122{ 128{
123 FILE *f = output == stdout ? stderr : stdout; 129 FILE *f = output == stdout ? stderr : stdout;
124 va_list ap; 130 va_list ap;
125 131
126 va_start(ap, fmt); 132 va_start(ap, fmt);
127 vfprintf(f, fmt, ap); 133 vfprintf(f, fmt, ap);
128 va_end(ap); 134 va_end(ap);
129} 135}
130 136
131void 137void
132debug_println(const char *fmt, ...) 138debug_println(const char *fmt, ...)
@@ -310,26 +316,29 @@ debug_parser_state(lexer_symbol lsym) @@ -310,26 +316,29 @@ debug_parser_state(lexer_symbol lsym)
310 debug_ps_int(decl_ind); 316 debug_ps_int(decl_ind);
311 debug_ps_bool(tabs_to_var); 317 debug_ps_bool(tabs_to_var);
312 318
313 debug_ps_bool(in_stmt_or_decl); 319 debug_ps_bool(in_stmt_or_decl);
314 debug_ps_bool(in_stmt_cont); 320 debug_ps_bool(in_stmt_cont);
315 debug_ps_bool(is_case_label); 321 debug_ps_bool(is_case_label);
316 debug_ps_bool(seen_case); 322 debug_ps_bool(seen_case);
317 323
318 // The debug output for the parser symbols is done in 'parse' instead. 324 // The debug output for the parser symbols is done in 'parse' instead.
319 325
320 debug_ps_enum(spaced_expr_psym, psym_name); 326 debug_ps_enum(spaced_expr_psym, psym_name);
321 debug_ps_int(quest_level); 327 debug_ps_int(quest_level);
322 328
 329 debug_ps_enum(line_kind, line_kind_name);
 330 debug_ps_enum(prev_line_kind, line_kind_name);
 331
323 prev_ps = ps; 332 prev_ps = ps;
324} 333}
325 334
326void 335void
327debug_parse_stack(const char *situation) 336debug_parse_stack(const char *situation)
328{ 337{
329 printf("parse stack %s:", situation); 338 printf("parse stack %s:", situation);
330 for (int i = 1; i <= ps.tos; ++i) 339 for (int i = 1; i <= ps.tos; ++i)
331 printf(" %s %d", psym_name[ps.s_sym[i]], ps.s_ind_level[i]); 340 printf(" %s %d", psym_name[ps.s_sym[i]], ps.s_ind_level[i]);
332 if (ps.tos == 0) 341 if (ps.tos == 0)
333 printf(" empty"); 342 printf(" empty");
334 printf("\n"); 343 printf("\n");
335} 344}

cvs diff -r1.296 -r1.297 src/usr.bin/indent/indent.c (expand / switch to unified diff)

--- src/usr.bin/indent/indent.c 2023/05/20 02:47:35 1.296
+++ src/usr.bin/indent/indent.c 2023/05/20 10:09:02 1.297
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: indent.c,v 1.296 2023/05/20 02:47:35 rillig Exp $ */ 1/* $NetBSD: indent.c,v 1.297 2023/05/20 10:09:02 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) 1976 Board of Trustees of the University of Illinois. 7 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
8 * Copyright (c) 1980, 1993 8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved. 9 * The Regents of the University of California. 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
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
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#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__RCSID("$NetBSD: indent.c,v 1.296 2023/05/20 02:47:35 rillig Exp $"); 41__RCSID("$NetBSD: indent.c,v 1.297 2023/05/20 10:09:02 rillig Exp $");
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <err.h> 44#include <err.h>
45#include <fcntl.h> 45#include <fcntl.h>
46#include <stdarg.h> 46#include <stdarg.h>
47#include <stdio.h> 47#include <stdio.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <string.h> 49#include <string.h>
50#include <unistd.h> 50#include <unistd.h>
51 51
52#include "indent.h" 52#include "indent.h"
53 53
54struct options opt = { 54struct options opt = {
@@ -965,39 +965,41 @@ process_preprocessing(void) @@ -965,39 +965,41 @@ process_preprocessing(void)
965 substring dir; 965 substring dir;
966 dir.s = lab.st + 1; 966 dir.s = lab.st + 1;
967 while (dir.s < end && ch_isblank(*dir.s)) 967 while (dir.s < end && ch_isblank(*dir.s))
968 dir.s++; 968 dir.s++;
969 dir.e = dir.s; 969 dir.e = dir.s;
970 while (dir.e < end && ch_isalpha(*dir.e)) 970 while (dir.e < end && ch_isalpha(*dir.e))
971 dir.e++; 971 dir.e++;
972 972
973 if (substring_starts_with(dir, "if")) { /* also ifdef, ifndef */ 973 if (substring_starts_with(dir, "if")) { /* also ifdef, ifndef */
974 if ((size_t)ifdef_level < array_length(state_stack)) 974 if ((size_t)ifdef_level < array_length(state_stack))
975 state_stack[ifdef_level++] = ps; 975 state_stack[ifdef_level++] = ps;
976 else 976 else
977 diag(1, "#if stack overflow"); 977 diag(1, "#if stack overflow");
 978 ps.line_kind = lk_if;
978 979
979 } else if (substring_starts_with(dir, "el")) { /* else, elif */ 980 } else if (substring_starts_with(dir, "el")) { /* else, elif */
980 if (ifdef_level <= 0) 981 if (ifdef_level <= 0)
981 diag(1, dir.s[2] == 'i' 982 diag(1, dir.s[2] == 'i'
982 ? "Unmatched #elif" : "Unmatched #else"); 983 ? "Unmatched #elif" : "Unmatched #else");
983 else 984 else
984 ps = state_stack[ifdef_level - 1]; 985 ps = state_stack[ifdef_level - 1];
985 986
986 } else if (substring_equals(dir, "endif")) { 987 } else if (substring_equals(dir, "endif")) {
987 if (ifdef_level <= 0) 988 if (ifdef_level <= 0)
988 diag(1, "Unmatched #endif"); 989 diag(1, "Unmatched #endif");
989 else 990 else
990 ifdef_level--; 991 ifdef_level--;
 992 ps.line_kind = lk_endif;
991 993
992 } else { 994 } else {
993 if (!substring_equals(dir, "pragma") && 995 if (!substring_equals(dir, "pragma") &&
994 !substring_equals(dir, "error") && 996 !substring_equals(dir, "error") &&
995 !substring_equals(dir, "line") && 997 !substring_equals(dir, "line") &&
996 !substring_equals(dir, "undef") && 998 !substring_equals(dir, "undef") &&
997 !substring_equals(dir, "define") && 999 !substring_equals(dir, "define") &&
998 !substring_equals(dir, "include")) { 1000 !substring_equals(dir, "include")) {
999 diag(1, "Unrecognized cpp directive \"%.*s\"", 1001 diag(1, "Unrecognized cpp directive \"%.*s\"",
1000 (int)(dir.e - dir.s), dir.s); 1002 (int)(dir.e - dir.s), dir.s);
1001 return; 1003 return;
1002 } 1004 }
1003 } 1005 }

cvs diff -r1.152 -r1.153 src/usr.bin/indent/indent.h (expand / switch to unified diff)

--- src/usr.bin/indent/indent.h 2023/05/20 02:47:35 1.152
+++ src/usr.bin/indent/indent.h 2023/05/20 10:09:02 1.153
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: indent.h,v 1.152 2023/05/20 02:47:35 rillig Exp $ */ 1/* $NetBSD: indent.h,v 1.153 2023/05/20 10:09:02 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * 5 *
6 * Copyright (c) 2001 Jens Schweikhardt 6 * Copyright (c) 2001 Jens Schweikhardt
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -384,26 +384,34 @@ extern struct parser_state { @@ -384,26 +384,34 @@ extern struct parser_state {
384 384
385 bool force_nl; /* whether the next token is forced to go to a 385 bool force_nl; /* whether the next token is forced to go to a
386 * new line; used after 'if (expr)' and in 386 * new line; used after 'if (expr)' and in
387 * similar situations; tokens like '{' may 387 * similar situations; tokens like '{' may
388 * ignore this */ 388 * ignore this */
389 389
390 enum declaration { 390 enum declaration {
391 decl_no, /* no declaration anywhere nearby */ 391 decl_no, /* no declaration anywhere nearby */
392 decl_begin, /* collecting tokens of a declaration */ 392 decl_begin, /* collecting tokens of a declaration */
393 decl_end, /* finished a declaration */ 393 decl_end, /* finished a declaration */
394 } declaration; 394 } declaration;
395 bool blank_line_after_decl; 395 bool blank_line_after_decl;
396 396
 397 enum line_kind {
 398 lk_other,
 399 lk_if, /* #if, #ifdef, #ifndef */
 400 lk_endif, /* #endif */
 401 } line_kind; /* kind of the current line, is reset to
 402 * lk_other at the beginning of each line */
 403 enum line_kind prev_line_kind;
 404
397 /* Comments */ 405 /* Comments */
398 406
399 bool curr_col_1; /* whether the current token started in column 407 bool curr_col_1; /* whether the current token started in column
400 * 1 of the original input */ 408 * 1 of the original input */
401 bool next_col_1; 409 bool next_col_1;
402} ps; 410} ps;
403 411
404 412
405#define array_length(array) (sizeof(array) / sizeof((array)[0])) 413#define array_length(array) (sizeof(array) / sizeof((array)[0]))
406 414
407#ifdef debug 415#ifdef debug
408void debug_printf(const char *, ...) __printflike(1, 2); 416void debug_printf(const char *, ...) __printflike(1, 2);
409void debug_println(const char *, ...) __printflike(1, 2); 417void debug_println(const char *, ...) __printflike(1, 2);
@@ -426,27 +434,26 @@ extern const char *const paren_level_cas @@ -426,27 +434,26 @@ extern const char *const paren_level_cas
426 434
427void register_typename(const char *); 435void register_typename(const char *);
428int compute_code_indent(void); 436int compute_code_indent(void);
429int compute_label_indent(void); 437int compute_label_indent(void);
430int ind_add(int, const char *, size_t); 438int ind_add(int, const char *, size_t);
431 439
432void inp_skip(void); 440void inp_skip(void);
433char inp_next(void); 441char inp_next(void);
434void clear_indent_off_text(void); 442void clear_indent_off_text(void);
435 443
436lexer_symbol lexi(void); 444lexer_symbol lexi(void);
437void diag(int, const char *, ...) __printflike(2, 3); 445void diag(int, const char *, ...) __printflike(2, 3);
438void output_line(void); 446void output_line(void);
439void output_line_ff(void); 
440void inp_read_line(void); 447void inp_read_line(void);
441void parse(parser_symbol); 448void parse(parser_symbol);
442void process_comment(void); 449void process_comment(void);
443void set_option(const char *, const char *); 450void set_option(const char *, const char *);
444void load_profile_files(const char *); 451void load_profile_files(const char *);
445 452
446void *nonnull(void *); 453void *nonnull(void *);
447 454
448void buf_add_char(struct buffer *, char); 455void buf_add_char(struct buffer *, char);
449void buf_add_chars(struct buffer *, const char *, size_t); 456void buf_add_chars(struct buffer *, const char *, size_t);
450 457
451static inline bool 458static inline bool
452ch_isalnum(char ch) 459ch_isalnum(char ch)

cvs diff -r1.178 -r1.179 src/usr.bin/indent/io.c (expand / switch to unified diff)

--- src/usr.bin/indent/io.c 2023/05/18 05:33:27 1.178
+++ src/usr.bin/indent/io.c 2023/05/20 10:09:02 1.179
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: io.c,v 1.178 2023/05/18 05:33:27 rillig Exp $ */ 1/* $NetBSD: io.c,v 1.179 2023/05/20 10:09:02 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
@@ -28,36 +28,38 @@ @@ -28,36 +28,38 @@
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#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__RCSID("$NetBSD: io.c,v 1.178 2023/05/18 05:33:27 rillig Exp $"); 41__RCSID("$NetBSD: io.c,v 1.179 2023/05/20 10:09:02 rillig Exp $");
42 42
43#include <stdio.h> 43#include <stdio.h>
44#include <string.h> 
45 44
46#include "indent.h" 45#include "indent.h"
47 46
48struct buffer inp; 47struct buffer inp;
49static struct buffer indent_off_text; 48static struct buffer indent_off_text; /* text from between 'INDENT OFF' and
50 49 * 'INDENT ON', both inclusive */
 50static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after
 51 * a single '\n', > 1 means there were
 52 * (n - 1) blank lines above */
51static int paren_indent; 53static int paren_indent;
52 54
53 55
54void 56void
55inp_skip(void) 57inp_skip(void)
56{ 58{
57 inp.st++; 59 inp.st++;
58 if ((size_t)(inp.st - inp.mem) >= inp.len) 60 if ((size_t)(inp.st - inp.mem) >= inp.len)
59 inp_read_line(); 61 inp_read_line();
60} 62}
61 63
62char 64char
63inp_next(void) 65inp_next(void)
@@ -82,62 +84,90 @@ inp_read_next_line(FILE *f) @@ -82,62 +84,90 @@ inp_read_next_line(FILE *f)
82 } 84 }
83 had_eof = true; 85 had_eof = true;
84 break; 86 break;
85 } 87 }
86 88
87 if (ch != '\0') 89 if (ch != '\0')
88 buf_add_char(&inp, (char)ch); 90 buf_add_char(&inp, (char)ch);
89 if (ch == '\n') 91 if (ch == '\n')
90 break; 92 break;
91 } 93 }
92} 94}
93 95
94static void 96static void
95output_char(char ch) 97output_newline(void)
96{ 98{
97 fputc(ch, output); 99 fputc('\n', output);
98 debug_vis_range("output_char '", &ch, 1, "'\n"); 100 debug_println("output_newline");
 101 wrote_newlines++;
99} 102}
100 103
101static void 104static void
102output_range(const char *s, size_t len) 105output_range(const char *s, size_t len)
103{ 106{
104 fwrite(s, 1, len, output); 107 fwrite(s, 1, len, output);
105 debug_vis_range("output_range \"", s, len, "\"\n"); 108 debug_vis_range("output_range \"", s, len, "\"\n");
 109 for (size_t i = 0; i < len; i++)
 110 wrote_newlines = s[i] == '\n' ? wrote_newlines + 1 : 0;
106} 111}
107 112
108static int 113static int
109output_indent(int old_ind, int new_ind) 114output_indent(int old_ind, int new_ind)
110{ 115{
111 int ind = old_ind; 116 int ind = old_ind;
112 117
113 if (opt.use_tabs) { 118 if (opt.use_tabs) {
114 int tabsize = opt.tabsize; 119 int tabsize = opt.tabsize;
115 int n = new_ind / tabsize - ind / tabsize; 120 int n = new_ind / tabsize - ind / tabsize;
116 if (n > 0) 121 if (n > 0)
117 ind -= ind % tabsize; 122 ind -= ind % tabsize;
118 for (int i = 0; i < n; i++) { 123 for (int i = 0; i < n; i++) {
119 fputc('\t', output); 124 fputc('\t', output);
120 ind += tabsize; 125 ind += tabsize;
 126 wrote_newlines = 0;
121 } 127 }
122 } 128 }
123 129
124 for (; ind < new_ind; ind++) 130 for (; ind < new_ind; ind++) {
125 fputc(' ', output); 131 fputc(' ', output);
 132 wrote_newlines = 0;
 133 }
126 134
127 debug_println("output_indent %d", ind); 135 debug_println("output_indent %d", ind);
128 return ind; 136 return ind;
129} 137}
130 138
 139static void
 140maybe_output_blank_line(void)
 141{
 142 bool want_blank_line = false;
 143
 144 if (ps.blank_line_after_decl && ps.declaration == decl_no) {
 145 ps.blank_line_after_decl = false;
 146 want_blank_line = true;
 147 }
 148
 149 if (opt.blanklines_around_conditional_compilation) {
 150 if (ps.prev_line_kind != lk_if && ps.line_kind == lk_if)
 151 want_blank_line = true;
 152 if (ps.prev_line_kind == lk_endif && ps.line_kind != lk_endif)
 153 want_blank_line = true;
 154 }
 155
 156 if (want_blank_line && wrote_newlines < 2
 157 && (lab.len > 0 || code.len > 0 || com.len > 0))
 158 output_newline();
 159}
 160
131static int 161static int
132output_line_label(void) 162output_line_label(void)
133{ 163{
134 int ind; 164 int ind;
135 165
136 while (lab.len > 0 && ch_isblank(lab.mem[lab.len - 1])) 166 while (lab.len > 0 && ch_isblank(lab.mem[lab.len - 1]))
137 lab.len--; 167 lab.len--;
138 168
139 ind = output_indent(0, compute_label_indent()); 169 ind = output_indent(0, compute_label_indent());
140 output_range(lab.st, lab.len); 170 output_range(lab.st, lab.len);
141 ind = ind_add(ind, lab.st, lab.len); 171 ind = ind_add(ind, lab.st, lab.len);
142 172
143 ps.is_case_label = false; 173 ps.is_case_label = false;
@@ -180,27 +210,27 @@ output_line_comment(int ind) @@ -180,27 +210,27 @@ output_line_comment(int ind)
180 for (; target_ind < 0; p++) { 210 for (; target_ind < 0; p++) {
181 if (*p == ' ') 211 if (*p == ' ')
182 target_ind++; 212 target_ind++;
183 else if (*p == '\t') 213 else if (*p == '\t')
184 target_ind = next_tab(target_ind); 214 target_ind = next_tab(target_ind);
185 else { 215 else {
186 target_ind = 0; 216 target_ind = 0;
187 break; 217 break;
188 } 218 }
189 } 219 }
190 220
191 /* if comment can't fit on this line, put it on the next line */ 221 /* if comment can't fit on this line, put it on the next line */
192 if (ind > target_ind) { 222 if (ind > target_ind) {
193 output_char('\n'); 223 output_newline();
194 ind = 0; 224 ind = 0;
195 } 225 }
196 226
197 while (com.mem + com.len > p && ch_isspace(com.mem[com.len - 1])) 227 while (com.mem + com.len > p && ch_isspace(com.mem[com.len - 1]))
198 com.len--; 228 com.len--;
199 229
200 (void)output_indent(ind, target_ind); 230 (void)output_indent(ind, target_ind);
201 output_range(p, com.len - (size_t)(p - com.mem)); 231 output_range(p, com.len - (size_t)(p - com.mem));
202 232
203 ps.comment_delta = ps.n_comment_delta; 233 ps.comment_delta = ps.n_comment_delta;
204} 234}
205 235
206/* 236/*
@@ -208,52 +238,48 @@ output_line_comment(int ind) @@ -208,52 +238,48 @@ output_line_comment(int ind)
208 * the label, the code and the comment. 238 * the label, the code and the comment.
209 * 239 *
210 * Comments are written directly, bypassing this function. 240 * Comments are written directly, bypassing this function.
211 */ 241 */
212void 242void
213output_line(void) 243output_line(void)
214{ 244{
215 debug_printf("%s", __func__); 245 debug_printf("%s", __func__);
216 debug_buffers(); 246 debug_buffers();
217 debug_println(""); 247 debug_println("");
218 248
219 ps.is_function_definition = false; 249 ps.is_function_definition = false;
220 250
221 if (ps.blank_line_after_decl && ps.declaration == decl_no) { 251 maybe_output_blank_line();
222 ps.blank_line_after_decl = false; 
223 if (lab.len > 0 || code.len > 0 || com.len > 0) 
224 output_char('\n'); 
225 } 
226 252
227 if (indent_enabled == indent_on) { 253 if (indent_enabled == indent_on) {
228 if (ps.ind_level == 0) 254 if (ps.ind_level == 0)
229 ps.in_stmt_cont = false; /* this is a class A 255 ps.in_stmt_cont = false; /* this is a class A
230 * kludge */ 256 * kludge */
231 257
232 if (opt.blank_line_after_decl && ps.declaration == decl_end 258 if (opt.blank_line_after_decl && ps.declaration == decl_end
233 && ps.tos > 1) { 259 && ps.tos > 1) {
234 ps.declaration = decl_no; 260 ps.declaration = decl_no;
235 ps.blank_line_after_decl = true; 261 ps.blank_line_after_decl = true;
236 } 262 }
237 263
238 int ind = 0; 264 int ind = 0;
239 if (lab.len > 0) 265 if (lab.len > 0)
240 ind = output_line_label(); 266 ind = output_line_label();
241 if (code.len > 0) 267 if (code.len > 0)
242 ind = output_line_code(ind); 268 ind = output_line_code(ind);
243 if (com.len > 0) 269 if (com.len > 0)
244 output_line_comment(ind); 270 output_line_comment(ind);
245 271
246 output_char('\n'); 272 output_newline();
247 } 273 }
248 274
249 if (indent_enabled == indent_last_off_line) { 275 if (indent_enabled == indent_last_off_line) {
250 indent_enabled = indent_on; 276 indent_enabled = indent_on;
251 output_range(indent_off_text.st, indent_off_text.len); 277 output_range(indent_off_text.st, indent_off_text.len);
252 indent_off_text.len = 0; 278 indent_off_text.len = 0;
253 } 279 }
254 280
255 ps.decl_on_line = ps.in_decl; /* for proper comment indentation */ 281 ps.decl_on_line = ps.in_decl; /* for proper comment indentation */
256 ps.in_stmt_cont = ps.in_stmt_or_decl && !ps.in_decl; 282 ps.in_stmt_cont = ps.in_stmt_or_decl && !ps.in_decl;
257 ps.decl_indent_done = false; 283 ps.decl_indent_done = false;
258 if (ps.extra_expr_indent == eei_last) 284 if (ps.extra_expr_indent == eei_last)
259 ps.extra_expr_indent = eei_no; 285 ps.extra_expr_indent = eei_no;
@@ -262,26 +288,28 @@ output_line(void) @@ -262,26 +288,28 @@ output_line(void)
262 code.len = 0; 288 code.len = 0;
263 com.len = 0; 289 com.len = 0;
264 290
265 ps.ind_level = ps.ind_level_follow; 291 ps.ind_level = ps.ind_level_follow;
266 ps.line_start_nparen = ps.nparen; 292 ps.line_start_nparen = ps.nparen;
267 293
268 if (ps.nparen > 0) { 294 if (ps.nparen > 0) {
269 /* TODO: explain what negative indentation means */ 295 /* TODO: explain what negative indentation means */
270 paren_indent = -1 - ps.paren[ps.nparen - 1].indent; 296 paren_indent = -1 - ps.paren[ps.nparen - 1].indent;
271 debug_println("paren_indent is now %d", paren_indent); 297 debug_println("paren_indent is now %d", paren_indent);
272 } 298 }
273 299
274 ps.want_blank = false; 300 ps.want_blank = false;
 301 ps.prev_line_kind = ps.line_kind;
 302 ps.line_kind = lk_other;
275} 303}
276 304
277static int 305static int
278compute_code_indent_lineup(int base_ind) 306compute_code_indent_lineup(int base_ind)
279{ 307{
280 int ind = paren_indent; 308 int ind = paren_indent;
281 int overflow = ind_add(ind, code.st, code.len) - opt.max_line_length; 309 int overflow = ind_add(ind, code.st, code.len) - opt.max_line_length;
282 if (overflow < 0) 310 if (overflow < 0)
283 return ind; 311 return ind;
284 312
285 if (ind_add(base_ind, code.st, code.len) < opt.max_line_length) { 313 if (ind_add(base_ind, code.st, code.len) < opt.max_line_length) {
286 ind -= overflow + 2; 314 ind -= overflow + 2;
287 if (ind > base_ind) 315 if (ind > base_ind)