Sat Jun 10 11:01:58 2023 UTC ()
indent: distinguish blank lines from newline characters


(rillig)
diff -r1.47 -r1.48 src/usr.bin/indent/debug.c
diff -r1.213 -r1.214 src/usr.bin/indent/io.c

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

--- src/usr.bin/indent/debug.c 2023/06/10 09:31:41 1.47
+++ src/usr.bin/indent/debug.c 2023/06/10 11:01:58 1.48
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: debug.c,v 1.47 2023/06/10 09:31:41 rillig Exp $ */ 1/* $NetBSD: debug.c,v 1.48 2023/06/10 11:01:58 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.47 2023/06/10 09:31:41 rillig Exp $"); 33__RCSID("$NetBSD: debug.c,v 1.48 2023/06/10 11:01:58 rillig Exp $");
34 34
35#include <stdarg.h> 35#include <stdarg.h>
36#include <string.h> 36#include <string.h>
37 37
38#include "indent.h" 38#include "indent.h"
39 39
40#ifdef debug 40#ifdef debug
41 41
42static struct { 42static struct {
43 /*- 43 /*-
44 * false show only the changes to the parser state 44 * false show only the changes to the parser state
45 * true show unchanged parts of the parser state as well 45 * true show unchanged parts of the parser state as well
46 */ 46 */
@@ -134,27 +134,27 @@ const char *const line_kind_name[] = { @@ -134,27 +134,27 @@ const char *const line_kind_name[] = {
134 "case/default", 134 "case/default",
135}; 135};
136 136
137static const char *const extra_expr_indent_name[] = { 137static const char *const extra_expr_indent_name[] = {
138 "no", 138 "no",
139 "maybe", 139 "maybe",
140 "last", 140 "last",
141}; 141};
142 142
143static struct { 143static struct {
144 struct parser_state prev_ps; 144 struct parser_state prev_ps;
145 bool ps_first; 145 bool ps_first;
146 const char *heading; 146 const char *heading;
147 unsigned wrote_newlines; 147 unsigned wrote_newlines;
148} state = { 148} state = {
149 .ps_first = true, 149 .ps_first = true,
150 .wrote_newlines = 1, 150 .wrote_newlines = 1,
151}; 151};
152 152
153void 153void
154debug_printf(const char *fmt, ...) 154debug_printf(const char *fmt, ...)
155{ 155{
156 FILE *f = output == stdout ? stderr : stdout; 156 FILE *f = output == stdout ? stderr : stdout;
157 va_list ap; 157 va_list ap;
158 158
159 if (state.heading != NULL) { 159 if (state.heading != NULL) {
160 fprintf(f, "%s\n", state.heading); 160 fprintf(f, "%s\n", state.heading);
@@ -217,27 +217,27 @@ debug_print_buf(const char *name, const  @@ -217,27 +217,27 @@ debug_print_buf(const char *name, const
217{ 217{
218 if (buf->len > 0) { 218 if (buf->len > 0) {
219 debug_printf(" %s ", name); 219 debug_printf(" %s ", name);
220 debug_vis_range("\"", buf->s, buf->len, "\""); 220 debug_vis_range("\"", buf->s, buf->len, "\"");
221 } 221 }
222} 222}
223 223
224void 224void
225debug_buffers(void) 225debug_buffers(void)
226{ 226{
227 debug_print_buf("label", &lab); 227 debug_print_buf("label", &lab);
228 debug_print_buf("code", &code); 228 debug_print_buf("code", &code);
229 debug_print_buf("comment", &com); 229 debug_print_buf("comment", &com);
230 debug_println(""); 230 debug_blank_line();
231} 231}
232 232
233static void 233static void
234write_ps_bool(const char *name, bool prev, bool curr) 234write_ps_bool(const char *name, bool prev, bool curr)
235{ 235{
236 if (curr != prev) { 236 if (curr != prev) {
237 char diff = " -+x"[(prev ? 1 : 0) + (curr ? 2 : 0)]; 237 char diff = " -+x"[(prev ? 1 : 0) + (curr ? 2 : 0)];
238 debug_println(" [%c] ps.%s", diff, name); 238 debug_println(" [%c] ps.%s", diff, name);
239 } else if (config.full_parser_state || state.ps_first) 239 } else if (config.full_parser_state || state.ps_first)
240 debug_println(" [%c] ps.%s", curr ? 'x' : ' ', name); 240 debug_println(" [%c] ps.%s", curr ? 'x' : ' ', name);
241} 241}
242 242
243static void 243static void
@@ -277,53 +277,53 @@ debug_ps_paren(void) @@ -277,53 +277,53 @@ debug_ps_paren(void)
277{ 277{
278 if (!config.full_parser_state && !ps_paren_has_changed() 278 if (!config.full_parser_state && !ps_paren_has_changed()
279 && !state.ps_first) 279 && !state.ps_first)
280 return; 280 return;
281 281
282 debug_printf(" ps.paren:"); 282 debug_printf(" ps.paren:");
283 for (int i = 0; i < ps.nparen; i++) { 283 for (int i = 0; i < ps.nparen; i++) {
284 debug_printf(" %s%d", 284 debug_printf(" %s%d",
285 paren_level_cast_name[ps.paren[i].cast], 285 paren_level_cast_name[ps.paren[i].cast],
286 ps.paren[i].indent); 286 ps.paren[i].indent);
287 } 287 }
288 if (ps.nparen == 0) 288 if (ps.nparen == 0)
289 debug_printf(" none"); 289 debug_printf(" none");
290 debug_println(""); 290 debug_blank_line();
291} 291}
292 292
293static bool 293static bool
294ps_di_stack_has_changed(void) 294ps_di_stack_has_changed(void)
295{ 295{
296 if (state.prev_ps.decl_level != ps.decl_level) 296 if (state.prev_ps.decl_level != ps.decl_level)
297 return true; 297 return true;
298 for (int i = 0; i < ps.decl_level; i++) 298 for (int i = 0; i < ps.decl_level; i++)
299 if (state.prev_ps.di_stack[i] != ps.di_stack[i]) 299 if (state.prev_ps.di_stack[i] != ps.di_stack[i])
300 return true; 300 return true;
301 return false; 301 return false;
302} 302}
303 303
304static void 304static void
305debug_ps_di_stack(void) 305debug_ps_di_stack(void)
306{ 306{
307 bool changed = ps_di_stack_has_changed(); 307 bool changed = ps_di_stack_has_changed();
308 if (!config.full_parser_state && !changed && !state.ps_first) 308 if (!config.full_parser_state && !changed && !state.ps_first)
309 return; 309 return;
310 310
311 debug_printf(" %s ps.di_stack:", changed ? "->" : " "); 311 debug_printf(" %s ps.di_stack:", changed ? "->" : " ");
312 for (int i = 0; i < ps.decl_level; i++) 312 for (int i = 0; i < ps.decl_level; i++)
313 debug_printf(" %d", ps.di_stack[i]); 313 debug_printf(" %d", ps.di_stack[i]);
314 if (ps.decl_level == 0) 314 if (ps.decl_level == 0)
315 debug_printf(" none"); 315 debug_printf(" none");
316 debug_println(""); 316 debug_blank_line();
317} 317}
318 318
319#define debug_ps_bool(name) \ 319#define debug_ps_bool(name) \
320 write_ps_bool(#name, state.prev_ps.name, ps.name) 320 write_ps_bool(#name, state.prev_ps.name, ps.name)
321#define debug_ps_int(name) \ 321#define debug_ps_int(name) \
322 write_ps_int(#name, state.prev_ps.name, ps.name) 322 write_ps_int(#name, state.prev_ps.name, ps.name)
323#define debug_ps_enum(name, names) \ 323#define debug_ps_enum(name, names) \
324 write_ps_enum(#name, (names)[state.prev_ps.name], (names)[ps.name]) 324 write_ps_enum(#name, (names)[state.prev_ps.name], (names)[ps.name])
325 325
326void 326void
327debug_parser_state(void) 327debug_parser_state(void)
328{ 328{
329 debug_blank_line(); 329 debug_blank_line();
@@ -385,16 +385,16 @@ debug_parser_state(void) @@ -385,16 +385,16 @@ debug_parser_state(void)
385 385
386 state.prev_ps = ps; 386 state.prev_ps = ps;
387 state.ps_first = false; 387 state.ps_first = false;
388} 388}
389 389
390void 390void
391debug_parse_stack(const char *situation) 391debug_parse_stack(const char *situation)
392{ 392{
393 debug_printf("parse stack %s:", situation); 393 debug_printf("parse stack %s:", situation);
394 const struct psym_stack *psyms = &ps.psyms; 394 const struct psym_stack *psyms = &ps.psyms;
395 for (int i = 0; i <= psyms->top; ++i) 395 for (int i = 0; i <= psyms->top; ++i)
396 debug_printf(" %d %s", 396 debug_printf(" %d %s",
397 psyms->ind_level[i], psym_name[psyms->sym[i]]); 397 psyms->ind_level[i], psym_name[psyms->sym[i]]);
398 debug_println(""); 398 debug_blank_line();
399} 399}
400#endif 400#endif

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

--- src/usr.bin/indent/io.c 2023/06/10 08:17:04 1.213
+++ src/usr.bin/indent/io.c 2023/06/10 11:01:58 1.214
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: io.c,v 1.213 2023/06/10 08:17:04 rillig Exp $ */ 1/* $NetBSD: io.c,v 1.214 2023/06/10 11:01:58 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,42 +28,43 @@ @@ -28,42 +28,43 @@
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.213 2023/06/10 08:17:04 rillig Exp $"); 41__RCSID("$NetBSD: io.c,v 1.214 2023/06/10 11:01:58 rillig Exp $");
42 42
43#include <stdio.h> 43#include <stdio.h>
44 44
45#include "indent.h" 45#include "indent.h"
46 46
47struct buffer inp; 47struct buffer inp;
48const char *inp_p; 48const char *inp_p;
49 49
50struct output_state out; 50struct output_state out;
51enum indent_enabled indent_enabled; 51enum indent_enabled indent_enabled;
52static int out_ind; /* width of the line that is being written */ 52static int out_ind; /* width of the line that is being written */
53static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after a 53static unsigned newlines = 2; /* the total of written and buffered newlines;
54 * single '\n', > 1 means there were (n 54 * 0 in the middle of a line, 1 after a single
55 * - 1) blank lines above */ 55 * finished line, anything > 1 are trailing
56static unsigned buffered_blank_lines; 56 * blank lines */
 57static unsigned buffered_newlines; /* not yet written */
57static int paren_indent; 58static int paren_indent;
58 59
59 60
60static void 61static void
61inp_read_next_line(FILE *f) 62inp_read_next_line(FILE *f)
62{ 63{
63 inp.len = 0; 64 inp.len = 0;
64 65
65 for (;;) { 66 for (;;) {
66 int ch = getc(f); 67 int ch = getc(f);
67 if (ch == EOF) { 68 if (ch == EOF) {
68 if (indent_enabled == indent_on) { 69 if (indent_enabled == indent_on) {
69 buf_add_char(&inp, ' '); 70 buf_add_char(&inp, ' ');
@@ -98,76 +99,76 @@ inp_skip(void) @@ -98,76 +99,76 @@ inp_skip(void)
98 inp_read_line(); 99 inp_read_line();
99} 100}
100 101
101char 102char
102inp_next(void) 103inp_next(void)
103{ 104{
104 char ch = inp_p[0]; 105 char ch = inp_p[0];
105 inp_skip(); 106 inp_skip();
106 return ch; 107 return ch;
107} 108}
108 109
109 110
110static void 111static void
111write_newline(void) 112buffer_newline(void)
112{ 113{
113 buffered_blank_lines++; 114 buffered_newlines++;
114 wrote_newlines++; 115 newlines++;
115 out_ind = 0; 116 out_ind = 0;
116} 117}
117 118
118static void 119static void
119write_buffered_blank_lines(void) 120write_buffered_newlines(void)
120{ 121{
121 for (; buffered_blank_lines > 0; buffered_blank_lines--) { 122 for (; buffered_newlines > 0; buffered_newlines--) {
122 fputc('\n', output); 123 fputc('\n', output);
123 debug_println("output_newline"); 124 debug_println("write_newline");
124 } 125 }
125} 126}
126 127
127static void 128static void
128write_range(const char *s, size_t len) 129write_range(const char *s, size_t len)
129{ 130{
130 write_buffered_blank_lines(); 131 write_buffered_newlines();
131 fwrite(s, 1, len, output); 132 fwrite(s, 1, len, output);
132 debug_vis_range("output_range \"", s, len, "\"\n"); 133 debug_vis_range("write_range \"", s, len, "\"\n");
133 for (size_t i = 0; i < len; i++) 134 for (size_t i = 0; i < len; i++)
134 wrote_newlines = s[i] == '\n' ? wrote_newlines + 1 : 0; 135 newlines = s[i] == '\n' ? newlines + 1 : 0;
135 out_ind = ind_add(out_ind, s, len); 136 out_ind = ind_add(out_ind, s, len);
136} 137}
137 138
138static void 139static void
139write_indent(int new_ind) 140write_indent(int new_ind)
140{ 141{
141 write_buffered_blank_lines(); 142 write_buffered_newlines();
142 143
143 int ind = out_ind; 144 int ind = out_ind;
144 145
145 if (opt.use_tabs) { 146 if (opt.use_tabs) {
146 int n = new_ind / opt.tabsize - ind / opt.tabsize; 147 int n = new_ind / opt.tabsize - ind / opt.tabsize;
147 if (n > 0) { 148 if (n > 0) {
148 ind = ind - ind % opt.tabsize + n * opt.tabsize; 149 ind = ind - ind % opt.tabsize + n * opt.tabsize;
149 while (n-- > 0) 150 while (n-- > 0)
150 fputc('\t', output); 151 fputc('\t', output);
151 wrote_newlines = 0; 152 newlines = 0;
152 } 153 }
153 } 154 }
154 155
155 for (; ind < new_ind; ind++) { 156 for (; ind < new_ind; ind++) {
156 fputc(' ', output); 157 fputc(' ', output);
157 wrote_newlines = 0; 158 newlines = 0;
158 } 159 }
159 160
160 debug_println("output_indent %d", ind); 161 debug_println("write_indent %d", ind);
161 out_ind = ind; 162 out_ind = ind;
162} 163}
163 164
164static bool 165static bool
165want_blank_line(void) 166want_blank_line(void)
166{ 167{
167 debug_println("%s: %s -> %s", __func__, 168 debug_println("%s: %s -> %s", __func__,
168 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]); 169 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]);
169 170
170 if (ps.blank_line_after_decl && ps.declaration == decl_no) { 171 if (ps.blank_line_after_decl && ps.declaration == decl_no) {
171 ps.blank_line_after_decl = false; 172 ps.blank_line_after_decl = false;
172 return true; 173 return true;
173 } 174 }
@@ -181,30 +182,30 @@ want_blank_line(void) @@ -181,30 +182,30 @@ want_blank_line(void)
181 if (opt.blanklines_after_procs && out.prev_line_kind == lk_func_end 182 if (opt.blanklines_after_procs && out.prev_line_kind == lk_func_end
182 && out.line_kind != lk_endif) 183 && out.line_kind != lk_endif)
183 return true; 184 return true;
184 if (opt.blanklines_before_block_comments 185 if (opt.blanklines_before_block_comments
185 && out.line_kind == lk_block_comment) 186 && out.line_kind == lk_block_comment)
186 return true; 187 return true;
187 return false; 188 return false;
188} 189}
189 190
190static bool 191static bool
191is_blank_line_optional(void) 192is_blank_line_optional(void)
192{ 193{
193 if (out.prev_line_kind == lk_stmt_head) 194 if (out.prev_line_kind == lk_stmt_head)
194 return wrote_newlines >= 1; 195 return newlines >= 1;
195 if (ps.psyms.top >= 2) 196 if (ps.psyms.top >= 2)
196 return wrote_newlines >= 2; 197 return newlines >= 2;
197 return wrote_newlines >= 3; 198 return newlines >= 3;
198} 199}
199 200
200static int 201static int
201compute_case_label_indent(void) 202compute_case_label_indent(void)
202{ 203{
203 int i = ps.psyms.top; 204 int i = ps.psyms.top;
204 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr) 205 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr)
205 i--; 206 i--;
206 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent; 207 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent;
207 return (int)(case_ind * (float)opt.indent_size); 208 return (int)(case_ind * (float)opt.indent_size);
208} 209}
209 210
210int 211int
@@ -301,70 +302,72 @@ output_line_comment(void) @@ -301,70 +302,72 @@ output_line_comment(void)
301 302
302 for (; target_ind < 0; p++) { 303 for (; target_ind < 0; p++) {
303 if (*p == ' ') 304 if (*p == ' ')
304 target_ind++; 305 target_ind++;
305 else if (*p == '\t') 306 else if (*p == '\t')
306 target_ind = next_tab(target_ind); 307 target_ind = next_tab(target_ind);
307 else { 308 else {
308 target_ind = 0; 309 target_ind = 0;
309 break; 310 break;
310 } 311 }
311 } 312 }
312 313
313 if (out_ind > target_ind) 314 if (out_ind > target_ind)
314 write_newline(); 315 buffer_newline();
315 316
316 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1])) 317 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1]))
317 com.len--; 318 com.len--;
318 319
319 write_indent(target_ind); 320 write_indent(target_ind);
320 write_range(p, com.len - (size_t)(p - com.s)); 321 write_range(p, com.len - (size_t)(p - com.s));
321 322
322 ps.comment_delta = ps.n_comment_delta; 323 ps.comment_delta = ps.n_comment_delta;
323} 324}
324 325
325static void 326static void
326output_line_indented(void) 327output_line_indented(void)
327{ 328{
328 if (lab.len == 0 && code.len == 0 && com.len == 0) 329 if (lab.len == 0 && code.len == 0 && com.len == 0)
329 out.line_kind = lk_blank; 330 out.line_kind = lk_blank;
330 331
331 if (want_blank_line() && wrote_newlines < 2 332 if (want_blank_line() && newlines < 2
332 && out.line_kind != lk_blank) 333 && out.line_kind != lk_blank)
333 write_newline(); 334 buffer_newline();
334 335
335 /* This kludge aligns function definitions correctly. */ 336 /* This kludge aligns function definitions correctly. */
336 if (ps.ind_level == 0) 337 if (ps.ind_level == 0)
337 ps.in_stmt_cont = false; 338 ps.in_stmt_cont = false;
338 339
339 if (opt.blank_line_after_decl && ps.declaration == decl_end 340 if (opt.blank_line_after_decl && ps.declaration == decl_end
340 && ps.psyms.top > 1) { 341 && ps.psyms.top > 1) {
341 ps.declaration = decl_no; 342 ps.declaration = decl_no;
342 ps.blank_line_after_decl = true; 343 ps.blank_line_after_decl = true;
343 } 344 }
344 345
345 if (opt.swallow_optional_blanklines 346 if (opt.swallow_optional_blanklines
346 && out.line_kind == lk_blank 347 && out.line_kind == lk_blank
347 && is_blank_line_optional()) 348 && is_blank_line_optional())
348 return; 349 return;
349 350
350 if (lab.len > 0) 351 if (lab.len > 0)
351 output_line_label(); 352 output_line_label();
352 if (code.len > 0) 353 if (code.len > 0)
353 output_line_code(); 354 output_line_code();
354 if (com.len > 0) 355 if (com.len > 0)
355 output_line_comment(); 356 output_line_comment();
 357 buffer_newline();
 358 if (out.line_kind != lk_blank)
 359 write_buffered_newlines();
356 360
357 write_newline(); 
358 out.prev_line_kind = out.line_kind; 361 out.prev_line_kind = out.line_kind;
359} 362}
360 363
361/* 364/*
362 * Write a line of formatted source to the output file. The line consists of 365 * Write a line of formatted source to the output file. The line consists of
363 * the label, the code and the comment. 366 * the label, the code and the comment.
364 */ 367 */
365void 368void
366output_line(void) 369output_line(void)
367{ 370{
368 debug_blank_line(); 371 debug_blank_line();
369 debug_printf("%s", __func__); 372 debug_printf("%s", __func__);
370 debug_buffers(); 373 debug_buffers();
@@ -397,25 +400,20 @@ output_line(void) @@ -397,25 +400,20 @@ output_line(void)
397 400
398 if (ps.nparen > 0) { 401 if (ps.nparen > 0) {
399 /* TODO: explain what negative indentation means */ 402 /* TODO: explain what negative indentation means */
400 paren_indent = -1 - ps.paren[ps.nparen - 1].indent; 403 paren_indent = -1 - ps.paren[ps.nparen - 1].indent;
401 debug_println("paren_indent is now %d", paren_indent); 404 debug_println("paren_indent is now %d", paren_indent);
402 } 405 }
403 406
404 out.line_kind = lk_other; 407 out.line_kind = lk_other;
405} 408}
406 409
407void 410void
408output_finish(void) 411output_finish(void)
409{ 412{
410 if (lab.len > 0 || code.len > 0 || com.len > 0) 413 output_line();
411 output_line(); 414 if (indent_enabled != indent_on) {
412 if (indent_enabled == indent_on) { 
413 if (buffered_blank_lines > 1) 
414 buffered_blank_lines = 1; 
415 write_buffered_blank_lines(); 
416 } else { 
417 indent_enabled = indent_last_off_line; 415 indent_enabled = indent_last_off_line;
418 output_line(); 416 output_line();
419 } 417 }
420 fflush(output); 418 fflush(output);
421} 419}