| @@ -1,421 +1,419 @@ | | | @@ -1,421 +1,419 @@ |
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 |
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 | #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 | |
47 | struct buffer inp; | | 47 | struct buffer inp; |
48 | const char *inp_p; | | 48 | const char *inp_p; |
49 | | | 49 | |
50 | struct output_state out; | | 50 | struct output_state out; |
51 | enum indent_enabled indent_enabled; | | 51 | enum indent_enabled indent_enabled; |
52 | static int out_ind; /* width of the line that is being written */ | | 52 | static int out_ind; /* width of the line that is being written */ |
53 | static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after a | | 53 | static 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 |
56 | static unsigned buffered_blank_lines; | | 56 | * blank lines */ |
| | | 57 | static unsigned buffered_newlines; /* not yet written */ |
57 | static int paren_indent; | | 58 | static int paren_indent; |
58 | | | 59 | |
59 | | | 60 | |
60 | static void | | 61 | static void |
61 | inp_read_next_line(FILE *f) | | 62 | inp_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, ' '); |
70 | buf_add_char(&inp, '\n'); | | 71 | buf_add_char(&inp, '\n'); |
71 | } | | 72 | } |
72 | had_eof = true; | | 73 | had_eof = true; |
73 | break; | | 74 | break; |
74 | } | | 75 | } |
75 | | | 76 | |
76 | if (ch != '\0') | | 77 | if (ch != '\0') |
77 | buf_add_char(&inp, (char)ch); | | 78 | buf_add_char(&inp, (char)ch); |
78 | if (ch == '\n') | | 79 | if (ch == '\n') |
79 | break; | | 80 | break; |
80 | } | | 81 | } |
81 | inp_p = inp.s; | | 82 | inp_p = inp.s; |
82 | } | | 83 | } |
83 | | | 84 | |
84 | void | | 85 | void |
85 | inp_read_line(void) | | 86 | inp_read_line(void) |
86 | { | | 87 | { |
87 | if (indent_enabled == indent_on) | | 88 | if (indent_enabled == indent_on) |
88 | out.indent_off_text.len = 0; | | 89 | out.indent_off_text.len = 0; |
89 | buf_add_chars(&out.indent_off_text, inp.s, inp.len); | | 90 | buf_add_chars(&out.indent_off_text, inp.s, inp.len); |
90 | inp_read_next_line(input); | | 91 | inp_read_next_line(input); |
91 | } | | 92 | } |
92 | | | 93 | |
93 | void | | 94 | void |
94 | inp_skip(void) | | 95 | inp_skip(void) |
95 | { | | 96 | { |
96 | inp_p++; | | 97 | inp_p++; |
97 | if ((size_t)(inp_p - inp.s) >= inp.len) | | 98 | if ((size_t)(inp_p - inp.s) >= inp.len) |
98 | inp_read_line(); | | 99 | inp_read_line(); |
99 | } | | 100 | } |
100 | | | 101 | |
101 | char | | 102 | char |
102 | inp_next(void) | | 103 | inp_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 | |
110 | static void | | 111 | static void |
111 | write_newline(void) | | 112 | buffer_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 | |
118 | static void | | 119 | static void |
119 | write_buffered_blank_lines(void) | | 120 | write_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 | |
127 | static void | | 128 | static void |
128 | write_range(const char *s, size_t len) | | 129 | write_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 | |
138 | static void | | 139 | static void |
139 | write_indent(int new_ind) | | 140 | write_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 | |
164 | static bool | | 165 | static bool |
165 | want_blank_line(void) | | 166 | want_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 | } |
174 | if (opt.blanklines_around_conditional_compilation) { | | 175 | if (opt.blanklines_around_conditional_compilation) { |
175 | if (out.prev_line_kind != lk_if && out.line_kind == lk_if) | | 176 | if (out.prev_line_kind != lk_if && out.line_kind == lk_if) |
176 | return true; | | 177 | return true; |
177 | if (out.prev_line_kind == lk_endif | | 178 | if (out.prev_line_kind == lk_endif |
178 | && out.line_kind != lk_endif) | | 179 | && out.line_kind != lk_endif) |
179 | return true; | | 180 | return true; |
180 | } | | 181 | } |
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 | |
190 | static bool | | 191 | static bool |
191 | is_blank_line_optional(void) | | 192 | is_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 | |
200 | static int | | 201 | static int |
201 | compute_case_label_indent(void) | | 202 | compute_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 | |
210 | int | | 211 | int |
211 | compute_label_indent(void) | | 212 | compute_label_indent(void) |
212 | { | | 213 | { |
213 | if (out.line_kind == lk_case_or_default) | | 214 | if (out.line_kind == lk_case_or_default) |
214 | return compute_case_label_indent(); | | 215 | return compute_case_label_indent(); |
215 | if (lab.s[0] == '#') | | 216 | if (lab.s[0] == '#') |
216 | return 0; | | 217 | return 0; |
217 | return opt.indent_size * (ps.ind_level - 2); | | 218 | return opt.indent_size * (ps.ind_level - 2); |
218 | } | | 219 | } |
219 | | | 220 | |
220 | static void | | 221 | static void |
221 | output_line_label(void) | | 222 | output_line_label(void) |
222 | { | | 223 | { |
223 | write_indent(compute_label_indent()); | | 224 | write_indent(compute_label_indent()); |
224 | write_range(lab.s, lab.len); | | 225 | write_range(lab.s, lab.len); |
225 | } | | 226 | } |
226 | | | 227 | |
227 | static int | | 228 | static int |
228 | compute_code_indent_lineup(int base_ind) | | 229 | compute_code_indent_lineup(int base_ind) |
229 | { | | 230 | { |
230 | int ind = paren_indent; | | 231 | int ind = paren_indent; |
231 | int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; | | 232 | int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; |
232 | if (overflow >= 0 | | 233 | if (overflow >= 0 |
233 | && ind_add(base_ind, code.s, code.len) < opt.max_line_length) { | | 234 | && ind_add(base_ind, code.s, code.len) < opt.max_line_length) { |
234 | ind -= overflow + 2; | | 235 | ind -= overflow + 2; |
235 | if (ind < base_ind) | | 236 | if (ind < base_ind) |
236 | ind = base_ind; | | 237 | ind = base_ind; |
237 | } | | 238 | } |
238 | | | 239 | |
239 | if (ps.extra_expr_indent != eei_no | | 240 | if (ps.extra_expr_indent != eei_no |
240 | && ind == base_ind + opt.indent_size) | | 241 | && ind == base_ind + opt.indent_size) |
241 | ind += opt.continuation_indent; | | 242 | ind += opt.continuation_indent; |
242 | return ind; | | 243 | return ind; |
243 | } | | 244 | } |
244 | | | 245 | |
245 | int | | 246 | int |
246 | compute_code_indent(void) | | 247 | compute_code_indent(void) |
247 | { | | 248 | { |
248 | int base_ind = ps.ind_level * opt.indent_size; | | 249 | int base_ind = ps.ind_level * opt.indent_size; |
249 | | | 250 | |
250 | if (ps.line_start_nparen == 0) { | | 251 | if (ps.line_start_nparen == 0) { |
251 | if (ps.psyms.top >= 1 | | 252 | if (ps.psyms.top >= 1 |
252 | && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum) | | 253 | && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum) |
253 | return base_ind; | | 254 | return base_ind; |
254 | if (ps.in_stmt_cont) | | 255 | if (ps.in_stmt_cont) |
255 | return base_ind + opt.continuation_indent; | | 256 | return base_ind + opt.continuation_indent; |
256 | return base_ind; | | 257 | return base_ind; |
257 | } | | 258 | } |
258 | | | 259 | |
259 | if (opt.lineup_to_parens) { | | 260 | if (opt.lineup_to_parens) { |
260 | if (opt.lineup_to_parens_always) | | 261 | if (opt.lineup_to_parens_always) |
261 | return paren_indent; | | 262 | return paren_indent; |
262 | return compute_code_indent_lineup(base_ind); | | 263 | return compute_code_indent_lineup(base_ind); |
263 | } | | 264 | } |
264 | | | 265 | |
265 | int rel_ind = opt.continuation_indent * ps.line_start_nparen; | | 266 | int rel_ind = opt.continuation_indent * ps.line_start_nparen; |
266 | if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size) | | 267 | if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size) |
267 | rel_ind += opt.continuation_indent; | | 268 | rel_ind += opt.continuation_indent; |
268 | return base_ind + rel_ind; | | 269 | return base_ind + rel_ind; |
269 | } | | 270 | } |
270 | | | 271 | |
271 | static void | | 272 | static void |
272 | output_line_code(void) | | 273 | output_line_code(void) |
273 | { | | 274 | { |
274 | int target_ind = compute_code_indent(); | | 275 | int target_ind = compute_code_indent(); |
275 | for (int i = 0; i < ps.nparen; i++) { | | 276 | for (int i = 0; i < ps.nparen; i++) { |
276 | int paren_ind = ps.paren[i].indent; | | 277 | int paren_ind = ps.paren[i].indent; |
277 | if (paren_ind >= 0) { | | 278 | if (paren_ind >= 0) { |
278 | ps.paren[i].indent = -1 - (paren_ind + target_ind); | | 279 | ps.paren[i].indent = -1 - (paren_ind + target_ind); |
279 | debug_println( | | 280 | debug_println( |
280 | "setting paren_indents[%d] from %d to %d " | | 281 | "setting paren_indents[%d] from %d to %d " |
281 | "for column %d", | | 282 | "for column %d", |
282 | i, paren_ind, ps.paren[i].indent, target_ind + 1); | | 283 | i, paren_ind, ps.paren[i].indent, target_ind + 1); |
283 | } | | 284 | } |
284 | } | | 285 | } |
285 | | | 286 | |
286 | if (lab.len > 0 && target_ind <= out_ind) | | 287 | if (lab.len > 0 && target_ind <= out_ind) |
287 | write_range(" ", 1); | | 288 | write_range(" ", 1); |
288 | write_indent(target_ind); | | 289 | write_indent(target_ind); |
289 | write_range(code.s, code.len); | | 290 | write_range(code.s, code.len); |
290 | } | | 291 | } |
291 | | | 292 | |
292 | static void | | 293 | static void |
293 | output_line_comment(void) | | 294 | output_line_comment(void) |
294 | { | | 295 | { |
295 | int target_ind = ps.com_ind + ps.comment_delta; | | 296 | int target_ind = ps.com_ind + ps.comment_delta; |
296 | const char *p; | | 297 | const char *p; |
297 | | | 298 | |
298 | /* consider original indentation in case this is a box comment */ | | 299 | /* consider original indentation in case this is a box comment */ |
299 | for (p = com.s; *p == '\t'; p++) | | 300 | for (p = com.s; *p == '\t'; p++) |
300 | target_ind += opt.tabsize; | | 301 | target_ind += opt.tabsize; |
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 | |
325 | static void | | 326 | static void |
326 | output_line_indented(void) | | 327 | output_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 | */ |
365 | void | | 368 | void |
366 | output_line(void) | | 369 | output_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(); |
371 | | | 374 | |
372 | if (indent_enabled == indent_on) | | 375 | if (indent_enabled == indent_on) |
373 | output_line_indented(); | | 376 | output_line_indented(); |
374 | else if (indent_enabled == indent_last_off_line) { | | 377 | else if (indent_enabled == indent_last_off_line) { |
375 | indent_enabled = indent_on; | | 378 | indent_enabled = indent_on; |
376 | write_range(out.indent_off_text.s, out.indent_off_text.len); | | 379 | write_range(out.indent_off_text.s, out.indent_off_text.len); |
377 | out.indent_off_text.len = 0; | | 380 | out.indent_off_text.len = 0; |
378 | } | | 381 | } |
379 | | | 382 | |
380 | lab.len = 0; | | 383 | lab.len = 0; |
381 | code.len = 0; | | 384 | code.len = 0; |
382 | com.len = 0; | | 385 | com.len = 0; |
383 | | | 386 | |
384 | ps.line_has_decl = ps.in_decl; | | 387 | ps.line_has_decl = ps.in_decl; |
385 | ps.line_has_func_def = false; | | 388 | ps.line_has_func_def = false; |
386 | ps.in_stmt_cont = ps.in_stmt_or_decl | | 389 | ps.in_stmt_cont = ps.in_stmt_or_decl |
387 | && (!ps.in_decl || ps.in_init) | | 390 | && (!ps.in_decl || ps.in_init) |
388 | && ps.init_level == 0; | | 391 | && ps.init_level == 0; |
389 | ps.decl_indent_done = false; | | 392 | ps.decl_indent_done = false; |
390 | if (ps.extra_expr_indent == eei_last) | | 393 | if (ps.extra_expr_indent == eei_last) |
391 | ps.extra_expr_indent = eei_no; | | 394 | ps.extra_expr_indent = eei_no; |
392 | if (!(ps.psyms.sym[ps.psyms.top] == psym_if_expr_stmt_else | | 395 | if (!(ps.psyms.sym[ps.psyms.top] == psym_if_expr_stmt_else |
393 | && ps.nparen > 0)) | | 396 | && ps.nparen > 0)) |
394 | ps.ind_level = ps.ind_level_follow; | | 397 | ps.ind_level = ps.ind_level_follow; |
395 | ps.line_start_nparen = ps.nparen; | | 398 | ps.line_start_nparen = ps.nparen; |
396 | ps.want_blank = false; | | 399 | ps.want_blank = false; |
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 | |
407 | void | | 410 | void |
408 | output_finish(void) | | 411 | output_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 | } |