Sat Jun 10 21:36:38 2023 UTC ()
indent: rename misleading variable

The name started with 'line_start', but the value is not always the
value from the beginning of the line.

No functional change.


(rillig)
diff -r1.52 -r1.53 src/usr.bin/indent/debug.c
diff -r1.356 -r1.357 src/usr.bin/indent/indent.c
diff -r1.187 -r1.188 src/usr.bin/indent/indent.h
diff -r1.216 -r1.217 src/usr.bin/indent/io.c

cvs diff -r1.52 -r1.53 src/usr.bin/indent/debug.c (switch to unified diff)

--- src/usr.bin/indent/debug.c 2023/06/10 20:37:12 1.52
+++ src/usr.bin/indent/debug.c 2023/06/10 21:36:38 1.53
@@ -1,399 +1,399 @@ @@ -1,399 +1,399 @@
1/* $NetBSD: debug.c,v 1.52 2023/06/10 20:37:12 rillig Exp $ */ 1/* $NetBSD: debug.c,v 1.53 2023/06/10 21:36:38 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
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.52 2023/06/10 20:37:12 rillig Exp $"); 33__RCSID("$NetBSD: debug.c,v 1.53 2023/06/10 21:36:38 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 */
47 bool full_parser_state; 47 bool full_parser_state;
48} config = { 48} config = {
49 .full_parser_state = false, 49 .full_parser_state = false,
50}; 50};
51 51
52const char *const lsym_name[] = { 52const char *const lsym_name[] = {
53 "eof", 53 "eof",
54 "preprocessing", 54 "preprocessing",
55 "newline", 55 "newline",
56 "comment", 56 "comment",
57 "lparen", 57 "lparen",
58 "rparen", 58 "rparen",
59 "lbracket", 59 "lbracket",
60 "rbracket", 60 "rbracket",
61 "lbrace", 61 "lbrace",
62 "rbrace", 62 "rbrace",
63 "period", 63 "period",
64 "unary_op", 64 "unary_op",
65 "sizeof", 65 "sizeof",
66 "offsetof", 66 "offsetof",
67 "postfix_op", 67 "postfix_op",
68 "binary_op", 68 "binary_op",
69 "question", 69 "question",
70 "question_colon", 70 "question_colon",
71 "comma", 71 "comma",
72 "typedef", 72 "typedef",
73 "modifier", 73 "modifier",
74 "tag", 74 "tag",
75 "type_outside_parentheses", 75 "type_outside_parentheses",
76 "type_in_parentheses", 76 "type_in_parentheses",
77 "word", 77 "word",
78 "funcname", 78 "funcname",
79 "label_colon", 79 "label_colon",
80 "other_colon", 80 "other_colon",
81 "semicolon", 81 "semicolon",
82 "case", 82 "case",
83 "default", 83 "default",
84 "do", 84 "do",
85 "else", 85 "else",
86 "for", 86 "for",
87 "if", 87 "if",
88 "switch", 88 "switch",
89 "while", 89 "while",
90 "return", 90 "return",
91}; 91};
92 92
93const char *const psym_name[] = { 93const char *const psym_name[] = {
94 "-", 94 "-",
95 "{block", 95 "{block",
96 "{struct", 96 "{struct",
97 "{union", 97 "{union",
98 "{enum", 98 "{enum",
99 "}", 99 "}",
100 "decl", 100 "decl",
101 "stmt", 101 "stmt",
102 "stmt_list", 102 "stmt_list",
103 "for_exprs", 103 "for_exprs",
104 "if_expr", 104 "if_expr",
105 "if_expr_stmt", 105 "if_expr_stmt",
106 "if_expr_stmt_else", 106 "if_expr_stmt_else",
107 "else", 107 "else",
108 "switch_expr", 108 "switch_expr",
109 "do", 109 "do",
110 "do_stmt", 110 "do_stmt",
111 "while_expr", 111 "while_expr",
112}; 112};
113 113
114static const char *const declaration_name[] = { 114static const char *const declaration_name[] = {
115 "no", 115 "no",
116 "begin", 116 "begin",
117 "end", 117 "end",
118}; 118};
119 119
120const char *const paren_level_cast_name[] = { 120const char *const paren_level_cast_name[] = {
121 "(unknown cast)", 121 "(unknown cast)",
122 "(maybe cast)", 122 "(maybe cast)",
123 "(no cast)", 123 "(no cast)",
124}; 124};
125 125
126const char *const line_kind_name[] = { 126const char *const line_kind_name[] = {
127 "other", 127 "other",
128 "blank", 128 "blank",
129 "#if", 129 "#if",
130 "#endif", 130 "#endif",
131 "stmt head", 131 "stmt head",
132 "}", 132 "}",
133 "block comment", 133 "block comment",
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);
161 state.heading = NULL; 161 state.heading = NULL;
162 } 162 }
163 va_start(ap, fmt); 163 va_start(ap, fmt);
164 vfprintf(f, fmt, ap); 164 vfprintf(f, fmt, ap);
165 va_end(ap); 165 va_end(ap);
166 state.wrote_newlines = 0; 166 state.wrote_newlines = 0;
167} 167}
168 168
169void 169void
170debug_println(const char *fmt, ...) 170debug_println(const char *fmt, ...)
171{ 171{
172 FILE *f = output == stdout ? stderr : stdout; 172 FILE *f = output == stdout ? stderr : stdout;
173 va_list ap; 173 va_list ap;
174 174
175 if (state.heading != NULL) { 175 if (state.heading != NULL) {
176 fprintf(f, "%s\n", state.heading); 176 fprintf(f, "%s\n", state.heading);
177 state.heading = NULL; 177 state.heading = NULL;
178 state.wrote_newlines = 1; 178 state.wrote_newlines = 1;
179 } 179 }
180 va_start(ap, fmt); 180 va_start(ap, fmt);
181 vfprintf(f, fmt, ap); 181 vfprintf(f, fmt, ap);
182 va_end(ap); 182 va_end(ap);
183 fprintf(f, "\n"); 183 fprintf(f, "\n");
184 state.wrote_newlines = fmt[0] == '\0' ? state.wrote_newlines + 1 : 1; 184 state.wrote_newlines = fmt[0] == '\0' ? state.wrote_newlines + 1 : 1;
185} 185}
186 186
187void 187void
188debug_blank_line(void) 188debug_blank_line(void)
189{ 189{
190 while (state.wrote_newlines < 2) 190 while (state.wrote_newlines < 2)
191 debug_println(""); 191 debug_println("");
192} 192}
193 193
194void 194void
195debug_vis_range(const char *prefix, const char *s, size_t len, 195debug_vis_range(const char *prefix, const char *s, size_t len,
196 const char *suffix) 196 const char *suffix)
197{ 197{
198 debug_printf("%s", prefix); 198 debug_printf("%s", prefix);
199 for (size_t i = 0; i < len; i++) { 199 for (size_t i = 0; i < len; i++) {
200 const char *p = s + i; 200 const char *p = s + i;
201 if (*p == '\\' || *p == '"') 201 if (*p == '\\' || *p == '"')
202 debug_printf("\\%c", *p); 202 debug_printf("\\%c", *p);
203 else if (isprint((unsigned char)*p)) 203 else if (isprint((unsigned char)*p))
204 debug_printf("%c", *p); 204 debug_printf("%c", *p);
205 else if (*p == '\n') 205 else if (*p == '\n')
206 debug_printf("\\n"); 206 debug_printf("\\n");
207 else if (*p == '\t') 207 else if (*p == '\t')
208 debug_printf("\\t"); 208 debug_printf("\\t");
209 else 209 else
210 debug_printf("\\x%02x", (unsigned char)*p); 210 debug_printf("\\x%02x", (unsigned char)*p);
211 } 211 }
212 debug_printf("%s", suffix); 212 debug_printf("%s", suffix);
213} 213}
214 214
215void 215void
216debug_print_buf(const char *name, const struct buffer *buf) 216debug_print_buf(const char *name, const struct buffer *buf)
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_blank_line(); 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 (!state.ps_first && curr != prev) { 236 if (!state.ps_first && 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
244write_ps_int(const char *name, int prev, int curr) 244write_ps_int(const char *name, int prev, int curr)
245{ 245{
246 if (!state.ps_first && curr != prev) 246 if (!state.ps_first && curr != prev)
247 debug_println(" %3d -> %3d ps.%s", prev, curr, name); 247 debug_println(" %3d -> %3d ps.%s", prev, curr, name);
248 else if (config.full_parser_state || state.ps_first) 248 else if (config.full_parser_state || state.ps_first)
249 debug_println(" %3d ps.%s", curr, name); 249 debug_println(" %3d ps.%s", curr, name);
250} 250}
251 251
252static void 252static void
253write_ps_enum(const char *name, const char *prev, const char *curr) 253write_ps_enum(const char *name, const char *prev, const char *curr)
254{ 254{
255 if (!state.ps_first && strcmp(prev, curr) != 0) 255 if (!state.ps_first && strcmp(prev, curr) != 0)
256 debug_println(" %3s -> %3s ps.%s", prev, curr, name); 256 debug_println(" %3s -> %3s ps.%s", prev, curr, name);
257 else if (config.full_parser_state || state.ps_first) 257 else if (config.full_parser_state || state.ps_first)
258 debug_println(" %10s ps.%s", curr, name); 258 debug_println(" %10s ps.%s", curr, name);
259} 259}
260 260
261static bool 261static bool
262ps_paren_has_changed(void) 262ps_paren_has_changed(void)
263{ 263{
264 if (state.prev_ps.nparen != ps.nparen) 264 if (state.prev_ps.nparen != ps.nparen)
265 return true; 265 return true;
266 266
267 const struct paren_level *prev = state.prev_ps.paren, *curr = ps.paren; 267 const struct paren_level *prev = state.prev_ps.paren, *curr = ps.paren;
268 for (int i = 0; i < ps.nparen; i++) 268 for (int i = 0; i < ps.nparen; i++)
269 if (curr[i].indent != prev[i].indent 269 if (curr[i].indent != prev[i].indent
270 || curr[i].cast != prev[i].cast) 270 || curr[i].cast != prev[i].cast)
271 return true; 271 return true;
272 return false; 272 return false;
273} 273}
274 274
275static void 275static void
276debug_ps_paren(void) 276debug_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_println("");
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_println("");
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();
330 330
331 state.heading = "token classification"; 331 state.heading = "token classification";
332 debug_ps_enum(prev_lsym, lsym_name); 332 debug_ps_enum(prev_lsym, lsym_name);
333 debug_ps_bool(in_stmt_or_decl); 333 debug_ps_bool(in_stmt_or_decl);
334 debug_ps_bool(in_decl); 334 debug_ps_bool(in_decl);
335 debug_ps_bool(in_var_decl); 335 debug_ps_bool(in_var_decl);
336 debug_ps_bool(in_init); 336 debug_ps_bool(in_init);
337 debug_ps_int(init_level); 337 debug_ps_int(init_level);
338 debug_ps_bool(line_has_func_def); 338 debug_ps_bool(line_has_func_def);
339 debug_ps_bool(in_func_def_params); 339 debug_ps_bool(in_func_def_params);
340 debug_ps_bool(line_has_decl); 340 debug_ps_bool(line_has_decl);
341 debug_ps_enum(lbrace_kind, psym_name); 341 debug_ps_enum(lbrace_kind, psym_name);
342 debug_ps_enum(spaced_expr_psym, psym_name); 342 debug_ps_enum(spaced_expr_psym, psym_name);
343 debug_ps_bool(seen_case); 343 debug_ps_bool(seen_case);
344 debug_ps_bool(prev_paren_was_cast); 344 debug_ps_bool(prev_paren_was_cast);
345 debug_ps_int(quest_level); 345 debug_ps_int(quest_level);
346 346
347 state.heading = "indentation of statements and declarations"; 347 state.heading = "indentation of statements and declarations";
348 debug_ps_int(ind_level); 348 debug_ps_int(ind_level);
349 debug_ps_int(ind_level_follow); 349 debug_ps_int(ind_level_follow);
350 debug_ps_bool(in_stmt_cont); 350 debug_ps_bool(in_stmt_cont);
351 debug_ps_int(decl_level); 351 debug_ps_int(decl_level);
352 debug_ps_di_stack(); 352 debug_ps_di_stack();
353 debug_ps_bool(decl_indent_done); 353 debug_ps_bool(decl_indent_done);
354 debug_ps_int(decl_ind); 354 debug_ps_int(decl_ind);
355 debug_ps_bool(tabs_to_var); 355 debug_ps_bool(tabs_to_var);
356 debug_ps_enum(extra_expr_indent, extra_expr_indent_name); 356 debug_ps_enum(extra_expr_indent, extra_expr_indent_name);
357 357
358 // The parser symbol stack is printed in debug_psyms_stack instead. 358 // The parser symbol stack is printed in debug_psyms_stack instead.
359 359
360 state.heading = "spacing inside a statement or declaration"; 360 state.heading = "spacing inside a statement or declaration";
361 debug_ps_bool(next_unary); 361 debug_ps_bool(next_unary);
362 debug_ps_bool(want_blank); 362 debug_ps_bool(want_blank);
363 debug_ps_int(line_start_nparen); 363 debug_ps_int(ind_paren_level);
364 debug_ps_int(nparen); 364 debug_ps_int(nparen);
365 debug_ps_paren(); 365 debug_ps_paren();
366 366
367 state.heading = "horizontal spacing for comments"; 367 state.heading = "horizontal spacing for comments";
368 debug_ps_int(comment_delta); 368 debug_ps_int(comment_delta);
369 debug_ps_int(n_comment_delta); 369 debug_ps_int(n_comment_delta);
370 debug_ps_int(com_ind); 370 debug_ps_int(com_ind);
371 371
372 state.heading = "vertical spacing"; 372 state.heading = "vertical spacing";
373 debug_ps_bool(break_after_comma); 373 debug_ps_bool(break_after_comma);
374 debug_ps_bool(force_nl); 374 debug_ps_bool(force_nl);
375 debug_ps_enum(declaration, declaration_name); 375 debug_ps_enum(declaration, declaration_name);
376 debug_ps_bool(blank_line_after_decl); 376 debug_ps_bool(blank_line_after_decl);
377 377
378 state.heading = "comments"; 378 state.heading = "comments";
379 debug_ps_bool(curr_col_1); 379 debug_ps_bool(curr_col_1);
380 debug_ps_bool(next_col_1); 380 debug_ps_bool(next_col_1);
381 381
382 state.heading = NULL; 382 state.heading = NULL;
383 debug_blank_line(); 383 debug_blank_line();
384 384
385 state.prev_ps = ps; 385 state.prev_ps = ps;
386 state.ps_first = false; 386 state.ps_first = false;
387} 387}
388 388
389void 389void
390debug_psyms_stack(const char *situation) 390debug_psyms_stack(const char *situation)
391{ 391{
392 debug_printf("parse stack %s:", situation); 392 debug_printf("parse stack %s:", situation);
393 const struct psym_stack *psyms = &ps.psyms; 393 const struct psym_stack *psyms = &ps.psyms;
394 for (int i = 0; i <= psyms->top; ++i) 394 for (int i = 0; i <= psyms->top; ++i)
395 debug_printf(" %d %s", 395 debug_printf(" %d %s",
396 psyms->ind_level[i], psym_name[psyms->sym[i]]); 396 psyms->ind_level[i], psym_name[psyms->sym[i]]);
397 debug_println(""); 397 debug_println("");
398} 398}
399#endif 399#endif

cvs diff -r1.356 -r1.357 src/usr.bin/indent/indent.c (switch to unified diff)

--- src/usr.bin/indent/indent.c 2023/06/10 20:37:12 1.356
+++ src/usr.bin/indent/indent.c 2023/06/10 21:36:38 1.357
@@ -1,1080 +1,1080 @@ @@ -1,1080 +1,1080 @@
1/* $NetBSD: indent.c,v 1.356 2023/06/10 20:37:12 rillig Exp $ */ 1/* $NetBSD: indent.c,v 1.357 2023/06/10 21:36:38 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
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: indent.c,v 1.356 2023/06/10 20:37:12 rillig Exp $"); 41__RCSID("$NetBSD: indent.c,v 1.357 2023/06/10 21:36:38 rillig Exp $");
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <err.h> 44#include <err.h>
45#include <stdarg.h> 45#include <stdarg.h>
46#include <stdio.h> 46#include <stdio.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "indent.h" 50#include "indent.h"
51 51
52struct options opt = { 52struct options opt = {
53 .brace_same_line = true, 53 .brace_same_line = true,
54 .comment_delimiter_on_blank_line = true, 54 .comment_delimiter_on_blank_line = true,
55 .cuddle_else = true, 55 .cuddle_else = true,
56 .comment_column = 33, 56 .comment_column = 33,
57 .decl_indent = 16, 57 .decl_indent = 16,
58 .else_if_in_same_line = true, 58 .else_if_in_same_line = true,
59 .function_brace_split = true, 59 .function_brace_split = true,
60 .format_col1_comments = true, 60 .format_col1_comments = true,
61 .format_block_comments = true, 61 .format_block_comments = true,
62 .indent_parameters = true, 62 .indent_parameters = true,
63 .indent_size = 8, 63 .indent_size = 8,
64 .local_decl_indent = -1, 64 .local_decl_indent = -1,
65 .lineup_to_parens = true, 65 .lineup_to_parens = true,
66 .procnames_start_line = true, 66 .procnames_start_line = true,
67 .star_comment_cont = true, 67 .star_comment_cont = true,
68 .tabsize = 8, 68 .tabsize = 8,
69 .max_line_length = 78, 69 .max_line_length = 78,
70 .use_tabs = true, 70 .use_tabs = true,
71}; 71};
72 72
73struct parser_state ps; 73struct parser_state ps;
74 74
75struct buffer token; 75struct buffer token;
76 76
77struct buffer lab; 77struct buffer lab;
78struct buffer code; 78struct buffer code;
79struct buffer com; 79struct buffer com;
80 80
81bool found_err; 81bool found_err;
82bool had_eof; 82bool had_eof;
83int line_no = 1; 83int line_no = 1;
84 84
85static int ifdef_level; 85static int ifdef_level;
86static struct parser_state state_stack[5]; 86static struct parser_state state_stack[5];
87 87
88FILE *input; 88FILE *input;
89FILE *output; 89FILE *output;
90 90
91static const char *in_name = "Standard Input"; 91static const char *in_name = "Standard Input";
92static char backup_name[PATH_MAX]; 92static char backup_name[PATH_MAX];
93static const char *backup_suffix = ".BAK"; 93static const char *backup_suffix = ".BAK";
94 94
95 95
96void * 96void *
97nonnull(void *p) 97nonnull(void *p)
98{ 98{
99 if (p == NULL) 99 if (p == NULL)
100 err(EXIT_FAILURE, NULL); 100 err(EXIT_FAILURE, NULL);
101 return p; 101 return p;
102} 102}
103 103
104static void 104static void
105buf_expand(struct buffer *buf, size_t add_size) 105buf_expand(struct buffer *buf, size_t add_size)
106{ 106{
107 buf->cap = buf->cap + add_size + 400; 107 buf->cap = buf->cap + add_size + 400;
108 buf->s = nonnull(realloc(buf->s, buf->cap)); 108 buf->s = nonnull(realloc(buf->s, buf->cap));
109} 109}
110 110
111#ifdef debug 111#ifdef debug
112void 112void
113buf_terminate(struct buffer *buf) 113buf_terminate(struct buffer *buf)
114{ 114{
115 if (buf->len == buf->cap) 115 if (buf->len == buf->cap)
116 buf_expand(buf, 1); 116 buf_expand(buf, 1);
117 buf->s[buf->len] = '\0'; 117 buf->s[buf->len] = '\0';
118} 118}
119#endif 119#endif
120 120
121void 121void
122buf_add_char(struct buffer *buf, char ch) 122buf_add_char(struct buffer *buf, char ch)
123{ 123{
124 if (buf->len == buf->cap) 124 if (buf->len == buf->cap)
125 buf_expand(buf, 1); 125 buf_expand(buf, 1);
126 buf->s[buf->len++] = ch; 126 buf->s[buf->len++] = ch;
127 buf_terminate(buf); 127 buf_terminate(buf);
128} 128}
129 129
130void 130void
131buf_add_chars(struct buffer *buf, const char *s, size_t len) 131buf_add_chars(struct buffer *buf, const char *s, size_t len)
132{ 132{
133 if (len == 0) 133 if (len == 0)
134 return; 134 return;
135 if (len > buf->cap - buf->len) 135 if (len > buf->cap - buf->len)
136 buf_expand(buf, len); 136 buf_expand(buf, len);
137 memcpy(buf->s + buf->len, s, len); 137 memcpy(buf->s + buf->len, s, len);
138 buf->len += len; 138 buf->len += len;
139 buf_terminate(buf); 139 buf_terminate(buf);
140} 140}
141 141
142static void 142static void
143buf_add_buf(struct buffer *buf, const struct buffer *add) 143buf_add_buf(struct buffer *buf, const struct buffer *add)
144{ 144{
145 buf_add_chars(buf, add->s, add->len); 145 buf_add_chars(buf, add->s, add->len);
146} 146}
147 147
148void 148void
149diag(int level, const char *msg, ...) 149diag(int level, const char *msg, ...)
150{ 150{
151 va_list ap; 151 va_list ap;
152 152
153 if (level != 0) 153 if (level != 0)
154 found_err = true; 154 found_err = true;
155 155
156 va_start(ap, msg); 156 va_start(ap, msg);
157 fprintf(stderr, "%s: %s:%d: ", 157 fprintf(stderr, "%s: %s:%d: ",
158 level == 0 ? "warning" : "error", in_name, line_no); 158 level == 0 ? "warning" : "error", in_name, line_no);
159 vfprintf(stderr, msg, ap); 159 vfprintf(stderr, msg, ap);
160 fprintf(stderr, "\n"); 160 fprintf(stderr, "\n");
161 va_end(ap); 161 va_end(ap);
162} 162}
163 163
164/* 164/*
165 * Compute the indentation from starting at 'ind' and adding the text starting 165 * Compute the indentation from starting at 'ind' and adding the text starting
166 * at 's'. 166 * at 's'.
167 */ 167 */
168int 168int
169ind_add(int ind, const char *s, size_t len) 169ind_add(int ind, const char *s, size_t len)
170{ 170{
171 for (const char *p = s; len > 0; p++, len--) { 171 for (const char *p = s; len > 0; p++, len--) {
172 if (*p == '\n') 172 if (*p == '\n')
173 ind = 0; 173 ind = 0;
174 else if (*p == '\t') 174 else if (*p == '\t')
175 ind = next_tab(ind); 175 ind = next_tab(ind);
176 else if (*p == '\b') 176 else if (*p == '\b')
177 --ind; 177 --ind;
178 else 178 else
179 ++ind; 179 ++ind;
180 } 180 }
181 return ind; 181 return ind;
182} 182}
183 183
184static void 184static void
185init_globals(void) 185init_globals(void)
186{ 186{
187 ps.psyms.sym[0] = psym_stmt_list; 187 ps.psyms.sym[0] = psym_stmt_list;
188 ps.prev_lsym = lsym_semicolon; 188 ps.prev_lsym = lsym_semicolon;
189 ps.next_col_1 = true; 189 ps.next_col_1 = true;
190 ps.lbrace_kind = psym_lbrace_block; 190 ps.lbrace_kind = psym_lbrace_block;
191 191
192 const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX"); 192 const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX");
193 if (suffix != NULL) 193 if (suffix != NULL)
194 backup_suffix = suffix; 194 backup_suffix = suffix;
195} 195}
196 196
197static void 197static void
198load_profiles(int argc, char **argv) 198load_profiles(int argc, char **argv)
199{ 199{
200 const char *profile_name = NULL; 200 const char *profile_name = NULL;
201 201
202 for (int i = 1; i < argc; ++i) { 202 for (int i = 1; i < argc; ++i) {
203 const char *arg = argv[i]; 203 const char *arg = argv[i];
204 204
205 if (strcmp(arg, "-npro") == 0) 205 if (strcmp(arg, "-npro") == 0)
206 return; 206 return;
207 if (arg[0] == '-' && arg[1] == 'P' && arg[2] != '\0') 207 if (arg[0] == '-' && arg[1] == 'P' && arg[2] != '\0')
208 profile_name = arg + 2; 208 profile_name = arg + 2;
209 } 209 }
210 210
211 load_profile_files(profile_name); 211 load_profile_files(profile_name);
212} 212}
213 213
214/* 214/*
215 * Copy the input file to the backup file, then make the backup file the input 215 * Copy the input file to the backup file, then make the backup file the input
216 * and the original input file the output. 216 * and the original input file the output.
217 */ 217 */
218static void 218static void
219copy_to_bak_file(void) 219copy_to_bak_file(void)
220{ 220{
221 size_t n; 221 size_t n;
222 char buff[BUFSIZ]; 222 char buff[BUFSIZ];
223 223
224 const char *last_slash = strrchr(in_name, '/'); 224 const char *last_slash = strrchr(in_name, '/');
225 const char *base = last_slash != NULL ? last_slash + 1 : in_name; 225 const char *base = last_slash != NULL ? last_slash + 1 : in_name;
226 snprintf(backup_name, sizeof(backup_name), "%s%s", base, backup_suffix); 226 snprintf(backup_name, sizeof(backup_name), "%s%s", base, backup_suffix);
227 227
228 /* copy the input file to the backup file */ 228 /* copy the input file to the backup file */
229 FILE *bak = fopen(backup_name, "w"); 229 FILE *bak = fopen(backup_name, "w");
230 if (bak == NULL) 230 if (bak == NULL)
231 err(1, "%s", backup_name); 231 err(1, "%s", backup_name);
232 232
233 while ((n = fread(buff, 1, sizeof(buff), input)) > 0) 233 while ((n = fread(buff, 1, sizeof(buff), input)) > 0)
234 if (fwrite(buff, 1, n, bak) != n) 234 if (fwrite(buff, 1, n, bak) != n)
235 err(1, "%s", backup_name); 235 err(1, "%s", backup_name);
236 if (fclose(input) != 0) 236 if (fclose(input) != 0)
237 err(1, "%s", in_name); 237 err(1, "%s", in_name);
238 if (fclose(bak) != 0) 238 if (fclose(bak) != 0)
239 err(1, "%s", backup_name); 239 err(1, "%s", backup_name);
240 240
241 /* re-open the backup file as the input file */ 241 /* re-open the backup file as the input file */
242 input = fopen(backup_name, "r"); 242 input = fopen(backup_name, "r");
243 if (input == NULL) 243 if (input == NULL)
244 err(1, "%s", backup_name); 244 err(1, "%s", backup_name);
245 /* now the original input file will be the output */ 245 /* now the original input file will be the output */
246 output = fopen(in_name, "w"); 246 output = fopen(in_name, "w");
247 if (output == NULL) { 247 if (output == NULL) {
248 remove(backup_name); 248 remove(backup_name);
249 err(1, "%s", in_name); 249 err(1, "%s", in_name);
250 } 250 }
251} 251}
252 252
253static void 253static void
254parse_command_line(int argc, char **argv) 254parse_command_line(int argc, char **argv)
255{ 255{
256 for (int i = 1; i < argc; ++i) { 256 for (int i = 1; i < argc; ++i) {
257 const char *arg = argv[i]; 257 const char *arg = argv[i];
258 258
259 if (arg[0] == '-') { 259 if (arg[0] == '-') {
260 set_option(arg, "Command line"); 260 set_option(arg, "Command line");
261 261
262 } else if (input == NULL) { 262 } else if (input == NULL) {
263 in_name = arg; 263 in_name = arg;
264 if ((input = fopen(in_name, "r")) == NULL) 264 if ((input = fopen(in_name, "r")) == NULL)
265 err(1, "%s", in_name); 265 err(1, "%s", in_name);
266 266
267 } else if (output == NULL) { 267 } else if (output == NULL) {
268 if (strcmp(arg, in_name) == 0) 268 if (strcmp(arg, in_name) == 0)
269 errx(1, "input and output files " 269 errx(1, "input and output files "
270 "must be different"); 270 "must be different");
271 if ((output = fopen(arg, "w")) == NULL) 271 if ((output = fopen(arg, "w")) == NULL)
272 err(1, "%s", arg); 272 err(1, "%s", arg);
273 273
274 } else 274 } else
275 errx(1, "too many arguments: %s", arg); 275 errx(1, "too many arguments: %s", arg);
276 } 276 }
277 277
278 if (input == NULL) { 278 if (input == NULL) {
279 input = stdin; 279 input = stdin;
280 output = stdout; 280 output = stdout;
281 } else if (output == NULL) 281 } else if (output == NULL)
282 copy_to_bak_file(); 282 copy_to_bak_file();
283 283
284 if (opt.comment_column <= 1) 284 if (opt.comment_column <= 1)
285 opt.comment_column = 2; /* don't put normal comments in column 285 opt.comment_column = 2; /* don't put normal comments in column
286 * 1, see opt.format_col1_comments */ 286 * 1, see opt.format_col1_comments */
287 if (opt.block_comment_max_line_length <= 0) 287 if (opt.block_comment_max_line_length <= 0)
288 opt.block_comment_max_line_length = opt.max_line_length; 288 opt.block_comment_max_line_length = opt.max_line_length;
289 if (opt.local_decl_indent < 0) 289 if (opt.local_decl_indent < 0)
290 opt.local_decl_indent = opt.decl_indent; 290 opt.local_decl_indent = opt.decl_indent;
291 if (opt.decl_comment_column <= 0) 291 if (opt.decl_comment_column <= 0)
292 opt.decl_comment_column = opt.left_justify_decl 292 opt.decl_comment_column = opt.left_justify_decl
293 ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8) 293 ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8)
294 : opt.comment_column; 294 : opt.comment_column;
295 if (opt.continuation_indent == 0) 295 if (opt.continuation_indent == 0)
296 opt.continuation_indent = opt.indent_size; 296 opt.continuation_indent = opt.indent_size;
297} 297}
298 298
299static void 299static void
300set_initial_indentation(void) 300set_initial_indentation(void)
301{ 301{
302 inp_read_line(); 302 inp_read_line();
303 303
304 int ind = 0; 304 int ind = 0;
305 for (const char *p = inp_p;; p++) { 305 for (const char *p = inp_p;; p++) {
306 if (*p == ' ') 306 if (*p == ' ')
307 ind++; 307 ind++;
308 else if (*p == '\t') 308 else if (*p == '\t')
309 ind = next_tab(ind); 309 ind = next_tab(ind);
310 else 310 else
311 break; 311 break;
312 } 312 }
313 313
314 ps.ind_level = ps.ind_level_follow = ind / opt.indent_size; 314 ps.ind_level = ps.ind_level_follow = ind / opt.indent_size;
315} 315}
316 316
317static bool 317static bool
318should_break_line(lexer_symbol lsym) 318should_break_line(lexer_symbol lsym)
319{ 319{
320 if (lsym == lsym_semicolon) 320 if (lsym == lsym_semicolon)
321 return false; 321 return false;
322 if (ps.prev_lsym == lsym_lbrace || ps.prev_lsym == lsym_semicolon) 322 if (ps.prev_lsym == lsym_lbrace || ps.prev_lsym == lsym_semicolon)
323 return true; 323 return true;
324 if (lsym == lsym_lbrace && opt.brace_same_line) 324 if (lsym == lsym_lbrace && opt.brace_same_line)
325 return false; 325 return false;
326 return true; 326 return true;
327} 327}
328 328
329static void 329static void
330move_com_to_code(lexer_symbol lsym) 330move_com_to_code(lexer_symbol lsym)
331{ 331{
332 if (ps.want_blank) 332 if (ps.want_blank)
333 buf_add_char(&code, ' '); 333 buf_add_char(&code, ' ');
334 buf_add_buf(&code, &com); 334 buf_add_buf(&code, &com);
335 buf_clear(&com); 335 buf_clear(&com);
336 ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket; 336 ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket;
337} 337}
338 338
339static void 339static void
340update_ps_lbrace_kind(lexer_symbol lsym) 340update_ps_lbrace_kind(lexer_symbol lsym)
341{ 341{
342 if (lsym == lsym_tag) { 342 if (lsym == lsym_tag) {
343 ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct : 343 ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct :
344 token.s[0] == 'u' ? psym_lbrace_union : 344 token.s[0] == 'u' ? psym_lbrace_union :
345 psym_lbrace_enum; 345 psym_lbrace_enum;
346 } else if (lsym != lsym_type_outside_parentheses 346 } else if (lsym != lsym_type_outside_parentheses
347 && lsym != lsym_word 347 && lsym != lsym_word
348 && lsym != lsym_lbrace) 348 && lsym != lsym_lbrace)
349 ps.lbrace_kind = psym_lbrace_block; 349 ps.lbrace_kind = psym_lbrace_block;
350} 350}
351 351
352static void 352static void
353indent_declarator(int decl_ind, bool tabs_to_var) 353indent_declarator(int decl_ind, bool tabs_to_var)
354{ 354{
355 int base = ps.ind_level * opt.indent_size; 355 int base = ps.ind_level * opt.indent_size;
356 int ind = base + (int)code.len; 356 int ind = base + (int)code.len;
357 int target = base + decl_ind; 357 int target = base + decl_ind;
358 size_t orig_code_len = code.len; 358 size_t orig_code_len = code.len;
359 359
360 if (tabs_to_var) 360 if (tabs_to_var)
361 for (int next; (next = next_tab(ind)) <= target; ind = next) 361 for (int next; (next = next_tab(ind)) <= target; ind = next)
362 buf_add_char(&code, '\t'); 362 buf_add_char(&code, '\t');
363 363
364 for (; ind < target; ind++) 364 for (; ind < target; ind++)
365 buf_add_char(&code, ' '); 365 buf_add_char(&code, ' ');
366 366
367 if (code.len == orig_code_len && ps.want_blank) { 367 if (code.len == orig_code_len && ps.want_blank) {
368 buf_add_char(&code, ' '); 368 buf_add_char(&code, ' ');
369 ps.want_blank = false; 369 ps.want_blank = false;
370 } 370 }
371 ps.decl_indent_done = true; 371 ps.decl_indent_done = true;
372} 372}
373 373
374static bool 374static bool
375is_function_pointer_declaration(void) 375is_function_pointer_declaration(void)
376{ 376{
377 return ps.in_decl 377 return ps.in_decl
378 && !ps.in_init 378 && !ps.in_init
379 && !ps.decl_indent_done 379 && !ps.decl_indent_done
380 && !ps.line_has_func_def 380 && !ps.line_has_func_def
381 && ps.line_start_nparen == 0; 381 && ps.ind_paren_level == 0;
382} 382}
383 383
384static int 384static int
385process_eof(void) 385process_eof(void)
386{ 386{
387 finish_output(); 387 finish_output();
388 388
389 if (ps.psyms.top > 1) /* check for balanced braces */ 389 if (ps.psyms.top > 1) /* check for balanced braces */
390 diag(1, "Stuff missing from end of file"); 390 diag(1, "Stuff missing from end of file");
391 391
392 return found_err ? EXIT_FAILURE : EXIT_SUCCESS; 392 return found_err ? EXIT_FAILURE : EXIT_SUCCESS;
393} 393}
394 394
395/* move the whole line to the 'label' buffer */ 395/* move the whole line to the 'label' buffer */
396static void 396static void
397read_preprocessing_line(void) 397read_preprocessing_line(void)
398{ 398{
399 enum { 399 enum {
400 PLAIN, STR, CHR, COMM 400 PLAIN, STR, CHR, COMM
401 } state = PLAIN; 401 } state = PLAIN;
402 402
403 buf_add_char(&lab, '#'); 403 buf_add_char(&lab, '#');
404 404
405 while (inp_p[0] != '\n' || (state == COMM && !had_eof)) { 405 while (inp_p[0] != '\n' || (state == COMM && !had_eof)) {
406 buf_add_char(&lab, inp_next()); 406 buf_add_char(&lab, inp_next());
407 switch (lab.s[lab.len - 1]) { 407 switch (lab.s[lab.len - 1]) {
408 case '\\': 408 case '\\':
409 if (state != COMM) 409 if (state != COMM)
410 buf_add_char(&lab, inp_next()); 410 buf_add_char(&lab, inp_next());
411 break; 411 break;
412 case '/': 412 case '/':
413 if (inp_p[0] == '*' && state == PLAIN) { 413 if (inp_p[0] == '*' && state == PLAIN) {
414 state = COMM; 414 state = COMM;
415 buf_add_char(&lab, *inp_p++); 415 buf_add_char(&lab, *inp_p++);
416 } 416 }
417 break; 417 break;
418 case '"': 418 case '"':
419 if (state == STR) 419 if (state == STR)
420 state = PLAIN; 420 state = PLAIN;
421 else if (state == PLAIN) 421 else if (state == PLAIN)
422 state = STR; 422 state = STR;
423 break; 423 break;
424 case '\'': 424 case '\'':
425 if (state == CHR) 425 if (state == CHR)
426 state = PLAIN; 426 state = PLAIN;
427 else if (state == PLAIN) 427 else if (state == PLAIN)
428 state = CHR; 428 state = CHR;
429 break; 429 break;
430 case '*': 430 case '*':
431 if (inp_p[0] == '/' && state == COMM) { 431 if (inp_p[0] == '/' && state == COMM) {
432 state = PLAIN; 432 state = PLAIN;
433 buf_add_char(&lab, *inp_p++); 433 buf_add_char(&lab, *inp_p++);
434 } 434 }
435 break; 435 break;
436 } 436 }
437 } 437 }
438 438
439 while (lab.len > 0 && ch_isblank(lab.s[lab.len - 1])) 439 while (lab.len > 0 && ch_isblank(lab.s[lab.len - 1]))
440 lab.len--; 440 lab.len--;
441 buf_terminate(&lab); 441 buf_terminate(&lab);
442} 442}
443 443
444static void 444static void
445process_preprocessing(void) 445process_preprocessing(void)
446{ 446{
447 if (lab.len > 0 || code.len > 0 || com.len > 0) 447 if (lab.len > 0 || code.len > 0 || com.len > 0)
448 output_line(); 448 output_line();
449 449
450 read_preprocessing_line(); 450 read_preprocessing_line();
451 451
452 const char *dir = lab.s + 1, *line_end = lab.s + lab.len; 452 const char *dir = lab.s + 1, *line_end = lab.s + lab.len;
453 while (dir < line_end && ch_isblank(*dir)) 453 while (dir < line_end && ch_isblank(*dir))
454 dir++; 454 dir++;
455 size_t dir_len = 0; 455 size_t dir_len = 0;
456 while (dir + dir_len < line_end && ch_isalpha(dir[dir_len])) 456 while (dir + dir_len < line_end && ch_isalpha(dir[dir_len]))
457 dir_len++; 457 dir_len++;
458 458
459 if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) { 459 if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) {
460 if ((size_t)ifdef_level < array_length(state_stack)) 460 if ((size_t)ifdef_level < array_length(state_stack))
461 state_stack[ifdef_level++] = ps; 461 state_stack[ifdef_level++] = ps;
462 else 462 else
463 diag(1, "#if stack overflow"); 463 diag(1, "#if stack overflow");
464 out.line_kind = lk_if; 464 out.line_kind = lk_if;
465 465
466 } else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) { 466 } else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) {
467 if (ifdef_level <= 0) 467 if (ifdef_level <= 0)
468 diag(1, dir[2] == 'i' 468 diag(1, dir[2] == 'i'
469 ? "Unmatched #elif" : "Unmatched #else"); 469 ? "Unmatched #elif" : "Unmatched #else");
470 else 470 else
471 ps = state_stack[ifdef_level - 1]; 471 ps = state_stack[ifdef_level - 1];
472 472
473 } else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) { 473 } else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) {
474 if (ifdef_level <= 0) 474 if (ifdef_level <= 0)
475 diag(1, "Unmatched #endif"); 475 diag(1, "Unmatched #endif");
476 else 476 else
477 ifdef_level--; 477 ifdef_level--;
478 out.line_kind = lk_endif; 478 out.line_kind = lk_endif;
479 } 479 }
480} 480}
481 481
482static void 482static void
483process_newline(void) 483process_newline(void)
484{ 484{
485 if (ps.prev_lsym == lsym_comma 485 if (ps.prev_lsym == lsym_comma
486 && ps.nparen == 0 && !ps.in_init 486 && ps.nparen == 0 && !ps.in_init
487 && !opt.break_after_comma && ps.break_after_comma 487 && !opt.break_after_comma && ps.break_after_comma
488 && lab.len == 0 /* for preprocessing lines */ 488 && lab.len == 0 /* for preprocessing lines */
489 && com.len == 0) 489 && com.len == 0)
490 goto stay_in_line; 490 goto stay_in_line;
491 if (ps.psyms.sym[ps.psyms.top] == psym_switch_expr 491 if (ps.psyms.sym[ps.psyms.top] == psym_switch_expr
492 && opt.brace_same_line) { 492 && opt.brace_same_line) {
493 ps.force_nl = true; 493 ps.force_nl = true;
494 goto stay_in_line; 494 goto stay_in_line;
495 } 495 }
496 496
497 output_line(); 497 output_line();
498 498
499stay_in_line: 499stay_in_line:
500 ++line_no; 500 ++line_no;
501} 501}
502 502
503static bool 503static bool
504want_blank_before_lparen(void) 504want_blank_before_lparen(void)
505{ 505{
506 if (!ps.want_blank) 506 if (!ps.want_blank)
507 return false; 507 return false;
508 if (opt.proc_calls_space) 508 if (opt.proc_calls_space)
509 return true; 509 return true;
510 if (ps.prev_lsym == lsym_rparen || ps.prev_lsym == lsym_rbracket) 510 if (ps.prev_lsym == lsym_rparen || ps.prev_lsym == lsym_rbracket)
511 return false; 511 return false;
512 if (ps.prev_lsym == lsym_offsetof) 512 if (ps.prev_lsym == lsym_offsetof)
513 return false; 513 return false;
514 if (ps.prev_lsym == lsym_sizeof) 514 if (ps.prev_lsym == lsym_sizeof)
515 return opt.blank_after_sizeof; 515 return opt.blank_after_sizeof;
516 if (ps.prev_lsym == lsym_word || ps.prev_lsym == lsym_funcname) 516 if (ps.prev_lsym == lsym_word || ps.prev_lsym == lsym_funcname)
517 return false; 517 return false;
518 return true; 518 return true;
519} 519}
520 520
521static void 521static void
522process_lparen(void) 522process_lparen(void)
523{ 523{
524 if (++ps.nparen == array_length(ps.paren)) { 524 if (++ps.nparen == array_length(ps.paren)) {
525 diag(0, "Reached internal limit of %zu unclosed parentheses", 525 diag(0, "Reached internal limit of %zu unclosed parentheses",
526 array_length(ps.paren)); 526 array_length(ps.paren));
527 ps.nparen--; 527 ps.nparen--;
528 } 528 }
529 529
530 if (is_function_pointer_declaration()) 530 if (is_function_pointer_declaration())
531 indent_declarator(ps.decl_ind, ps.tabs_to_var); 531 indent_declarator(ps.decl_ind, ps.tabs_to_var);
532 else if (want_blank_before_lparen()) 532 else if (want_blank_before_lparen())
533 buf_add_char(&code, ' '); 533 buf_add_char(&code, ' ');
534 ps.want_blank = false; 534 ps.want_blank = false;
535 buf_add_char(&code, token.s[0]); 535 buf_add_char(&code, token.s[0]);
536 536
537 if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0) 537 if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0)
538 ps.extra_expr_indent = eei_maybe; 538 ps.extra_expr_indent = eei_maybe;
539 539
540 if (ps.in_var_decl && ps.psyms.top <= 2 && !ps.in_init) { 540 if (ps.in_var_decl && ps.psyms.top <= 2 && !ps.in_init) {
541 parse(psym_stmt); /* prepare for function definition */ 541 parse(psym_stmt); /* prepare for function definition */
542 ps.in_var_decl = false; 542 ps.in_var_decl = false;
543 } 543 }
544 544
545 int indent = ind_add(0, code.s, code.len); 545 int indent = ind_add(0, code.s, code.len);
546 546
547 enum paren_level_cast cast = cast_unknown; 547 enum paren_level_cast cast = cast_unknown;
548 if (ps.prev_lsym == lsym_offsetof 548 if (ps.prev_lsym == lsym_offsetof
549 || ps.prev_lsym == lsym_sizeof 549 || ps.prev_lsym == lsym_sizeof
550 || ps.prev_lsym == lsym_for 550 || ps.prev_lsym == lsym_for
551 || ps.prev_lsym == lsym_if 551 || ps.prev_lsym == lsym_if
552 || ps.prev_lsym == lsym_switch 552 || ps.prev_lsym == lsym_switch
553 || ps.prev_lsym == lsym_while 553 || ps.prev_lsym == lsym_while
554 || ps.line_has_func_def) 554 || ps.line_has_func_def)
555 cast = cast_no; 555 cast = cast_no;
556 556
557 ps.paren[ps.nparen - 1].indent = indent; 557 ps.paren[ps.nparen - 1].indent = indent;
558 ps.paren[ps.nparen - 1].cast = cast; 558 ps.paren[ps.nparen - 1].cast = cast;
559 debug_println("paren_indents[%d] is now %s%d", 559 debug_println("paren_indents[%d] is now %s%d",
560 ps.nparen - 1, paren_level_cast_name[cast], indent); 560 ps.nparen - 1, paren_level_cast_name[cast], indent);
561} 561}
562 562
563static void 563static void
564process_rparen(void) 564process_rparen(void)
565{ 565{
566 if (ps.nparen == 0) { 566 if (ps.nparen == 0) {
567 diag(0, "Extra '%c'", *token.s); 567 diag(0, "Extra '%c'", *token.s);
568 goto unbalanced; 568 goto unbalanced;
569 } 569 }
570 570
571 enum paren_level_cast cast = ps.paren[--ps.nparen].cast; 571 enum paren_level_cast cast = ps.paren[--ps.nparen].cast;
572 if (ps.in_func_def_params || (ps.line_has_decl && !ps.in_init)) 572 if (ps.in_func_def_params || (ps.line_has_decl && !ps.in_init))
573 cast = cast_no; 573 cast = cast_no;
574 574
575 ps.prev_paren_was_cast = cast == cast_maybe; 575 ps.prev_paren_was_cast = cast == cast_maybe;
576 if (cast == cast_maybe) { 576 if (cast == cast_maybe) {
577 ps.next_unary = true; 577 ps.next_unary = true;
578 ps.want_blank = opt.space_after_cast; 578 ps.want_blank = opt.space_after_cast;
579 } else 579 } else
580 ps.want_blank = true; 580 ps.want_blank = true;
581 581
582 if (code.len == 0) 582 if (code.len == 0)
583 ps.line_start_nparen = ps.nparen; 583 ps.ind_paren_level = ps.nparen;
584 584
585unbalanced: 585unbalanced:
586 buf_add_char(&code, token.s[0]); 586 buf_add_char(&code, token.s[0]);
587 587
588 if (ps.spaced_expr_psym != psym_0 && ps.nparen == 0) { 588 if (ps.spaced_expr_psym != psym_0 && ps.nparen == 0) {
589 if (ps.extra_expr_indent == eei_maybe) 589 if (ps.extra_expr_indent == eei_maybe)
590 ps.extra_expr_indent = eei_last; 590 ps.extra_expr_indent = eei_last;
591 ps.force_nl = true; 591 ps.force_nl = true;
592 ps.next_unary = true; 592 ps.next_unary = true;
593 ps.in_stmt_or_decl = false; 593 ps.in_stmt_or_decl = false;
594 parse(ps.spaced_expr_psym); 594 parse(ps.spaced_expr_psym);
595 ps.spaced_expr_psym = psym_0; 595 ps.spaced_expr_psym = psym_0;
596 ps.want_blank = true; 596 ps.want_blank = true;
597 out.line_kind = lk_stmt_head; 597 out.line_kind = lk_stmt_head;
598 } 598 }
599} 599}
600 600
601static void 601static void
602process_lbracket(void) 602process_lbracket(void)
603{ 603{
604 if (++ps.nparen == array_length(ps.paren)) { 604 if (++ps.nparen == array_length(ps.paren)) {
605 diag(0, "Reached internal limit of %zu unclosed parentheses", 605 diag(0, "Reached internal limit of %zu unclosed parentheses",
606 array_length(ps.paren)); 606 array_length(ps.paren));
607 ps.nparen--; 607 ps.nparen--;
608 } 608 }
609 609
610 if (code.len > 0 610 if (code.len > 0
611 && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op)) 611 && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op))
612 buf_add_char(&code, ' '); 612 buf_add_char(&code, ' ');
613 ps.want_blank = false; 613 ps.want_blank = false;
614 buf_add_char(&code, token.s[0]); 614 buf_add_char(&code, token.s[0]);
615 615
616 int indent = ind_add(0, code.s, code.len); 616 int indent = ind_add(0, code.s, code.len);
617 617
618 ps.paren[ps.nparen - 1].indent = indent; 618 ps.paren[ps.nparen - 1].indent = indent;
619 ps.paren[ps.nparen - 1].cast = cast_no; 619 ps.paren[ps.nparen - 1].cast = cast_no;
620 debug_println("paren_indents[%d] is now %d", ps.nparen - 1, indent); 620 debug_println("paren_indents[%d] is now %d", ps.nparen - 1, indent);
621} 621}
622 622
623static void 623static void
624process_rbracket(void) 624process_rbracket(void)
625{ 625{
626 if (ps.nparen == 0) { 626 if (ps.nparen == 0) {
627 diag(0, "Extra '%c'", *token.s); 627 diag(0, "Extra '%c'", *token.s);
628 goto unbalanced; 628 goto unbalanced;
629 } 629 }
630 --ps.nparen; 630 --ps.nparen;
631 631
632 ps.want_blank = true; 632 ps.want_blank = true;
633 if (code.len == 0) 633 if (code.len == 0)
634 ps.line_start_nparen = ps.nparen; 634 ps.ind_paren_level = ps.nparen;
635 635
636unbalanced: 636unbalanced:
637 buf_add_char(&code, token.s[0]); 637 buf_add_char(&code, token.s[0]);
638} 638}
639 639
640static void 640static void
641process_lbrace(void) 641process_lbrace(void)
642{ 642{
643 if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) { 643 if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) {
644 ps.in_var_decl = true; // XXX: not really 644 ps.in_var_decl = true; // XXX: not really
645 ps.in_init = true; 645 ps.in_init = true;
646 } 646 }
647 647
648 if (out.line_kind == lk_stmt_head) 648 if (out.line_kind == lk_stmt_head)
649 out.line_kind = lk_other; 649 out.line_kind = lk_other;
650 650
651 ps.in_stmt_or_decl = false; /* don't indent the {} */ 651 ps.in_stmt_or_decl = false; /* don't indent the {} */
652 652
653 if (ps.in_init) 653 if (ps.in_init)
654 ps.init_level++; 654 ps.init_level++;
655 else 655 else
656 ps.force_nl = true; 656 ps.force_nl = true;
657 657
658 if (code.len > 0 && !ps.in_init) { 658 if (code.len > 0 && !ps.in_init) {
659 if (!opt.brace_same_line || 659 if (!opt.brace_same_line ||
660 (code.len > 0 && code.s[code.len - 1] == '}')) 660 (code.len > 0 && code.s[code.len - 1] == '}'))
661 output_line(); 661 output_line();
662 else if (ps.in_func_def_params && !ps.in_var_decl) { 662 else if (ps.in_func_def_params && !ps.in_var_decl) {
663 ps.ind_level_follow = 0; 663 ps.ind_level_follow = 0;
664 if (opt.function_brace_split) 664 if (opt.function_brace_split)
665 output_line(); 665 output_line();
666 else 666 else
667 ps.want_blank = true; 667 ps.want_blank = true;
668 } 668 }
669 } 669 }
670 670
671 if (ps.nparen > 0 && ps.init_level == 0) { 671 if (ps.nparen > 0 && ps.init_level == 0) {
672 diag(1, "Unbalanced parentheses"); 672 diag(1, "Unbalanced parentheses");
673 ps.nparen = 0; 673 ps.nparen = 0;
674 if (ps.spaced_expr_psym != psym_0) { 674 if (ps.spaced_expr_psym != psym_0) {
675 parse(ps.spaced_expr_psym); 675 parse(ps.spaced_expr_psym);
676 ps.spaced_expr_psym = psym_0; 676 ps.spaced_expr_psym = psym_0;
677 ps.ind_level = ps.ind_level_follow; 677 ps.ind_level = ps.ind_level_follow;
678 } 678 }
679 } 679 }
680 680
681 if (code.len == 0) 681 if (code.len == 0)
682 ps.in_stmt_cont = false; /* don't indent the '{' itself 682 ps.in_stmt_cont = false; /* don't indent the '{' itself
683 */ 683 */
684 if (ps.in_decl && ps.in_var_decl) { 684 if (ps.in_decl && ps.in_var_decl) {
685 ps.di_stack[ps.decl_level] = ps.decl_ind; 685 ps.di_stack[ps.decl_level] = ps.decl_ind;
686 if (++ps.decl_level == (int)array_length(ps.di_stack)) { 686 if (++ps.decl_level == (int)array_length(ps.di_stack)) {
687 diag(0, "Reached internal limit of %zu struct levels", 687 diag(0, "Reached internal limit of %zu struct levels",
688 array_length(ps.di_stack)); 688 array_length(ps.di_stack));
689 ps.decl_level--; 689 ps.decl_level--;
690 } 690 }
691 } else { 691 } else {
692 ps.line_has_decl = false; /* we can't be in the middle of 692 ps.line_has_decl = false; /* we can't be in the middle of
693 * a declaration, so don't do 693 * a declaration, so don't do
694 * special indentation of 694 * special indentation of
695 * comments */ 695 * comments */
696 ps.in_func_def_params = false; 696 ps.in_func_def_params = false;
697 ps.in_decl = false; 697 ps.in_decl = false;
698 } 698 }
699 699
700 ps.decl_ind = 0; 700 ps.decl_ind = 0;
701 parse(ps.lbrace_kind); 701 parse(ps.lbrace_kind);
702 if (ps.want_blank) 702 if (ps.want_blank)
703 buf_add_char(&code, ' '); 703 buf_add_char(&code, ' ');
704 ps.want_blank = false; 704 ps.want_blank = false;
705 buf_add_char(&code, '{'); 705 buf_add_char(&code, '{');
706 ps.declaration = decl_no; 706 ps.declaration = decl_no;
707} 707}
708 708
709static void 709static void
710process_rbrace(void) 710process_rbrace(void)
711{ 711{
712 if (ps.nparen > 0 && ps.init_level == 0) { 712 if (ps.nparen > 0 && ps.init_level == 0) {
713 diag(1, "Unbalanced parentheses"); 713 diag(1, "Unbalanced parentheses");
714 ps.nparen = 0; 714 ps.nparen = 0;
715 ps.spaced_expr_psym = psym_0; 715 ps.spaced_expr_psym = psym_0;
716 } 716 }
717 717
718 ps.declaration = decl_no; 718 ps.declaration = decl_no;
719 if (ps.init_level > 0) 719 if (ps.init_level > 0)
720 ps.init_level--; 720 ps.init_level--;
721 721
722 if (code.len > 0 && !ps.in_init) 722 if (code.len > 0 && !ps.in_init)
723 output_line(); 723 output_line();
724 724
725 buf_add_char(&code, '}'); 725 buf_add_char(&code, '}');
726 ps.want_blank = true; 726 ps.want_blank = true;
727 ps.in_stmt_or_decl = false; // XXX: Initializers don't end a stmt 727 ps.in_stmt_or_decl = false; // XXX: Initializers don't end a stmt
728 ps.in_stmt_cont = false; 728 ps.in_stmt_cont = false;
729 729
730 if (ps.decl_level > 0) { /* multi-level structure declaration */ 730 if (ps.decl_level > 0) { /* multi-level structure declaration */
731 ps.decl_ind = ps.di_stack[--ps.decl_level]; 731 ps.decl_ind = ps.di_stack[--ps.decl_level];
732 if (ps.decl_level == 0 && !ps.in_func_def_params) { 732 if (ps.decl_level == 0 && !ps.in_func_def_params) {
733 ps.declaration = decl_begin; 733 ps.declaration = decl_begin;
734 ps.decl_ind = ps.ind_level == 0 734 ps.decl_ind = ps.ind_level == 0
735 ? opt.decl_indent : opt.local_decl_indent; 735 ? opt.decl_indent : opt.local_decl_indent;
736 } 736 }
737 ps.in_decl = true; 737 ps.in_decl = true;
738 } 738 }
739 739
740 if (ps.psyms.top == 2) 740 if (ps.psyms.top == 2)
741 out.line_kind = lk_func_end; 741 out.line_kind = lk_func_end;
742 742
743 parse(psym_rbrace); 743 parse(psym_rbrace);
744 744
745 if (!ps.in_var_decl 745 if (!ps.in_var_decl
746 && ps.psyms.sym[ps.psyms.top] != psym_do_stmt 746 && ps.psyms.sym[ps.psyms.top] != psym_do_stmt
747 && ps.psyms.sym[ps.psyms.top] != psym_if_expr_stmt) 747 && ps.psyms.sym[ps.psyms.top] != psym_if_expr_stmt)
748 ps.force_nl = true; 748 ps.force_nl = true;
749} 749}
750 750
751static void 751static void
752process_period(void) 752process_period(void)
753{ 753{
754 if (code.len > 0 && code.s[code.len - 1] == ',') 754 if (code.len > 0 && code.s[code.len - 1] == ',')
755 buf_add_char(&code, ' '); 755 buf_add_char(&code, ' ');
756 buf_add_char(&code, '.'); 756 buf_add_char(&code, '.');
757 ps.want_blank = false; 757 ps.want_blank = false;
758} 758}
759 759
760static void 760static void
761process_unary_op(void) 761process_unary_op(void)
762{ 762{
763 if (is_function_pointer_declaration()) { 763 if (is_function_pointer_declaration()) {
764 int ind = ps.decl_ind - (int)token.len; 764 int ind = ps.decl_ind - (int)token.len;
765 indent_declarator(ind, ps.tabs_to_var); 765 indent_declarator(ind, ps.tabs_to_var);
766 ps.want_blank = false; 766 ps.want_blank = false;
767 } else if ((token.s[0] == '+' || token.s[0] == '-') 767 } else if ((token.s[0] == '+' || token.s[0] == '-')
768 && code.len > 0 && code.s[code.len - 1] == token.s[0]) 768 && code.len > 0 && code.s[code.len - 1] == token.s[0])
769 ps.want_blank = true; 769 ps.want_blank = true;
770 770
771 if (ps.want_blank) 771 if (ps.want_blank)
772 buf_add_char(&code, ' '); 772 buf_add_char(&code, ' ');
773 buf_add_buf(&code, &token); 773 buf_add_buf(&code, &token);
774 ps.want_blank = false; 774 ps.want_blank = false;
775} 775}
776 776
777static void 777static void
778process_postfix_op(void) 778process_postfix_op(void)
779{ 779{
780 buf_add_buf(&code, &token); 780 buf_add_buf(&code, &token);
781 ps.want_blank = true; 781 ps.want_blank = true;
782} 782}
783 783
784static void 784static void
785process_comma(void) 785process_comma(void)
786{ 786{
787 ps.want_blank = code.len > 0; /* only put blank after comma if comma 787 ps.want_blank = code.len > 0; /* only put blank after comma if comma
788 * does not start the line */ 788 * does not start the line */
789 789
790 if (ps.in_decl && !ps.line_has_func_def && !ps.in_init && 790 if (ps.in_decl && !ps.line_has_func_def && !ps.in_init &&
791 !ps.decl_indent_done && ps.line_start_nparen == 0) { 791 !ps.decl_indent_done && ps.ind_paren_level == 0) {
792 /* indent leading commas and not the actual identifiers */ 792 /* indent leading commas and not the actual identifiers */
793 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); 793 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var);
794 } 794 }
795 795
796 buf_add_char(&code, ','); 796 buf_add_char(&code, ',');
797 797
798 if (ps.nparen == 0) { 798 if (ps.nparen == 0) {
799 if (ps.init_level == 0) 799 if (ps.init_level == 0)
800 ps.in_init = false; 800 ps.in_init = false;
801 int typical_varname_length = 8; 801 int typical_varname_length = 8;
802 if (ps.break_after_comma && (opt.break_after_comma || 802 if (ps.break_after_comma && (opt.break_after_comma ||
803 ind_add(compute_code_indent(), code.s, code.len) 803 ind_add(compute_code_indent(), code.s, code.len)
804 >= opt.max_line_length - typical_varname_length)) 804 >= opt.max_line_length - typical_varname_length))
805 ps.force_nl = true; 805 ps.force_nl = true;
806 } 806 }
807} 807}
808 808
809static void 809static void
810process_label_colon(void) 810process_label_colon(void)
811{ 811{
812 buf_add_buf(&lab, &code); 812 buf_add_buf(&lab, &code);
813 buf_add_char(&lab, ':'); 813 buf_add_char(&lab, ':');
814 buf_clear(&code); 814 buf_clear(&code);
815 815
816 if (ps.seen_case) 816 if (ps.seen_case)
817 out.line_kind = lk_case_or_default; 817 out.line_kind = lk_case_or_default;
818 ps.in_stmt_or_decl = false; 818 ps.in_stmt_or_decl = false;
819 ps.force_nl = ps.seen_case; 819 ps.force_nl = ps.seen_case;
820 ps.seen_case = false; 820 ps.seen_case = false;
821 ps.want_blank = false; 821 ps.want_blank = false;
822} 822}
823 823
824static void 824static void
825process_other_colon(void) 825process_other_colon(void)
826{ 826{
827 buf_add_char(&code, ':'); 827 buf_add_char(&code, ':');
828 ps.want_blank = ps.decl_level == 0; 828 ps.want_blank = ps.decl_level == 0;
829} 829}
830 830
831static void 831static void
832process_semicolon(void) 832process_semicolon(void)
833{ 833{
834 if (out.line_kind == lk_stmt_head) 834 if (out.line_kind == lk_stmt_head)
835 out.line_kind = lk_other; 835 out.line_kind = lk_other;
836 if (ps.decl_level == 0) 836 if (ps.decl_level == 0)
837 ps.in_var_decl = false; 837 ps.in_var_decl = false;
838 ps.seen_case = false; /* only needs to be reset on error */ 838 ps.seen_case = false; /* only needs to be reset on error */
839 ps.quest_level = 0; /* only needs to be reset on error */ 839 ps.quest_level = 0; /* only needs to be reset on error */
840 if (ps.prev_lsym == lsym_rparen) 840 if (ps.prev_lsym == lsym_rparen)
841 ps.in_func_def_params = false; 841 ps.in_func_def_params = false;
842 ps.in_init = false; 842 ps.in_init = false;
843 ps.init_level = 0; 843 ps.init_level = 0;
844 ps.declaration = ps.declaration == decl_begin ? decl_end : decl_no; 844 ps.declaration = ps.declaration == decl_begin ? decl_end : decl_no;
845 845
846 if (ps.in_decl && code.len == 0 && !ps.in_init && 846 if (ps.in_decl && code.len == 0 && !ps.in_init &&
847 !ps.decl_indent_done && ps.line_start_nparen == 0) { 847 !ps.decl_indent_done && ps.ind_paren_level == 0) {
848 /* indent stray semicolons in declarations */ 848 /* indent stray semicolons in declarations */
849 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); 849 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var);
850 } 850 }
851 851
852 ps.in_decl = ps.decl_level > 0; /* if we were in a first level 852 ps.in_decl = ps.decl_level > 0; /* if we were in a first level
853 * structure declaration before, we 853 * structure declaration before, we
854 * aren't anymore */ 854 * aren't anymore */
855 855
856 if (ps.nparen > 0 && ps.spaced_expr_psym != psym_for_exprs) { 856 if (ps.nparen > 0 && ps.spaced_expr_psym != psym_for_exprs) {
857 /* There were unbalanced parentheses in the statement. It is a 857 /* There were unbalanced parentheses in the statement. It is a
858 * bit complicated, because the semicolon might be in a for 858 * bit complicated, because the semicolon might be in a for
859 * statement. */ 859 * statement. */
860 diag(1, "Unbalanced parentheses"); 860 diag(1, "Unbalanced parentheses");
861 ps.nparen = 0; 861 ps.nparen = 0;
862 if (ps.spaced_expr_psym != psym_0) { 862 if (ps.spaced_expr_psym != psym_0) {
863 parse(ps.spaced_expr_psym); 863 parse(ps.spaced_expr_psym);
864 ps.spaced_expr_psym = psym_0; 864 ps.spaced_expr_psym = psym_0;
865 } 865 }
866 } 866 }
867 buf_add_char(&code, ';'); 867 buf_add_char(&code, ';');
868 ps.want_blank = true; 868 ps.want_blank = true;
869 ps.in_stmt_or_decl = ps.nparen > 0; 869 ps.in_stmt_or_decl = ps.nparen > 0;
870 ps.decl_ind = 0; 870 ps.decl_ind = 0;
871 871
872 if (ps.spaced_expr_psym == psym_0) { 872 if (ps.spaced_expr_psym == psym_0) {
873 parse(psym_stmt); 873 parse(psym_stmt);
874 ps.force_nl = true; 874 ps.force_nl = true;
875 } 875 }
876} 876}
877 877
878static void 878static void
879process_type_outside_parentheses(void) 879process_type_outside_parentheses(void)
880{ 880{
881 parse(psym_decl); /* let the parser worry about indentation */ 881 parse(psym_decl); /* let the parser worry about indentation */
882 882
883 if (ps.prev_lsym == lsym_rparen && ps.psyms.top <= 1 && code.len > 0) 883 if (ps.prev_lsym == lsym_rparen && ps.psyms.top <= 1 && code.len > 0)
884 output_line(); 884 output_line();
885 885
886 if (ps.in_func_def_params && opt.indent_parameters && 886 if (ps.in_func_def_params && opt.indent_parameters &&
887 ps.decl_level == 0) { 887 ps.decl_level == 0) {
888 ps.ind_level = ps.ind_level_follow = 1; 888 ps.ind_level = ps.ind_level_follow = 1;
889 ps.in_stmt_cont = false; 889 ps.in_stmt_cont = false;
890 } 890 }
891 891
892 ps.in_var_decl = /* maybe */ true; 892 ps.in_var_decl = /* maybe */ true;
893 ps.in_decl = ps.line_has_decl = ps.prev_lsym != lsym_typedef; 893 ps.in_decl = ps.line_has_decl = ps.prev_lsym != lsym_typedef;
894 if (ps.decl_level <= 0) 894 if (ps.decl_level <= 0)
895 ps.declaration = decl_begin; 895 ps.declaration = decl_begin;
896 896
897 int len = (int)token.len + 1; 897 int len = (int)token.len + 1;
898 int ind = ps.ind_level > 0 && ps.decl_level == 0 898 int ind = ps.ind_level > 0 && ps.decl_level == 0
899 ? opt.local_decl_indent /* local variable */ 899 ? opt.local_decl_indent /* local variable */
900 : opt.decl_indent; /* global variable, or member */ 900 : opt.decl_indent; /* global variable, or member */
901 ps.decl_ind = ind > 0 ? ind : len; 901 ps.decl_ind = ind > 0 ? ind : len;
902 ps.tabs_to_var = opt.use_tabs && ind > 0; 902 ps.tabs_to_var = opt.use_tabs && ind > 0;
903} 903}
904 904
905static void 905static void
906process_word(lexer_symbol lsym) 906process_word(lexer_symbol lsym)
907{ 907{
908 if (ps.in_decl) { 908 if (ps.in_decl) {
909 if (lsym == lsym_funcname) { 909 if (lsym == lsym_funcname) {
910 ps.in_decl = false; 910 ps.in_decl = false;
911 if (opt.procnames_start_line && code.len > 0) 911 if (opt.procnames_start_line && code.len > 0)
912 output_line(); 912 output_line();
913 else if (ps.want_blank) 913 else if (ps.want_blank)
914 buf_add_char(&code, ' '); 914 buf_add_char(&code, ' ');
915 ps.want_blank = false; 915 ps.want_blank = false;
916 916
917 } else if (!ps.in_init && !ps.decl_indent_done && 917 } else if (!ps.in_init && !ps.decl_indent_done &&
918 ps.line_start_nparen == 0) { 918 ps.ind_paren_level == 0) {
919 if (opt.decl_indent == 0 919 if (opt.decl_indent == 0
920 && code.len > 0 && code.s[code.len - 1] == '}') 920 && code.len > 0 && code.s[code.len - 1] == '}')
921 ps.decl_ind = ind_add(0, code.s, code.len) + 1; 921 ps.decl_ind = ind_add(0, code.s, code.len) + 1;
922 indent_declarator(ps.decl_ind, ps.tabs_to_var); 922 indent_declarator(ps.decl_ind, ps.tabs_to_var);
923 ps.want_blank = false; 923 ps.want_blank = false;
924 } 924 }
925 925
926 } else if (ps.spaced_expr_psym != psym_0 && ps.nparen == 0) { 926 } else if (ps.spaced_expr_psym != psym_0 && ps.nparen == 0) {
927 ps.force_nl = true; 927 ps.force_nl = true;
928 ps.in_stmt_or_decl = false; 928 ps.in_stmt_or_decl = false;
929 ps.next_unary = true; 929 ps.next_unary = true;
930 parse(ps.spaced_expr_psym); 930 parse(ps.spaced_expr_psym);
931 ps.spaced_expr_psym = psym_0; 931 ps.spaced_expr_psym = psym_0;
932 } 932 }
933} 933}
934 934
935static void 935static void
936process_do(void) 936process_do(void)
937{ 937{
938 ps.in_stmt_or_decl = false; 938 ps.in_stmt_or_decl = false;
939 ps.in_decl = false; 939 ps.in_decl = false;
940 940
941 if (code.len > 0) 941 if (code.len > 0)
942 output_line(); 942 output_line();
943 943
944 ps.force_nl = true; 944 ps.force_nl = true;
945 parse(psym_do); 945 parse(psym_do);
946} 946}
947 947
948static void 948static void
949process_else(void) 949process_else(void)
950{ 950{
951 ps.in_stmt_or_decl = false; 951 ps.in_stmt_or_decl = false;
952 952
953 if (code.len > 0 953 if (code.len > 0
954 && !(opt.cuddle_else && code.s[code.len - 1] == '}')) 954 && !(opt.cuddle_else && code.s[code.len - 1] == '}'))
955 output_line(); 955 output_line();
956 956
957 ps.force_nl = true; 957 ps.force_nl = true;
958 parse(psym_else); 958 parse(psym_else);
959} 959}
960 960
961static void 961static void
962process_lsym(lexer_symbol lsym) 962process_lsym(lexer_symbol lsym)
963{ 963{
964 switch (lsym) { 964 switch (lsym) {
965 /* INDENT OFF */ 965 /* INDENT OFF */
966 case lsym_preprocessing: process_preprocessing(); break; 966 case lsym_preprocessing: process_preprocessing(); break;
967 case lsym_newline: process_newline(); break; 967 case lsym_newline: process_newline(); break;
968 case lsym_comment: process_comment(); break; 968 case lsym_comment: process_comment(); break;
969 case lsym_lparen: process_lparen(); break; 969 case lsym_lparen: process_lparen(); break;
970 case lsym_lbracket: process_lbracket(); break; 970 case lsym_lbracket: process_lbracket(); break;
971 case lsym_rparen: process_rparen(); break; 971 case lsym_rparen: process_rparen(); break;
972 case lsym_rbracket: process_rbracket(); break; 972 case lsym_rbracket: process_rbracket(); break;
973 case lsym_lbrace: process_lbrace(); break; 973 case lsym_lbrace: process_lbrace(); break;
974 case lsym_rbrace: process_rbrace(); break; 974 case lsym_rbrace: process_rbrace(); break;
975 case lsym_period: process_period(); break; 975 case lsym_period: process_period(); break;
976 case lsym_unary_op: process_unary_op(); break; 976 case lsym_unary_op: process_unary_op(); break;
977 case lsym_postfix_op: process_postfix_op(); break; 977 case lsym_postfix_op: process_postfix_op(); break;
978 case lsym_binary_op: goto copy_token; 978 case lsym_binary_op: goto copy_token;
979 case lsym_question: ps.quest_level++; goto copy_token; 979 case lsym_question: ps.quest_level++; goto copy_token;
980 case lsym_question_colon: goto copy_token; 980 case lsym_question_colon: goto copy_token;
981 case lsym_label_colon: process_label_colon(); break; 981 case lsym_label_colon: process_label_colon(); break;
982 case lsym_other_colon: process_other_colon(); break; 982 case lsym_other_colon: process_other_colon(); break;
983 case lsym_comma: process_comma(); break; 983 case lsym_comma: process_comma(); break;
984 case lsym_semicolon: process_semicolon(); break; 984 case lsym_semicolon: process_semicolon(); break;
985 case lsym_typedef: goto copy_token; 985 case lsym_typedef: goto copy_token;
986 case lsym_modifier: goto copy_token; 986 case lsym_modifier: goto copy_token;
987 case lsym_case: ps.seen_case = true; goto copy_token; 987 case lsym_case: ps.seen_case = true; goto copy_token;
988 case lsym_default: ps.seen_case = true; goto copy_token; 988 case lsym_default: ps.seen_case = true; goto copy_token;
989 case lsym_do: process_do(); goto copy_token; 989 case lsym_do: process_do(); goto copy_token;
990 case lsym_else: process_else(); goto copy_token; 990 case lsym_else: process_else(); goto copy_token;
991 case lsym_for: ps.spaced_expr_psym = psym_for_exprs; goto copy_token; 991 case lsym_for: ps.spaced_expr_psym = psym_for_exprs; goto copy_token;
992 case lsym_if: ps.spaced_expr_psym = psym_if_expr; goto copy_token; 992 case lsym_if: ps.spaced_expr_psym = psym_if_expr; goto copy_token;
993 case lsym_switch: ps.spaced_expr_psym = psym_switch_expr; goto copy_token; 993 case lsym_switch: ps.spaced_expr_psym = psym_switch_expr; goto copy_token;
994 case lsym_while: ps.spaced_expr_psym = psym_while_expr; goto copy_token; 994 case lsym_while: ps.spaced_expr_psym = psym_while_expr; goto copy_token;
995 /* INDENT ON */ 995 /* INDENT ON */
996 996
997 case lsym_tag: 997 case lsym_tag:
998 if (ps.nparen > 0) 998 if (ps.nparen > 0)
999 goto copy_token; 999 goto copy_token;
1000 /* FALLTHROUGH */ 1000 /* FALLTHROUGH */
1001 case lsym_type_outside_parentheses: 1001 case lsym_type_outside_parentheses:
1002 process_type_outside_parentheses(); 1002 process_type_outside_parentheses();
1003 goto copy_token; 1003 goto copy_token;
1004 1004
1005 case lsym_type_in_parentheses: 1005 case lsym_type_in_parentheses:
1006 case lsym_sizeof: 1006 case lsym_sizeof:
1007 case lsym_offsetof: 1007 case lsym_offsetof:
1008 case lsym_word: 1008 case lsym_word:
1009 case lsym_funcname: 1009 case lsym_funcname:
1010 case lsym_return: 1010 case lsym_return:
1011 process_word(lsym); 1011 process_word(lsym);
1012copy_token: 1012copy_token:
1013 if (ps.want_blank) 1013 if (ps.want_blank)
1014 buf_add_char(&code, ' '); 1014 buf_add_char(&code, ' ');
1015 buf_add_buf(&code, &token); 1015 buf_add_buf(&code, &token);
1016 if (lsym != lsym_funcname) 1016 if (lsym != lsym_funcname)
1017 ps.want_blank = true; 1017 ps.want_blank = true;
1018 break; 1018 break;
1019 1019
1020 default: 1020 default:
1021 break; 1021 break;
1022 } 1022 }
1023} 1023}
1024 1024
1025static int 1025static int
1026indent(void) 1026indent(void)
1027{ 1027{
1028 debug_parser_state(); 1028 debug_parser_state();
1029 1029
1030 for (;;) { /* loop until we reach eof */ 1030 for (;;) { /* loop until we reach eof */
1031 lexer_symbol lsym = lexi(); 1031 lexer_symbol lsym = lexi();
1032 1032
1033 debug_blank_line(); 1033 debug_blank_line();
1034 debug_printf("line %d: %s", line_no, lsym_name[lsym]); 1034 debug_printf("line %d: %s", line_no, lsym_name[lsym]);
1035 debug_print_buf("token", &token); 1035 debug_print_buf("token", &token);
1036 debug_buffers(); 1036 debug_buffers();
1037 debug_blank_line(); 1037 debug_blank_line();
1038 1038
1039 if (lsym == lsym_eof) 1039 if (lsym == lsym_eof)
1040 return process_eof(); 1040 return process_eof();
1041 1041
1042 if (lsym == lsym_if && ps.prev_lsym == lsym_else 1042 if (lsym == lsym_if && ps.prev_lsym == lsym_else
1043 && opt.else_if_in_same_line) 1043 && opt.else_if_in_same_line)
1044 ps.force_nl = false; 1044 ps.force_nl = false;
1045 1045
1046 if (lsym == lsym_preprocessing || lsym == lsym_newline) 1046 if (lsym == lsym_preprocessing || lsym == lsym_newline)
1047 ps.force_nl = false; 1047 ps.force_nl = false;
1048 else if (lsym == lsym_comment) { 1048 else if (lsym == lsym_comment) {
1049 /* no special processing */ 1049 /* no special processing */
1050 } else { 1050 } else {
1051 if (ps.force_nl && should_break_line(lsym)) { 1051 if (ps.force_nl && should_break_line(lsym)) {
1052 ps.force_nl = false; 1052 ps.force_nl = false;
1053 output_line(); 1053 output_line();
1054 } 1054 }
1055 ps.in_stmt_or_decl = true; 1055 ps.in_stmt_or_decl = true;
1056 if (com.len > 0) 1056 if (com.len > 0)
1057 move_com_to_code(lsym); 1057 move_com_to_code(lsym);
1058 update_ps_lbrace_kind(lsym); 1058 update_ps_lbrace_kind(lsym);
1059 } 1059 }
1060 1060
1061 process_lsym(lsym); 1061 process_lsym(lsym);
1062 1062
1063 if (lsym != lsym_preprocessing 1063 if (lsym != lsym_preprocessing
1064 && lsym != lsym_newline 1064 && lsym != lsym_newline
1065 && lsym != lsym_comment) 1065 && lsym != lsym_comment)
1066 ps.prev_lsym = lsym; 1066 ps.prev_lsym = lsym;
1067 1067
1068 debug_parser_state(); 1068 debug_parser_state();
1069 } 1069 }
1070} 1070}
1071 1071
1072int 1072int
1073main(int argc, char **argv) 1073main(int argc, char **argv)
1074{ 1074{
1075 init_globals(); 1075 init_globals();
1076 load_profiles(argc, argv); 1076 load_profiles(argc, argv);
1077 parse_command_line(argc, argv); 1077 parse_command_line(argc, argv);
1078 set_initial_indentation(); 1078 set_initial_indentation();
1079 return indent(); 1079 return indent();
1080} 1080}

cvs diff -r1.187 -r1.188 src/usr.bin/indent/indent.h (switch to unified diff)

--- src/usr.bin/indent/indent.h 2023/06/10 16:43:56 1.187
+++ src/usr.bin/indent/indent.h 2023/06/10 21:36:38 1.188
@@ -1,536 +1,535 @@ @@ -1,536 +1,535 @@
1/* $NetBSD: indent.h,v 1.187 2023/06/10 16:43:56 rillig Exp $ */ 1/* $NetBSD: indent.h,v 1.188 2023/06/10 21:36:38 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
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30/*- 30/*-
31 * SPDX-License-Identifier: BSD-4-Clause 31 * SPDX-License-Identifier: BSD-4-Clause
32 * 32 *
33 * Copyright (c) 1985 Sun Microsystems, Inc. 33 * Copyright (c) 1985 Sun Microsystems, Inc.
34 * Copyright (c) 1980, 1993 34 * Copyright (c) 1980, 1993
35 * The Regents of the University of California. All rights reserved. 35 * The Regents of the University of California. All rights reserved.
36 * All rights reserved. 36 * All rights reserved.
37 * 37 *
38 * Redistribution and use in source and binary forms, with or without 38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions 39 * modification, are permitted provided that the following conditions
40 * are met: 40 * are met:
41 * 1. Redistributions of source code must retain the above copyright 41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer. 42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright 43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the 44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution. 45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software 46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement: 47 * must display the following acknowledgement:
48 * This product includes software developed by the University of 48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors. 49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors 50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software 51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission. 52 * without specific prior written permission.
53 * 53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE. 64 * SUCH DAMAGE.
65 */ 65 */
66 66
67#include <ctype.h> 67#include <ctype.h>
68#include <stdbool.h> 68#include <stdbool.h>
69#include <stdio.h> 69#include <stdio.h>
70 70
71typedef enum lexer_symbol { 71typedef enum lexer_symbol {
72 lsym_eof, 72 lsym_eof,
73 lsym_preprocessing, /* the initial '#' of a preprocessing line */ 73 lsym_preprocessing, /* the initial '#' of a preprocessing line */
74 lsym_newline, 74 lsym_newline,
75 lsym_comment, /* the initial '/ *' or '//' of a comment */ 75 lsym_comment, /* the initial '/ *' or '//' of a comment */
76 76
77 lsym_lparen, 77 lsym_lparen,
78 lsym_rparen, 78 lsym_rparen,
79 lsym_lbracket, 79 lsym_lbracket,
80 lsym_rbracket, 80 lsym_rbracket,
81 lsym_lbrace, 81 lsym_lbrace,
82 lsym_rbrace, 82 lsym_rbrace,
83 83
84 lsym_period, 84 lsym_period,
85 lsym_unary_op, /* e.g. '*', '&', '-' or leading '++' */ 85 lsym_unary_op, /* e.g. '*', '&', '-' or leading '++' */
86 lsym_sizeof, 86 lsym_sizeof,
87 lsym_offsetof, 87 lsym_offsetof,
88 lsym_postfix_op, /* trailing '++' or '--' */ 88 lsym_postfix_op, /* trailing '++' or '--' */
89 lsym_binary_op, /* e.g. '*', '&', '<<', '&&' or '/=' */ 89 lsym_binary_op, /* e.g. '*', '&', '<<', '&&' or '/=' */
90 lsym_question, /* the '?' from a '?:' expression */ 90 lsym_question, /* the '?' from a '?:' expression */
91 lsym_question_colon, /* the ':' from a '?:' expression */ 91 lsym_question_colon, /* the ':' from a '?:' expression */
92 lsym_comma, 92 lsym_comma,
93 93
94 lsym_typedef, 94 lsym_typedef,
95 lsym_modifier, /* modifiers for types, functions, variables */ 95 lsym_modifier, /* modifiers for types, functions, variables */
96 lsym_tag, /* 'struct', 'union' or 'enum' */ 96 lsym_tag, /* 'struct', 'union' or 'enum' */
97 lsym_type_outside_parentheses, 97 lsym_type_outside_parentheses,
98 lsym_type_in_parentheses, 98 lsym_type_in_parentheses,
99 lsym_word, /* identifier, constant or string */ 99 lsym_word, /* identifier, constant or string */
100 lsym_funcname, /* name of a function being defined */ 100 lsym_funcname, /* name of a function being defined */
101 lsym_label_colon, /* the ':' after a label */ 101 lsym_label_colon, /* the ':' after a label */
102 lsym_other_colon, /* bit-fields, generic-association (C11), 102 lsym_other_colon, /* bit-fields, generic-association (C11),
103 * enum-type-specifier (C23), 103 * enum-type-specifier (C23),
104 * attribute-prefixed-token (C23), 104 * attribute-prefixed-token (C23),
105 * pp-prefixed-parameter (C23 6.10) */ 105 * pp-prefixed-parameter (C23 6.10) */
106 lsym_semicolon, 106 lsym_semicolon,
107 107
108 lsym_case, 108 lsym_case,
109 lsym_default, 109 lsym_default,
110 lsym_do, 110 lsym_do,
111 lsym_else, 111 lsym_else,
112 lsym_for, 112 lsym_for,
113 lsym_if, 113 lsym_if,
114 lsym_switch, 114 lsym_switch,
115 lsym_while, 115 lsym_while,
116 lsym_return, 116 lsym_return,
117} lexer_symbol; 117} lexer_symbol;
118 118
119/* 119/*
120 * Structure of the source code, in terms of declarations, statements and 120 * Structure of the source code, in terms of declarations, statements and
121 * braces; used to determine the indentation level of these parts. 121 * braces; used to determine the indentation level of these parts.
122 */ 122 */
123typedef enum parser_symbol { 123typedef enum parser_symbol {
124 psym_0, /* a placeholder; not stored on the stack */ 124 psym_0, /* a placeholder; not stored on the stack */
125 psym_lbrace_block, /* '{' for a block of code */ 125 psym_lbrace_block, /* '{' for a block of code */
126 psym_lbrace_struct, /* '{' in 'struct ... { ... }' */ 126 psym_lbrace_struct, /* '{' in 'struct ... { ... }' */
127 psym_lbrace_union, /* '{' in 'union ... { ... }' */ 127 psym_lbrace_union, /* '{' in 'union ... { ... }' */
128 psym_lbrace_enum, /* '{' in 'enum ... { ... }' */ 128 psym_lbrace_enum, /* '{' in 'enum ... { ... }' */
129 psym_rbrace, /* not stored on the stack */ 129 psym_rbrace, /* not stored on the stack */
130 psym_decl, 130 psym_decl,
131 psym_stmt, 131 psym_stmt,
132 psym_stmt_list, 132 psym_stmt_list,
133 psym_for_exprs, /* 'for' '(' ... ')' */ 133 psym_for_exprs, /* 'for' '(' ... ')' */
134 psym_if_expr, /* 'if' '(' expr ')' */ 134 psym_if_expr, /* 'if' '(' expr ')' */
135 psym_if_expr_stmt, /* 'if' '(' expr ')' stmt */ 135 psym_if_expr_stmt, /* 'if' '(' expr ')' stmt */
136 psym_if_expr_stmt_else, /* 'if' '(' expr ')' stmt 'else' */ 136 psym_if_expr_stmt_else, /* 'if' '(' expr ')' stmt 'else' */
137 psym_else, /* 'else'; not stored on the stack */ 137 psym_else, /* 'else'; not stored on the stack */
138 psym_switch_expr, /* 'switch' '(' expr ')' */ 138 psym_switch_expr, /* 'switch' '(' expr ')' */
139 psym_do, /* 'do' */ 139 psym_do, /* 'do' */
140 psym_do_stmt, /* 'do' stmt */ 140 psym_do_stmt, /* 'do' stmt */
141 psym_while_expr, /* 'while' '(' expr ')' */ 141 psym_while_expr, /* 'while' '(' expr ')' */
142} parser_symbol; 142} parser_symbol;
143 143
144/* A range of characters, only null-terminated in debug mode. */ 144/* A range of characters, only null-terminated in debug mode. */
145struct buffer { 145struct buffer {
146 char *s; 146 char *s;
147 size_t len; 147 size_t len;
148 size_t cap; 148 size_t cap;
149}; 149};
150 150
151extern FILE *input; 151extern FILE *input;
152extern FILE *output; 152extern FILE *output;
153 153
154/* 154/*
155 * The current line from the input file, used by the lexer to generate tokens. 155 * The current line from the input file, used by the lexer to generate tokens.
156 * To read from the line, start at inp_p and continue up to and including the 156 * To read from the line, start at inp_p and continue up to and including the
157 * next '\n'. To read beyond the '\n', call inp_skip or inp_next, which will 157 * next '\n'. To read beyond the '\n', call inp_skip or inp_next, which will
158 * make the next line available, invalidating any pointers into the previous 158 * make the next line available, invalidating any pointers into the previous
159 * line. 159 * line.
160 */ 160 */
161extern struct buffer inp; 161extern struct buffer inp;
162extern const char *inp_p; 162extern const char *inp_p;
163 163
164extern struct buffer token; /* the current token to be processed, is 164extern struct buffer token; /* the current token to be processed, is
165 * typically copied to the buffer 'code', or in 165 * typically copied to the buffer 'code', or in
166 * some cases to 'lab'. */ 166 * some cases to 'lab'. */
167 167
168extern struct buffer lab; /* the label or preprocessor directive */ 168extern struct buffer lab; /* the label or preprocessor directive */
169extern struct buffer code; /* the main part of the current line of code, 169extern struct buffer code; /* the main part of the current line of code,
170 * containing declarations or statements */ 170 * containing declarations or statements */
171extern struct buffer com; /* the trailing comment of the line, or the 171extern struct buffer com; /* the trailing comment of the line, or the
172 * start or end of a multi-line comment, or 172 * start or end of a multi-line comment, or
173 * while in process_comment, a single line of a 173 * while in process_comment, a single line of a
174 * multi-line comment */ 174 * multi-line comment */
175 175
176extern struct options { 176extern struct options {
177 bool blank_line_around_conditional_compilation; 177 bool blank_line_around_conditional_compilation;
178 bool blank_line_after_decl_at_top; /* this is vaguely similar to 178 bool blank_line_after_decl_at_top; /* this is vaguely similar to
179 * blank_line_after_decl except 179 * blank_line_after_decl except
180 * that it only applies to the 180 * that it only applies to the
181 * first set of declarations in 181 * first set of declarations in
182 * a procedure (just after the 182 * a procedure (just after the
183 * first '{') and it causes a 183 * first '{') and it causes a
184 * blank line to be generated 184 * blank line to be generated
185 * even if there are no 185 * even if there are no
186 * declarations */ 186 * declarations */
187 bool blank_line_after_decl; 187 bool blank_line_after_decl;
188 bool blank_line_after_proc; 188 bool blank_line_after_proc;
189 bool blank_line_before_block_comment; 189 bool blank_line_before_block_comment;
190 bool break_after_comma; /* whether to add a line break after each 190 bool break_after_comma; /* whether to add a line break after each
191 * declarator */ 191 * declarator */
192 bool brace_same_line; /* whether a brace should be on same line as an 192 bool brace_same_line; /* whether a brace should be on same line as an
193 * if, while, etc. */ 193 * if, while, etc. */
194 bool blank_after_sizeof; 194 bool blank_after_sizeof;
195 bool comment_delimiter_on_blank_line; 195 bool comment_delimiter_on_blank_line;
196 int decl_comment_column; /* the column in which comments after 196 int decl_comment_column; /* the column in which comments after
197 * declarations should be put */ 197 * declarations should be put */
198 bool cuddle_else; /* whether 'else' should cuddle up to '}' */ 198 bool cuddle_else; /* whether 'else' should cuddle up to '}' */
199 int continuation_indent; /* the indentation between the edge of 199 int continuation_indent; /* the indentation between the edge of
200 * code and continuation lines */ 200 * code and continuation lines */
201 float case_indent; /* the distance (measured in indentation 201 float case_indent; /* the distance (measured in indentation
202 * levels) to indent case labels from the 202 * levels) to indent case labels from the
203 * switch statement */ 203 * switch statement */
204 int comment_column; /* the column in which comments to the right of 204 int comment_column; /* the column in which comments to the right of
205 * code should start */ 205 * code should start */
206 int decl_indent; /* indentation of identifier in declaration */ 206 int decl_indent; /* indentation of identifier in declaration */
207 bool left_justify_decl; 207 bool left_justify_decl;
208 int unindent_displace; /* comments not to the right of code will be 208 int unindent_displace; /* comments not to the right of code will be
209 * placed this many indentation levels to the 209 * placed this many indentation levels to the
210 * left of code */ 210 * left of code */
211 bool extra_expr_indent; /* whether continuation lines from the 211 bool extra_expr_indent; /* whether continuation lines from the
212 * expression part of "if (e)", "while (e)", 212 * expression part of "if (e)", "while (e)",
213 * "for (e; e; e)" should be indented an extra 213 * "for (e; e; e)" should be indented an extra
214 * tab stop so that they are not confused with 214 * tab stop so that they are not confused with
215 * the code that follows */ 215 * the code that follows */
216 bool else_if_in_same_line; 216 bool else_if_in_same_line;
217 bool function_brace_split; /* split function declaration and brace 217 bool function_brace_split; /* split function declaration and brace
218 * onto separate lines */ 218 * onto separate lines */
219 bool format_col1_comments; /* whether comments that start in 219 bool format_col1_comments; /* whether comments that start in
220 * column 1 are to be reformatted (just 220 * column 1 are to be reformatted (just
221 * like comments that begin in later 221 * like comments that begin in later
222 * columns) */ 222 * columns) */
223 bool format_block_comments; /* whether to reformat comments that 223 bool format_block_comments; /* whether to reformat comments that
224 * begin with '/ * \n' */ 224 * begin with '/ * \n' */
225 bool indent_parameters; 225 bool indent_parameters;
226 int indent_size; /* the size of one indentation level */ 226 int indent_size; /* the size of one indentation level */
227 int block_comment_max_line_length; 227 int block_comment_max_line_length;
228 int local_decl_indent; /* like decl_indent but for locals */ 228 int local_decl_indent; /* like decl_indent but for locals */
229 bool lineup_to_parens_always; /* whether to not(?) attempt to keep 229 bool lineup_to_parens_always; /* whether to not(?) attempt to keep
230 * lined-up code within the margin */ 230 * lined-up code within the margin */
231 bool lineup_to_parens; /* whether continued code within parens will be 231 bool lineup_to_parens; /* whether continued code within parens will be
232 * lined up to the open paren */ 232 * lined up to the open paren */
233 bool proc_calls_space; /* whether function calls look like: foo (bar) 233 bool proc_calls_space; /* whether function calls look like: foo (bar)
234 * rather than foo(bar) */ 234 * rather than foo(bar) */
235 bool procnames_start_line; /* whether the names of functions being 235 bool procnames_start_line; /* whether the names of functions being
236 * defined get placed in column 1 (i.e. 236 * defined get placed in column 1 (i.e.
237 * a newline is placed between the type 237 * a newline is placed between the type
238 * of the function and its name) */ 238 * of the function and its name) */
239 bool space_after_cast; /* "b = (int) a" vs. "b = (int)a" */ 239 bool space_after_cast; /* "b = (int) a" vs. "b = (int)a" */
240 bool star_comment_cont; /* whether comment continuation lines should 240 bool star_comment_cont; /* whether comment continuation lines should
241 * have stars at the beginning of each line */ 241 * have stars at the beginning of each line */
242 bool swallow_optional_blank_lines; 242 bool swallow_optional_blank_lines;
243 bool auto_typedefs; /* whether to recognize identifiers ending in 243 bool auto_typedefs; /* whether to recognize identifiers ending in
244 * "_t" like typedefs */ 244 * "_t" like typedefs */
245 int tabsize; /* the size of a tab */ 245 int tabsize; /* the size of a tab */
246 int max_line_length; 246 int max_line_length;
247 bool use_tabs; /* set true to use tabs for spacing, false uses 247 bool use_tabs; /* set true to use tabs for spacing, false uses
248 * all spaces */ 248 * all spaces */
249 bool verbose; /* print configuration to stderr */ 249 bool verbose; /* print configuration to stderr */
250} opt; 250} opt;
251 251
252extern bool found_err; 252extern bool found_err;
253extern bool had_eof; /* whether input is exhausted */ 253extern bool had_eof; /* whether input is exhausted */
254extern int line_no; /* the current input line number */ 254extern int line_no; /* the current input line number */
255extern enum indent_enabled { 255extern enum indent_enabled {
256 indent_on, 256 indent_on,
257 indent_off, 257 indent_off,
258 indent_last_off_line, 258 indent_last_off_line,
259} indent_enabled; 259} indent_enabled;
260 260
261#define STACKSIZE 256 261#define STACKSIZE 256
262 262
263/* Properties of each level of parentheses or brackets. */ 263/* Properties of each level of parentheses or brackets. */
264struct paren_level { 264struct paren_level {
265 int indent; /* indentation of the operand/argument, 265 int indent; /* indentation of the operand/argument,
266 * relative to the enclosing statement; if 266 * relative to the enclosing statement; if
267 * negative, reflected at -1 */ 267 * negative, reflected at -1 */
268 enum paren_level_cast { 268 enum paren_level_cast {
269 cast_unknown, 269 cast_unknown,
270 cast_maybe, 270 cast_maybe,
271 cast_no, 271 cast_no,
272 } cast; /* whether the parentheses form a type cast */ 272 } cast; /* whether the parentheses form a type cast */
273}; 273};
274 274
275struct psym_stack { 275struct psym_stack {
276 int top; /* pointer to top of stack */ 276 int top; /* pointer to top of stack */
277 parser_symbol sym[STACKSIZE]; 277 parser_symbol sym[STACKSIZE];
278 int ind_level[STACKSIZE]; 278 int ind_level[STACKSIZE];
279}; 279};
280 280
281/* 281/*
282 * The parser state determines the layout of the formatted text. 282 * The parser state determines the layout of the formatted text.
283 * 283 *
284 * At each '#if', the parser state is copied so that the corresponding '#else' 284 * At each '#if', the parser state is copied so that the corresponding '#else'
285 * lines start in the same state. 285 * lines start in the same state.
286 * 286 *
287 * In a function body, the number of block braces determines the indentation 287 * In a function body, the number of block braces determines the indentation
288 * of statements and declarations. 288 * of statements and declarations.
289 * 289 *
290 * In a statement, the number of parentheses or brackets determines the 290 * In a statement, the number of parentheses or brackets determines the
291 * indentation of follow-up lines. 291 * indentation of follow-up lines.
292 * 292 *
293 * In an expression, the token type determine whether to put spaces around. 293 * In an expression, the token type determine whether to put spaces around.
294 * 294 *
295 * In a source file, the types of line determine the vertical spacing, such as 295 * In a source file, the types of line determine the vertical spacing, such as
296 * around preprocessing directives or function bodies, or above block 296 * around preprocessing directives or function bodies, or above block
297 * comments. 297 * comments.
298 */ 298 */
299extern struct parser_state { 299extern struct parser_state {
300 lexer_symbol prev_lsym; /* the previous token, but never comment, 300 lexer_symbol prev_lsym; /* the previous token, but never comment,
301 * newline or preprocessing line */ 301 * newline or preprocessing line */
302 302
303 /* Token classification */ 303 /* Token classification */
304 304
305 bool in_stmt_or_decl; /* whether in a statement or a struct 305 bool in_stmt_or_decl; /* whether in a statement or a struct
306 * declaration or a plain declaration */ 306 * declaration or a plain declaration */
307 bool in_decl; /* XXX: double-check the exact meaning */ 307 bool in_decl; /* XXX: double-check the exact meaning */
308 bool in_var_decl; /* starts at a type name or a '){' from a 308 bool in_var_decl; /* starts at a type name or a '){' from a
309 * compound literal; ends at the '(' from a 309 * compound literal; ends at the '(' from a
310 * function definition or a ';' outside '{}'; 310 * function definition or a ';' outside '{}';
311 * when active, '{}' form struct or union 311 * when active, '{}' form struct or union
312 * declarations, ':' marks a bit-field, and '=' 312 * declarations, ':' marks a bit-field, and '='
313 * starts an initializer */ 313 * starts an initializer */
314 bool in_init; /* whether inside an initializer */ 314 bool in_init; /* whether inside an initializer */
315 int init_level; /* the number of '{}' in an initializer */ 315 int init_level; /* the number of '{}' in an initializer */
316 bool line_has_func_def; /* starts either at the 'name(' from a function 316 bool line_has_func_def; /* starts either at the 'name(' from a function
317 * definition if it occurs at the beginning of 317 * definition if it occurs at the beginning of
318 * a line, or at the first '*' from inside a 318 * a line, or at the first '*' from inside a
319 * declaration when the line starts with words 319 * declaration when the line starts with words
320 * followed by a '(' */ 320 * followed by a '(' */
321 bool in_func_def_params; /* for old-style functions */ 321 bool in_func_def_params; /* for old-style functions */
322 bool line_has_decl; /* whether this line of code has part of a 322 bool line_has_decl; /* whether this line of code has part of a
323 * declaration on it; used for indenting 323 * declaration on it; used for indenting
324 * comments */ 324 * comments */
325 parser_symbol lbrace_kind; /* the kind of brace to be pushed to 325 parser_symbol lbrace_kind; /* the kind of brace to be pushed to
326 * the parser symbol stack next */ 326 * the parser symbol stack next */
327 parser_symbol spaced_expr_psym; /* the parser symbol to be shifted 327 parser_symbol spaced_expr_psym; /* the parser symbol to be shifted
328 * after the parenthesized expression 328 * after the parenthesized expression
329 * from a 'for', 'if', 'switch' or 329 * from a 'for', 'if', 'switch' or
330 * 'while'; or psym_0 */ 330 * 'while'; or psym_0 */
331 bool seen_case; /* whether there was a 'case' or 'default', to 331 bool seen_case; /* whether there was a 'case' or 'default', to
332 * properly space the following ':' */ 332 * properly space the following ':' */
333 bool prev_paren_was_cast; 333 bool prev_paren_was_cast;
334 int quest_level; /* when this is positive, we have seen a '?' 334 int quest_level; /* when this is positive, we have seen a '?'
335 * without the matching ':' in a '?:' 335 * without the matching ':' in a '?:'
336 * expression */ 336 * expression */
337 337
338 /* Indentation of statements and declarations */ 338 /* Indentation of statements and declarations */
339 339
340 int ind_level; /* the indentation level for the line that is 340 int ind_level; /* the indentation level for the line that is
341 * currently prepared for output */ 341 * currently prepared for output */
342 int ind_level_follow; /* the level to which ind_level should be set 342 int ind_level_follow; /* the level to which ind_level should be set
343 * after the current line is printed */ 343 * after the current line is printed */
344 bool in_stmt_cont; /* whether the current line should have an 344 bool in_stmt_cont; /* whether the current line should have an
345 * extra indentation level because we are in 345 * extra indentation level because we are in
346 * the middle of a statement */ 346 * the middle of a statement */
347 int decl_level; /* current nesting level for a structure 347 int decl_level; /* current nesting level for a structure
348 * declaration or an initializer */ 348 * declaration or an initializer */
349 int di_stack[20]; /* a stack of structure indentation levels */ 349 int di_stack[20]; /* a stack of structure indentation levels */
350 bool decl_indent_done; /* whether the indentation for a declaration 350 bool decl_indent_done; /* whether the indentation for a declaration
351 * has been added to the code buffer. */ 351 * has been added to the code buffer. */
352 int decl_ind; /* current indentation for declarations */ 352 int decl_ind; /* current indentation for declarations */
353 bool tabs_to_var; /* true if using tabs to indent to var name */ 353 bool tabs_to_var; /* true if using tabs to indent to var name */
354 354
355 enum { 355 enum {
356 eei_no, 356 eei_no,
357 eei_maybe, 357 eei_maybe,
358 eei_last 358 eei_last
359 } extra_expr_indent; 359 } extra_expr_indent;
360 360
361 struct psym_stack psyms; 361 struct psym_stack psyms;
362 362
363 /* Spacing inside a statement or declaration */ 363 /* Spacing inside a statement or declaration */
364 364
365 bool next_unary; /* whether the following operator should be 365 bool next_unary; /* whether the following operator should be
366 * unary; is used in declarations for '*', as 366 * unary; is used in declarations for '*', as
367 * well as in expressions */ 367 * well as in expressions */
368 bool want_blank; /* whether the following token should be 368 bool want_blank; /* whether the following token should be
369 * prefixed by a blank. (Said prefixing is 369 * prefixed by a blank. (Said prefixing is
370 * ignored in some cases.) */ 370 * ignored in some cases.) */
371 int line_start_nparen; /* the number of parentheses or brackets that 371 int ind_paren_level; /* the number of parentheses or brackets that
372 * were open at the beginning of the current 372 * is used for indenting a continuation line of
373 * line; used to indent within statements, 373 * a declaration, initializer or statement */
374 * initializers and declarations */ 
375 int nparen; /* the number of parentheses or brackets that 374 int nparen; /* the number of parentheses or brackets that
376 * are currently open; used to indent the 375 * are currently open; used to indent the
377 * remaining lines of the statement, 376 * remaining lines of the statement,
378 * initializer or declaration */ 377 * initializer or declaration */
379 struct paren_level paren[20]; 378 struct paren_level paren[20];
380 379
381 /* Horizontal spacing for comments */ 380 /* Horizontal spacing for comments */
382 381
383 int comment_delta; /* used to set up indentation for all lines of 382 int comment_delta; /* used to set up indentation for all lines of
384 * a boxed comment after the first one */ 383 * a boxed comment after the first one */
385 int n_comment_delta; /* remembers how many columns there were before 384 int n_comment_delta; /* remembers how many columns there were before
386 * the start of a box comment so that 385 * the start of a box comment so that
387 * forthcoming lines of the comment are 386 * forthcoming lines of the comment are
388 * indented properly */ 387 * indented properly */
389 int com_ind; /* indentation of the current comment */ 388 int com_ind; /* indentation of the current comment */
390 389
391 /* Vertical spacing */ 390 /* Vertical spacing */
392 391
393 bool break_after_comma; /* whether to add a newline after the next 392 bool break_after_comma; /* whether to add a newline after the next
394 * comma; used in declarations but not in 393 * comma; used in declarations but not in
395 * initializer lists */ 394 * initializer lists */
396 bool force_nl; /* whether the next token is forced to go to a 395 bool force_nl; /* whether the next token is forced to go to a
397 * new line; used after 'if (expr)' and in 396 * new line; used after 'if (expr)' and in
398 * similar situations; tokens like '{' may 397 * similar situations; tokens like '{' may
399 * ignore this */ 398 * ignore this */
400 399
401 enum declaration { 400 enum declaration {
402 decl_no, /* no declaration anywhere nearby */ 401 decl_no, /* no declaration anywhere nearby */
403 decl_begin, /* collecting tokens of a declaration */ 402 decl_begin, /* collecting tokens of a declaration */
404 decl_end, /* finished a declaration */ 403 decl_end, /* finished a declaration */
405 } declaration; 404 } declaration;
406 bool blank_line_after_decl; 405 bool blank_line_after_decl;
407 406
408 /* Comments */ 407 /* Comments */
409 408
410 bool curr_col_1; /* whether the current token started in column 409 bool curr_col_1; /* whether the current token started in column
411 * 1 of the original input */ 410 * 1 of the original input */
412 bool next_col_1; 411 bool next_col_1;
413} ps; 412} ps;
414 413
415extern struct output_state { 414extern struct output_state {
416 enum line_kind { 415 enum line_kind {
417 lk_other, 416 lk_other,
418 lk_blank, 417 lk_blank,
419 lk_if, /* #if, #ifdef, #ifndef */ 418 lk_if, /* #if, #ifdef, #ifndef */
420 lk_endif, /* #endif */ 419 lk_endif, /* #endif */
421 lk_stmt_head, /* the ')' of an incomplete statement such as 420 lk_stmt_head, /* the ')' of an incomplete statement such as
422 * 'if (expr)' or 'for (expr; expr; expr)' */ 421 * 'if (expr)' or 'for (expr; expr; expr)' */
423 lk_func_end, /* the last '}' of a function body */ 422 lk_func_end, /* the last '}' of a function body */
424 lk_block_comment, 423 lk_block_comment,
425 lk_case_or_default, 424 lk_case_or_default,
426 } line_kind; /* kind of the line that is being prepared for 425 } line_kind; /* kind of the line that is being prepared for
427 * output; is reset to lk_other each time after 426 * output; is reset to lk_other each time after
428 * trying to send a line to the output, even if 427 * trying to send a line to the output, even if
429 * that line was a suppressed blank line; used 428 * that line was a suppressed blank line; used
430 * for inserting or removing blank lines */ 429 * for inserting or removing blank lines */
431 enum line_kind prev_line_kind; /* the kind of line that was actually 430 enum line_kind prev_line_kind; /* the kind of line that was actually
432 * sent to the output */ 431 * sent to the output */
433 432
434 struct buffer indent_off_text; /* text from between 'INDENT OFF' and 433 struct buffer indent_off_text; /* text from between 'INDENT OFF' and
435 * 'INDENT ON', both inclusive */ 434 * 'INDENT ON', both inclusive */
436} out; 435} out;
437 436
438 437
439#define array_length(array) (sizeof(array) / sizeof((array)[0])) 438#define array_length(array) (sizeof(array) / sizeof((array)[0]))
440 439
441#ifdef debug 440#ifdef debug
442void debug_printf(const char *, ...) __printflike(1, 2); 441void debug_printf(const char *, ...) __printflike(1, 2);
443void debug_println(const char *, ...) __printflike(1, 2); 442void debug_println(const char *, ...) __printflike(1, 2);
444void debug_blank_line(void); 443void debug_blank_line(void);
445void debug_vis_range(const char *, const char *, size_t, const char *); 444void debug_vis_range(const char *, const char *, size_t, const char *);
446void debug_parser_state(void); 445void debug_parser_state(void);
447void debug_psyms_stack(const char *); 446void debug_psyms_stack(const char *);
448void debug_print_buf(const char *, const struct buffer *); 447void debug_print_buf(const char *, const struct buffer *);
449void debug_buffers(void); 448void debug_buffers(void);
450extern const char *const lsym_name[]; 449extern const char *const lsym_name[];
451extern const char *const psym_name[]; 450extern const char *const psym_name[];
452extern const char *const paren_level_cast_name[]; 451extern const char *const paren_level_cast_name[];
453extern const char *const line_kind_name[]; 452extern const char *const line_kind_name[];
454#else 453#else
455#define debug_noop() do { } while (false) 454#define debug_noop() do { } while (false)
456#define debug_printf(fmt, ...) debug_noop() 455#define debug_printf(fmt, ...) debug_noop()
457#define debug_println(fmt, ...) debug_noop() 456#define debug_println(fmt, ...) debug_noop()
458#define debug_blank_line() debug_noop() 457#define debug_blank_line() debug_noop()
459#define debug_vis_range(prefix, s, e, suffix) debug_noop() 458#define debug_vis_range(prefix, s, e, suffix) debug_noop()
460#define debug_parser_state() debug_noop() 459#define debug_parser_state() debug_noop()
461#define debug_psyms_stack(situation) debug_noop() 460#define debug_psyms_stack(situation) debug_noop()
462#define debug_print_buf(name, buf) debug_noop() 461#define debug_print_buf(name, buf) debug_noop()
463#define debug_buffers() debug_noop() 462#define debug_buffers() debug_noop()
464#endif 463#endif
465 464
466void register_typename(const char *); 465void register_typename(const char *);
467int compute_code_indent(void); 466int compute_code_indent(void);
468int compute_label_indent(void); 467int compute_label_indent(void);
469int ind_add(int, const char *, size_t); 468int ind_add(int, const char *, size_t);
470 469
471void inp_skip(void); 470void inp_skip(void);
472char inp_next(void); 471char inp_next(void);
473void finish_output(void); 472void finish_output(void);
474 473
475lexer_symbol lexi(void); 474lexer_symbol lexi(void);
476void diag(int, const char *, ...) __printflike(2, 3); 475void diag(int, const char *, ...) __printflike(2, 3);
477void output_line(void); 476void output_line(void);
478void inp_read_line(void); 477void inp_read_line(void);
479void parse(parser_symbol); 478void parse(parser_symbol);
480void process_comment(void); 479void process_comment(void);
481void set_option(const char *, const char *); 480void set_option(const char *, const char *);
482void load_profile_files(const char *); 481void load_profile_files(const char *);
483 482
484void *nonnull(void *); 483void *nonnull(void *);
485 484
486void buf_add_char(struct buffer *, char); 485void buf_add_char(struct buffer *, char);
487void buf_add_chars(struct buffer *, const char *, size_t); 486void buf_add_chars(struct buffer *, const char *, size_t);
488 487
489static inline bool 488static inline bool
490ch_isalnum(char ch) 489ch_isalnum(char ch)
491{ 490{
492 return isalnum((unsigned char)ch) != 0; 491 return isalnum((unsigned char)ch) != 0;
493} 492}
494 493
495static inline bool 494static inline bool
496ch_isalpha(char ch) 495ch_isalpha(char ch)
497{ 496{
498 return isalpha((unsigned char)ch) != 0; 497 return isalpha((unsigned char)ch) != 0;
499} 498}
500 499
501static inline bool 500static inline bool
502ch_isblank(char ch) 501ch_isblank(char ch)
503{ 502{
504 return ch == ' ' || ch == '\t'; 503 return ch == ' ' || ch == '\t';
505} 504}
506 505
507static inline bool 506static inline bool
508ch_isdigit(char ch) 507ch_isdigit(char ch)
509{ 508{
510 return '0' <= ch && ch <= '9'; 509 return '0' <= ch && ch <= '9';
511} 510}
512 511
513static inline bool 512static inline bool
514ch_isspace(char ch) 513ch_isspace(char ch)
515{ 514{
516 return isspace((unsigned char)ch) != 0; 515 return isspace((unsigned char)ch) != 0;
517} 516}
518 517
519static inline int 518static inline int
520next_tab(int ind) 519next_tab(int ind)
521{ 520{
522 return ind - ind % opt.tabsize + opt.tabsize; 521 return ind - ind % opt.tabsize + opt.tabsize;
523} 522}
524 523
525#ifdef debug 524#ifdef debug
526void buf_terminate(struct buffer *); 525void buf_terminate(struct buffer *);
527#else 526#else
528#define buf_terminate(buf) debug_noop() 527#define buf_terminate(buf) debug_noop()
529#endif 528#endif
530 529
531static inline void 530static inline void
532buf_clear(struct buffer *buf) 531buf_clear(struct buffer *buf)
533{ 532{
534 buf->len = 0; 533 buf->len = 0;
535 buf_terminate(buf); 534 buf_terminate(buf);
536} 535}

cvs diff -r1.216 -r1.217 src/usr.bin/indent/io.c (switch to unified diff)

--- src/usr.bin/indent/io.c 2023/06/10 16:43:56 1.216
+++ src/usr.bin/indent/io.c 2023/06/10 21:36:38 1.217
@@ -1,421 +1,421 @@ @@ -1,421 +1,421 @@
1/* $NetBSD: io.c,v 1.216 2023/06/10 16:43:56 rillig Exp $ */ 1/* $NetBSD: io.c,v 1.217 2023/06/10 21:36:38 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.216 2023/06/10 16:43:56 rillig Exp $"); 41__RCSID("$NetBSD: io.c,v 1.217 2023/06/10 21:36:38 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 newlines = 2; /* the total of written and buffered newlines; 53static unsigned newlines = 2; /* the total of written and buffered newlines;
54 * 0 in the middle of a line, 1 after a single 54 * 0 in the middle of a line, 1 after a single
55 * finished line, anything > 1 are trailing 55 * finished line, anything > 1 are trailing
56 * blank lines */ 56 * blank lines */
57static unsigned buffered_newlines; /* not yet written */ 57static unsigned buffered_newlines; /* not yet written */
58static int paren_indent; 58static int paren_indent;
59 59
60 60
61static void 61static void
62inp_read_next_line(FILE *f) 62inp_read_next_line(FILE *f)
63{ 63{
64 buf_clear(&inp); 64 buf_clear(&inp);
65 65
66 for (;;) { 66 for (;;) {
67 int ch = getc(f); 67 int ch = getc(f);
68 if (ch == EOF) { 68 if (ch == EOF) {
69 if (indent_enabled == indent_on) { 69 if (indent_enabled == indent_on) {
70 buf_add_char(&inp, ' '); 70 buf_add_char(&inp, ' ');
71 buf_add_char(&inp, '\n'); 71 buf_add_char(&inp, '\n');
72 } 72 }
73 had_eof = true; 73 had_eof = true;
74 break; 74 break;
75 } 75 }
76 76
77 if (ch != '\0') 77 if (ch != '\0')
78 buf_add_char(&inp, (char)ch); 78 buf_add_char(&inp, (char)ch);
79 if (ch == '\n') 79 if (ch == '\n')
80 break; 80 break;
81 } 81 }
82 buf_terminate(&inp); 82 buf_terminate(&inp);
83 inp_p = inp.s; 83 inp_p = inp.s;
84} 84}
85 85
86void 86void
87inp_read_line(void) 87inp_read_line(void)
88{ 88{
89 if (indent_enabled == indent_on) 89 if (indent_enabled == indent_on)
90 buf_clear(&out.indent_off_text); 90 buf_clear(&out.indent_off_text);
91 buf_add_chars(&out.indent_off_text, inp.s, inp.len); 91 buf_add_chars(&out.indent_off_text, inp.s, inp.len);
92 inp_read_next_line(input); 92 inp_read_next_line(input);
93} 93}
94 94
95void 95void
96inp_skip(void) 96inp_skip(void)
97{ 97{
98 inp_p++; 98 inp_p++;
99 if ((size_t)(inp_p - inp.s) >= inp.len) 99 if ((size_t)(inp_p - inp.s) >= inp.len)
100 inp_read_line(); 100 inp_read_line();
101} 101}
102 102
103char 103char
104inp_next(void) 104inp_next(void)
105{ 105{
106 char ch = inp_p[0]; 106 char ch = inp_p[0];
107 inp_skip(); 107 inp_skip();
108 return ch; 108 return ch;
109} 109}
110 110
111 111
112static void 112static void
113add_buffered_newline(void) 113add_buffered_newline(void)
114{ 114{
115 buffered_newlines++; 115 buffered_newlines++;
116 newlines++; 116 newlines++;
117 out_ind = 0; 117 out_ind = 0;
118} 118}
119 119
120static void 120static void
121write_buffered_newlines(void) 121write_buffered_newlines(void)
122{ 122{
123 for (; buffered_newlines > 0; buffered_newlines--) { 123 for (; buffered_newlines > 0; buffered_newlines--) {
124 fputc('\n', output); 124 fputc('\n', output);
125 debug_println("write_newline"); 125 debug_println("write_newline");
126 } 126 }
127} 127}
128 128
129static void 129static void
130write_range(const char *s, size_t len) 130write_range(const char *s, size_t len)
131{ 131{
132 write_buffered_newlines(); 132 write_buffered_newlines();
133 fwrite(s, 1, len, output); 133 fwrite(s, 1, len, output);
134 debug_vis_range("write_range \"", s, len, "\"\n"); 134 debug_vis_range("write_range \"", s, len, "\"\n");
135 for (size_t i = 0; i < len; i++) 135 for (size_t i = 0; i < len; i++)
136 newlines = s[i] == '\n' ? newlines + 1 : 0; 136 newlines = s[i] == '\n' ? newlines + 1 : 0;
137 out_ind = ind_add(out_ind, s, len); 137 out_ind = ind_add(out_ind, s, len);
138} 138}
139 139
140static void 140static void
141write_indent(int new_ind) 141write_indent(int new_ind)
142{ 142{
143 write_buffered_newlines(); 143 write_buffered_newlines();
144 144
145 int ind = out_ind; 145 int ind = out_ind;
146 146
147 if (opt.use_tabs) { 147 if (opt.use_tabs) {
148 int n = new_ind / opt.tabsize - ind / opt.tabsize; 148 int n = new_ind / opt.tabsize - ind / opt.tabsize;
149 if (n > 0) { 149 if (n > 0) {
150 ind = ind - ind % opt.tabsize + n * opt.tabsize; 150 ind = ind - ind % opt.tabsize + n * opt.tabsize;
151 while (n-- > 0) 151 while (n-- > 0)
152 fputc('\t', output); 152 fputc('\t', output);
153 newlines = 0; 153 newlines = 0;
154 } 154 }
155 } 155 }
156 156
157 for (; ind < new_ind; ind++) { 157 for (; ind < new_ind; ind++) {
158 fputc(' ', output); 158 fputc(' ', output);
159 newlines = 0; 159 newlines = 0;
160 } 160 }
161 161
162 debug_println("write_indent %d", ind); 162 debug_println("write_indent %d", ind);
163 out_ind = ind; 163 out_ind = ind;
164} 164}
165 165
166static bool 166static bool
167want_blank_line(void) 167want_blank_line(void)
168{ 168{
169 debug_println("%s: %s -> %s", __func__, 169 debug_println("%s: %s -> %s", __func__,
170 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]); 170 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]);
171 171
172 if (ps.blank_line_after_decl && ps.declaration == decl_no) { 172 if (ps.blank_line_after_decl && ps.declaration == decl_no) {
173 ps.blank_line_after_decl = false; 173 ps.blank_line_after_decl = false;
174 return true; 174 return true;
175 } 175 }
176 if (opt.blank_line_around_conditional_compilation) { 176 if (opt.blank_line_around_conditional_compilation) {
177 if (out.prev_line_kind != lk_if && out.line_kind == lk_if) 177 if (out.prev_line_kind != lk_if && out.line_kind == lk_if)
178 return true; 178 return true;
179 if (out.prev_line_kind == lk_endif 179 if (out.prev_line_kind == lk_endif
180 && out.line_kind != lk_endif) 180 && out.line_kind != lk_endif)
181 return true; 181 return true;
182 } 182 }
183 if (opt.blank_line_after_proc && out.prev_line_kind == lk_func_end 183 if (opt.blank_line_after_proc && out.prev_line_kind == lk_func_end
184 && out.line_kind != lk_endif) 184 && out.line_kind != lk_endif)
185 return true; 185 return true;
186 if (opt.blank_line_before_block_comment 186 if (opt.blank_line_before_block_comment
187 && out.line_kind == lk_block_comment) 187 && out.line_kind == lk_block_comment)
188 return true; 188 return true;
189 return false; 189 return false;
190} 190}
191 191
192static bool 192static bool
193is_blank_line_optional(void) 193is_blank_line_optional(void)
194{ 194{
195 if (out.prev_line_kind == lk_stmt_head) 195 if (out.prev_line_kind == lk_stmt_head)
196 return newlines >= 1; 196 return newlines >= 1;
197 if (ps.psyms.top >= 2) 197 if (ps.psyms.top >= 2)
198 return newlines >= 2; 198 return newlines >= 2;
199 return newlines >= 3; 199 return newlines >= 3;
200} 200}
201 201
202static int 202static int
203compute_case_label_indent(void) 203compute_case_label_indent(void)
204{ 204{
205 int i = ps.psyms.top; 205 int i = ps.psyms.top;
206 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr) 206 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr)
207 i--; 207 i--;
208 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent; 208 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent;
209 return (int)(case_ind * (float)opt.indent_size); 209 return (int)(case_ind * (float)opt.indent_size);
210} 210}
211 211
212int 212int
213compute_label_indent(void) 213compute_label_indent(void)
214{ 214{
215 if (out.line_kind == lk_case_or_default) 215 if (out.line_kind == lk_case_or_default)
216 return compute_case_label_indent(); 216 return compute_case_label_indent();
217 if (lab.s[0] == '#') 217 if (lab.s[0] == '#')
218 return 0; 218 return 0;
219 return opt.indent_size * (ps.ind_level - 2); 219 return opt.indent_size * (ps.ind_level - 2);
220} 220}
221 221
222static void 222static void
223output_line_label(void) 223output_line_label(void)
224{ 224{
225 write_indent(compute_label_indent()); 225 write_indent(compute_label_indent());
226 write_range(lab.s, lab.len); 226 write_range(lab.s, lab.len);
227} 227}
228 228
229static int 229static int
230compute_lined_up_code_indent(int base_ind) 230compute_lined_up_code_indent(int base_ind)
231{ 231{
232 int ind = paren_indent; 232 int ind = paren_indent;
233 int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; 233 int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length;
234 if (overflow >= 0 234 if (overflow >= 0
235 && ind_add(base_ind, code.s, code.len) < opt.max_line_length) { 235 && ind_add(base_ind, code.s, code.len) < opt.max_line_length) {
236 ind -= overflow + 2; 236 ind -= overflow + 2;
237 if (ind < base_ind) 237 if (ind < base_ind)
238 ind = base_ind; 238 ind = base_ind;
239 } 239 }
240 240
241 if (ps.extra_expr_indent != eei_no 241 if (ps.extra_expr_indent != eei_no
242 && ind == base_ind + opt.indent_size) 242 && ind == base_ind + opt.indent_size)
243 ind += opt.continuation_indent; 243 ind += opt.continuation_indent;
244 return ind; 244 return ind;
245} 245}
246 246
247int 247int
248compute_code_indent(void) 248compute_code_indent(void)
249{ 249{
250 int base_ind = ps.ind_level * opt.indent_size; 250 int base_ind = ps.ind_level * opt.indent_size;
251 251
252 if (ps.line_start_nparen == 0) { 252 if (ps.ind_paren_level == 0) {
253 if (ps.psyms.top >= 1 253 if (ps.psyms.top >= 1
254 && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum) 254 && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum)
255 return base_ind; 255 return base_ind;
256 if (ps.in_stmt_cont) 256 if (ps.in_stmt_cont)
257 return base_ind + opt.continuation_indent; 257 return base_ind + opt.continuation_indent;
258 return base_ind; 258 return base_ind;
259 } 259 }
260 260
261 if (opt.lineup_to_parens) { 261 if (opt.lineup_to_parens) {
262 if (opt.lineup_to_parens_always) 262 if (opt.lineup_to_parens_always)
263 return paren_indent; 263 return paren_indent;
264 return compute_lined_up_code_indent(base_ind); 264 return compute_lined_up_code_indent(base_ind);
265 } 265 }
266 266
267 int rel_ind = opt.continuation_indent * ps.line_start_nparen; 267 int rel_ind = opt.continuation_indent * ps.ind_paren_level;
268 if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size) 268 if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size)
269 rel_ind += opt.continuation_indent; 269 rel_ind += opt.continuation_indent;
270 return base_ind + rel_ind; 270 return base_ind + rel_ind;
271} 271}
272 272
273static void 273static void
274output_line_code(void) 274output_line_code(void)
275{ 275{
276 int target_ind = compute_code_indent(); 276 int target_ind = compute_code_indent();
277 for (int i = 0; i < ps.nparen; i++) { 277 for (int i = 0; i < ps.nparen; i++) {
278 int paren_ind = ps.paren[i].indent; 278 int paren_ind = ps.paren[i].indent;
279 if (paren_ind >= 0) { 279 if (paren_ind >= 0) {
280 ps.paren[i].indent = -1 - (paren_ind + target_ind); 280 ps.paren[i].indent = -1 - (paren_ind + target_ind);
281 debug_println( 281 debug_println(
282 "setting paren_indents[%d] from %d to %d " 282 "setting paren_indents[%d] from %d to %d "
283 "for column %d", 283 "for column %d",
284 i, paren_ind, ps.paren[i].indent, target_ind + 1); 284 i, paren_ind, ps.paren[i].indent, target_ind + 1);
285 } 285 }
286 } 286 }
287 287
288 if (lab.len > 0 && target_ind <= out_ind) 288 if (lab.len > 0 && target_ind <= out_ind)
289 write_range(" ", 1); 289 write_range(" ", 1);
290 write_indent(target_ind); 290 write_indent(target_ind);
291 write_range(code.s, code.len); 291 write_range(code.s, code.len);
292} 292}
293 293
294static void 294static void
295output_comment(void) 295output_comment(void)
296{ 296{
297 int target_ind = ps.com_ind + ps.comment_delta; 297 int target_ind = ps.com_ind + ps.comment_delta;
298 const char *p; 298 const char *p;
299 299
300 /* consider original indentation in case this is a box comment */ 300 /* consider original indentation in case this is a box comment */
301 for (p = com.s; *p == '\t'; p++) 301 for (p = com.s; *p == '\t'; p++)
302 target_ind += opt.tabsize; 302 target_ind += opt.tabsize;
303 303
304 for (; target_ind < 0; p++) { 304 for (; target_ind < 0; p++) {
305 if (*p == ' ') 305 if (*p == ' ')
306 target_ind++; 306 target_ind++;
307 else if (*p == '\t') 307 else if (*p == '\t')
308 target_ind = next_tab(target_ind); 308 target_ind = next_tab(target_ind);
309 else { 309 else {
310 target_ind = 0; 310 target_ind = 0;
311 break; 311 break;
312 } 312 }
313 } 313 }
314 314
315 if (out_ind > target_ind) 315 if (out_ind > target_ind)
316 add_buffered_newline(); 316 add_buffered_newline();
317 317
318 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1])) 318 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1]))
319 com.len--; 319 com.len--;
320 buf_terminate(&com); 320 buf_terminate(&com);
321 321
322 write_indent(target_ind); 322 write_indent(target_ind);
323 write_range(p, com.len - (size_t)(p - com.s)); 323 write_range(p, com.len - (size_t)(p - com.s));
324 324
325 ps.comment_delta = ps.n_comment_delta; 325 ps.comment_delta = ps.n_comment_delta;
326} 326}
327 327
328static void 328static void
329output_indented_line(void) 329output_indented_line(void)
330{ 330{
331 if (lab.len == 0 && code.len == 0 && com.len == 0) 331 if (lab.len == 0 && code.len == 0 && com.len == 0)
332 out.line_kind = lk_blank; 332 out.line_kind = lk_blank;
333 333
334 if (want_blank_line() && newlines < 2 334 if (want_blank_line() && newlines < 2
335 && out.line_kind != lk_blank) 335 && out.line_kind != lk_blank)
336 add_buffered_newline(); 336 add_buffered_newline();
337 337
338 /* This kludge aligns function definitions correctly. */ 338 /* This kludge aligns function definitions correctly. */
339 if (ps.ind_level == 0) 339 if (ps.ind_level == 0)
340 ps.in_stmt_cont = false; 340 ps.in_stmt_cont = false;
341 341
342 if (opt.blank_line_after_decl && ps.declaration == decl_end 342 if (opt.blank_line_after_decl && ps.declaration == decl_end
343 && ps.psyms.top > 1) { 343 && ps.psyms.top > 1) {
344 ps.declaration = decl_no; 344 ps.declaration = decl_no;
345 ps.blank_line_after_decl = true; 345 ps.blank_line_after_decl = true;
346 } 346 }
347 347
348 if (opt.swallow_optional_blank_lines 348 if (opt.swallow_optional_blank_lines
349 && out.line_kind == lk_blank 349 && out.line_kind == lk_blank
350 && is_blank_line_optional()) 350 && is_blank_line_optional())
351 return; 351 return;
352 352
353 if (lab.len > 0) 353 if (lab.len > 0)
354 output_line_label(); 354 output_line_label();
355 if (code.len > 0) 355 if (code.len > 0)
356 output_line_code(); 356 output_line_code();
357 if (com.len > 0) 357 if (com.len > 0)
358 output_comment(); 358 output_comment();
359 add_buffered_newline(); 359 add_buffered_newline();
360 if (out.line_kind != lk_blank) 360 if (out.line_kind != lk_blank)
361 write_buffered_newlines(); 361 write_buffered_newlines();
362 362
363 out.prev_line_kind = out.line_kind; 363 out.prev_line_kind = out.line_kind;
364} 364}
365 365
366/* 366/*
367 * Write a line of formatted source to the output file. The line consists of 367 * Write a line of formatted source to the output file. The line consists of
368 * the label, the code and the comment. 368 * the label, the code and the comment.
369 */ 369 */
370void 370void
371output_line(void) 371output_line(void)
372{ 372{
373 debug_blank_line(); 373 debug_blank_line();
374 debug_printf("%s", __func__); 374 debug_printf("%s", __func__);
375 debug_buffers(); 375 debug_buffers();
376 376
377 if (indent_enabled == indent_on) 377 if (indent_enabled == indent_on)
378 output_indented_line(); 378 output_indented_line();
379 else if (indent_enabled == indent_last_off_line) { 379 else if (indent_enabled == indent_last_off_line) {
380 indent_enabled = indent_on; 380 indent_enabled = indent_on;
381 write_range(out.indent_off_text.s, out.indent_off_text.len); 381 write_range(out.indent_off_text.s, out.indent_off_text.len);
382 buf_clear(&out.indent_off_text); 382 buf_clear(&out.indent_off_text);
383 } 383 }
384 384
385 buf_clear(&lab); 385 buf_clear(&lab);
386 buf_clear(&code); 386 buf_clear(&code);
387 buf_clear(&com); 387 buf_clear(&com);
388 388
389 ps.line_has_decl = ps.in_decl; 389 ps.line_has_decl = ps.in_decl;
390 ps.line_has_func_def = false; 390 ps.line_has_func_def = false;
391 ps.in_stmt_cont = ps.in_stmt_or_decl 391 ps.in_stmt_cont = ps.in_stmt_or_decl
392 && (!ps.in_decl || ps.in_init) 392 && (!ps.in_decl || ps.in_init)
393 && ps.init_level == 0; 393 && ps.init_level == 0;
394 ps.decl_indent_done = false; 394 ps.decl_indent_done = false;
395 if (ps.extra_expr_indent == eei_last) 395 if (ps.extra_expr_indent == eei_last)
396 ps.extra_expr_indent = eei_no; 396 ps.extra_expr_indent = eei_no;
397 if (!(ps.psyms.sym[ps.psyms.top] == psym_if_expr_stmt_else 397 if (!(ps.psyms.sym[ps.psyms.top] == psym_if_expr_stmt_else
398 && ps.nparen > 0)) 398 && ps.nparen > 0))
399 ps.ind_level = ps.ind_level_follow; 399 ps.ind_level = ps.ind_level_follow;
400 ps.line_start_nparen = ps.nparen; 400 ps.ind_paren_level = ps.nparen;
401 ps.want_blank = false; 401 ps.want_blank = false;
402 402
403 if (ps.nparen > 0) { 403 if (ps.nparen > 0) {
404 /* TODO: explain what negative indentation means */ 404 /* TODO: explain what negative indentation means */
405 paren_indent = -1 - ps.paren[ps.nparen - 1].indent; 405 paren_indent = -1 - ps.paren[ps.nparen - 1].indent;
406 debug_println("paren_indent is now %d", paren_indent); 406 debug_println("paren_indent is now %d", paren_indent);
407 } 407 }
408 408
409 out.line_kind = lk_other; 409 out.line_kind = lk_other;
410} 410}
411 411
412void 412void
413finish_output(void) 413finish_output(void)
414{ 414{
415 output_line(); 415 output_line();
416 if (indent_enabled != indent_on) { 416 if (indent_enabled != indent_on) {
417 indent_enabled = indent_last_off_line; 417 indent_enabled = indent_last_off_line;
418 output_line(); 418 output_line();
419 } 419 }
420 fflush(output); 420 fflush(output);
421} 421}