Thu Jun 8 06:47:14 2023 UTC ()
indent: clean up and condense code

No functional change.


(rillig)
diff -r1.6 -r1.7 src/tests/usr.bin/indent/lsym_rbrace.c
diff -r1.338 -r1.339 src/usr.bin/indent/indent.c
diff -r1.177 -r1.178 src/usr.bin/indent/indent.h
diff -r1.202 -r1.203 src/usr.bin/indent/io.c

cvs diff -r1.6 -r1.7 src/tests/usr.bin/indent/lsym_rbrace.c (switch to unified diff)

--- src/tests/usr.bin/indent/lsym_rbrace.c 2023/06/04 13:49:00 1.6
+++ src/tests/usr.bin/indent/lsym_rbrace.c 2023/06/08 06:47:14 1.7
@@ -1,68 +1,98 @@ @@ -1,68 +1,98 @@
1/* $NetBSD: lsym_rbrace.c,v 1.6 2023/06/04 13:49:00 rillig Exp $ */ 1/* $NetBSD: lsym_rbrace.c,v 1.7 2023/06/08 06:47:14 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the token lsym_rbrace, which represents a '}' in these contexts: 4 * Tests for the token lsym_rbrace, which represents a '}' in these contexts:
5 * 5 *
6 * In an initializer, '}' ends an inner group of initializers, usually to 6 * In an initializer, '}' ends an inner group of initializers, usually to
7 * initialize a nested struct, union or array. 7 * initialize a nested struct, union or array.
8 * 8 *
9 * In a function body, '}' ends a block. 9 * In a function body, '}' ends a block.
10 * 10 *
11 * In an expression like '(type){...}', '}' ends a compound literal, which is 11 * In an expression like '(type){...}', '}' ends a compound literal, which is
12 * typically used in an assignment to a struct or array. 12 * typically used in an assignment to a struct or array.
13 * 13 *
14 * In macro arguments, a '}' is an ordinary character, it does not need to be 14 * In macro arguments, a '}' is an ordinary character, it does not need to be
15 * balanced. This is in contrast to '(' and ')', which must be balanced. 15 * balanced. This is in contrast to '(' and ')', which must be balanced.
16 * 16 *
17 * TODO: try to split this token into lsym_rbrace_block and lsym_rbrace_init. 17 * TODO: try to split this token into lsym_rbrace_block and lsym_rbrace_init.
18 * 18 *
19 * See also: 19 * See also:
20 * lsym_lbrace.c 20 * lsym_lbrace.c
21 */ 21 */
22 22
23/* Brace level in an initializer */ 23/* Brace level in an initializer */
24//indent input 24//indent input
25void 25void
26function(void) 26function(void)
27{ 27{
28 struct person p = { 28 struct person p = {
29 .name = "Name", 29 .name = "Name",
30 .age = {{{35}}}, /* C11 6.7.9 allows this. */ 30 .age = {{{35}}}, /* C11 6.7.9 allows this. */
31 }; 31 };
32} 32}
33//indent end 33//indent end
34 34
35//indent run-equals-input 35//indent run-equals-input
36 36
37 37
38/* Begin of a block of statements */ 38/* Begin of a block of statements */
39//indent input 39//indent input
40void function(void) {{{ body(); }}} 40void function(void) {{{ body(); }}}
41//indent end 41//indent end
42 42
43//indent run 43//indent run
44void 44void
45function(void) 45function(void)
46{ 46{
47 { 47 {
48 { 48 {
49 body(); 49 body();
50 } 50 }
51 } 51 }
52} 52}
53//indent end 53//indent end
54 54
55 55
56/* Compound literal */ 56/* Compound literal */
57//indent input 57//indent input
58struct point 58struct point
59origin(void) 59origin(void)
60{ 60{
61 return (struct point){ 61 return (struct point){
62 .x = 0, 62 .x = 0,
63 .y = 0, 63 .y = 0,
64 }; 64 };
65} 65}
66//indent end 66//indent end
67 67
68//indent run-equals-input 68//indent run-equals-input
 69
 70
 71//indent input
 72{
 73int numbers[][] = {
 74{11},
 75{21},
 76{31},
 77};
 78int numbers[][] = {{11},
 79{21},
 80{31},
 81};
 82}
 83//indent end
 84
 85//indent run -di0
 86{
 87 int numbers[][] = {
 88 {11},
 89 {21},
 90 {31},
 91 };
 92 int numbers[][] = {{11},
 93 // $ FIXME: Must be indented.
 94 {21},
 95 {31},
 96 };
 97}
 98//indent end

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

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

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

--- src/usr.bin/indent/indent.h 2023/06/07 15:46:12 1.177
+++ src/usr.bin/indent/indent.h 2023/06/08 06:47:13 1.178
@@ -1,528 +1,527 @@ @@ -1,528 +1,527 @@
1/* $NetBSD: indent.h,v 1.177 2023/06/07 15:46:12 rillig Exp $ */ 1/* $NetBSD: indent.h,v 1.178 2023/06/08 06:47:13 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 lsym_lparen, 76 lsym_lparen,
77 lsym_lbracket, 77 lsym_lbracket,
78 lsym_rparen, 78 lsym_rparen,
79 lsym_rbracket, 79 lsym_rbracket,
80 lsym_lbrace, 80 lsym_lbrace,
81 lsym_rbrace, 81 lsym_rbrace,
82 lsym_period, 82 lsym_period,
83 lsym_unary_op, /* e.g. '*', '&', '-' or leading '++' */ 83 lsym_unary_op, /* e.g. '*', '&', '-' or leading '++' */
84 lsym_binary_op, /* e.g. '*', '&', '<<', '&&' or '/=' */ 
85 lsym_postfix_op, /* trailing '++' or '--' */ 84 lsym_postfix_op, /* trailing '++' or '--' */
 85 lsym_binary_op, /* e.g. '*', '&', '<<', '&&' or '/=' */
86 lsym_question, /* the '?' from a '?:' expression */ 86 lsym_question, /* the '?' from a '?:' expression */
87 lsym_colon_question, /* the ':' from a '?:' expression */ 87 lsym_colon_question, /* the ':' from a '?:' expression */
88 lsym_colon_label, /* the ':' after a label */ 88 lsym_colon_label, /* the ':' after a label */
89 lsym_colon_other, /* bit-fields, generic-association (C11), 89 lsym_colon_other, /* bit-fields, generic-association (C11),
90 * enum-type-specifier (C23), 90 * enum-type-specifier (C23),
91 * attribute-prefixed-token (C23), 91 * attribute-prefixed-token (C23),
92 * pp-prefixed-parameter (C23 6.10) */ 92 * pp-prefixed-parameter (C23 6.10) */
93 lsym_comma, 93 lsym_comma,
94 lsym_semicolon, 94 lsym_semicolon,
95 lsym_typedef, 95 lsym_typedef,
96 lsym_modifier, /* modifiers for types, functions, variables */ 96 lsym_modifier, /* modifiers for types, functions, variables */
97 lsym_type_outside_parentheses, 97 lsym_type_outside_parentheses,
98 lsym_type_in_parentheses, 98 lsym_type_in_parentheses,
99 lsym_tag, /* 'struct', 'union' or 'enum' */ 99 lsym_tag, /* 'struct', 'union' or 'enum' */
100 lsym_case, 100 lsym_case,
101 lsym_default, 101 lsym_default,
102 lsym_sizeof, 102 lsym_sizeof,
103 lsym_offsetof, 103 lsym_offsetof,
104 lsym_word, /* identifier, constant or string */ 104 lsym_word, /* identifier, constant or string */
105 lsym_funcname, /* name of a function being defined */ 105 lsym_funcname, /* name of a function being defined */
106 lsym_do, 106 lsym_do,
107 lsym_else, 107 lsym_else,
108 lsym_for, 108 lsym_for,
109 lsym_if, 109 lsym_if,
110 lsym_switch, 110 lsym_switch,
111 lsym_while, 111 lsym_while,
112 lsym_return, 112 lsym_return,
113} lexer_symbol; 113} lexer_symbol;
114 114
115/* 115/*
116 * Structure of the source code, in terms of declarations, statements and 116 * Structure of the source code, in terms of declarations, statements and
117 * braces; used to determine the indentation level of these parts. 117 * braces; used to determine the indentation level of these parts.
118 */ 118 */
119typedef enum parser_symbol { 119typedef enum parser_symbol {
120 psym_0, /* a placeholder; not stored on the stack */ 120 psym_0, /* a placeholder; not stored on the stack */
121 psym_lbrace_block, /* '{' for a block of code */ 121 psym_lbrace_block, /* '{' for a block of code */
122 psym_lbrace_struct, /* '{' in 'struct ... { ... }' */ 122 psym_lbrace_struct, /* '{' in 'struct ... { ... }' */
123 psym_lbrace_union, /* '{' in 'union ... { ... }' */ 123 psym_lbrace_union, /* '{' in 'union ... { ... }' */
124 psym_lbrace_enum, /* '{' in 'enum ... { ... }' */ 124 psym_lbrace_enum, /* '{' in 'enum ... { ... }' */
125 psym_rbrace, /* not stored on the stack */ 125 psym_rbrace, /* not stored on the stack */
126 psym_decl, 126 psym_decl,
127 psym_stmt, 127 psym_stmt,
128 psym_stmt_list, 128 psym_stmt_list,
129 psym_for_exprs, /* 'for' '(' ... ')' */ 129 psym_for_exprs, /* 'for' '(' ... ')' */
130 psym_if_expr, /* 'if' '(' expr ')' */ 130 psym_if_expr, /* 'if' '(' expr ')' */
131 psym_if_expr_stmt, /* 'if' '(' expr ')' stmt */ 131 psym_if_expr_stmt, /* 'if' '(' expr ')' stmt */
132 psym_if_expr_stmt_else, /* 'if' '(' expr ')' stmt 'else' */ 132 psym_if_expr_stmt_else, /* 'if' '(' expr ')' stmt 'else' */
133 psym_else, /* 'else'; not stored on the stack */ 133 psym_else, /* 'else'; not stored on the stack */
134 psym_switch_expr, /* 'switch' '(' expr ')' */ 134 psym_switch_expr, /* 'switch' '(' expr ')' */
135 psym_do, /* 'do' */ 135 psym_do, /* 'do' */
136 psym_do_stmt, /* 'do' stmt */ 136 psym_do_stmt, /* 'do' stmt */
137 psym_while_expr, /* 'while' '(' expr ')' */ 137 psym_while_expr, /* 'while' '(' expr ')' */
138} parser_symbol; 138} parser_symbol;
139 139
140/* A range of characters, not null-terminated. */ 140/* A range of characters, not null-terminated. */
141struct buffer { 141struct buffer {
142 char *s; 142 char *s;
143 size_t len; 143 size_t len;
144 size_t cap; 144 size_t cap;
145}; 145};
146 146
147extern FILE *input; 147extern FILE *input;
148extern FILE *output; 148extern FILE *output;
149 149
150/* 150/*
151 * The current line from the input file, used by the lexer to generate tokens. 151 * The current line from the input file, used by the lexer to generate tokens.
152 * To read from the line, start at inp_p and continue up to and including the 152 * To read from the line, start at inp_p and continue up to and including the
153 * next '\n'. To read beyond the '\n', call inp_skip or inp_next, which will 153 * next '\n'. To read beyond the '\n', call inp_skip or inp_next, which will
154 * make the next line available, invalidating any pointers into the previous 154 * make the next line available, invalidating any pointers into the previous
155 * line. 155 * line.
156 */ 156 */
157extern struct buffer inp; 157extern struct buffer inp;
158extern const char *inp_p; 158extern const char *inp_p;
159 159
160extern struct buffer token; /* the current token to be processed, is 160extern struct buffer token; /* the current token to be processed, is
161 * typically copied to the buffer 'code', or in 161 * typically copied to the buffer 'code', or in
162 * some cases to 'lab'. */ 162 * some cases to 'lab'. */
163 163
164extern struct buffer lab; /* the label or preprocessor directive */ 164extern struct buffer lab; /* the label or preprocessor directive */
165extern struct buffer code; /* the main part of the current line of code, 165extern struct buffer code; /* the main part of the current line of code,
166 * containing declarations or statements */ 166 * containing declarations or statements */
167extern struct buffer com; /* the trailing comment of the line, or the 167extern struct buffer com; /* the trailing comment of the line, or the
168 * start or end of a multi-line comment, or 168 * start or end of a multi-line comment, or
169 * while in process_comment, a single line of a 169 * while in process_comment, a single line of a
170 * multi-line comment */ 170 * multi-line comment */
171 171
172extern struct options { 172extern struct options {
173 bool blanklines_around_conditional_compilation; 173 bool blanklines_around_conditional_compilation;
174 bool blank_line_after_decl_at_top; /* this is vaguely similar to 174 bool blank_line_after_decl_at_top; /* this is vaguely similar to
175 * blank_line_after_decl except 175 * blank_line_after_decl except
176 * that it only applies to the 176 * that it only applies to the
177 * first set of declarations in 177 * first set of declarations in
178 * a procedure (just after the 178 * a procedure (just after the
179 * first '{') and it causes a 179 * first '{') and it causes a
180 * blank line to be generated 180 * blank line to be generated
181 * even if there are no 181 * even if there are no
182 * declarations */ 182 * declarations */
183 bool blank_line_after_decl; 183 bool blank_line_after_decl;
184 bool blanklines_after_procs; 184 bool blanklines_after_procs;
185 bool blanklines_before_block_comments; 185 bool blanklines_before_block_comments;
186 bool break_after_comma; /* whether to add a line break after each 186 bool break_after_comma; /* whether to add a line break after each
187 * declarator */ 187 * declarator */
188 bool brace_same_line; /* whether brace should be on same line as if, 188 bool brace_same_line; /* whether brace should be on same line as if,
189 * while, etc */ 189 * while, etc */
190 bool blank_after_sizeof; /* whether a blank should always be 190 bool blank_after_sizeof; /* whether a blank should always be
191 * inserted after sizeof */ 191 * inserted after sizeof */
192 bool comment_delimiter_on_blankline; 192 bool comment_delimiter_on_blankline;
193 int decl_comment_column; /* the column in which comments after 193 int decl_comment_column; /* the column in which comments after
194 * declarations should be put */ 194 * declarations should be put */
195 bool cuddle_else; /* whether 'else' should cuddle up to '}' */ 195 bool cuddle_else; /* whether 'else' should cuddle up to '}' */
196 int continuation_indent; /* the indentation between the edge of 196 int continuation_indent; /* the indentation between the edge of
197 * code and continuation lines */ 197 * code and continuation lines */
198 float case_indent; /* The distance (measured in indentation 198 float case_indent; /* The distance (measured in indentation
199 * levels) to indent case labels from the 199 * levels) to indent case labels from the
200 * switch statement */ 200 * switch statement */
201 int comment_column; /* the column in which comments to the right of 201 int comment_column; /* the column in which comments to the right of
202 * code should start */ 202 * code should start */
203 int decl_indent; /* indentation of identifier in declaration */ 203 int decl_indent; /* indentation of identifier in declaration */
204 bool left_justify_decl; 204 bool left_justify_decl;
205 int unindent_displace; /* comments not to the right of code will be 205 int unindent_displace; /* comments not to the right of code will be
206 * placed this many indentation levels to the 206 * placed this many indentation levels to the
207 * left of code */ 207 * left of code */
208 bool extra_expr_indent; /* whether continuation lines from the 208 bool extra_expr_indent; /* whether continuation lines from the
209 * expression part of "if (e)", "while (e)", 209 * expression part of "if (e)", "while (e)",
210 * "for (e; e; e)" should be indented an extra 210 * "for (e; e; e)" should be indented an extra
211 * tab stop so that they are not confused with 211 * tab stop so that they are not confused with
212 * the code that follows */ 212 * the code that follows */
213 bool else_if_in_same_line; 213 bool else_if_in_same_line;
214 bool function_brace_split; /* split function declaration and brace 214 bool function_brace_split; /* split function declaration and brace
215 * onto separate lines */ 215 * onto separate lines */
216 bool format_col1_comments; /* If comments which start in column 1 216 bool format_col1_comments; /* If comments which start in column 1
217 * are to be reformatted (just like 217 * are to be reformatted (just like
218 * comments that begin in later 218 * comments that begin in later
219 * columns) */ 219 * columns) */
220 bool format_block_comments; /* whether comments beginning with '/ * 220 bool format_block_comments; /* whether comments beginning with '/ *
221 * \n' are to be reformatted */ 221 * \n' are to be reformatted */
222 bool indent_parameters; 222 bool indent_parameters;
223 int indent_size; /* the size of one indentation level */ 223 int indent_size; /* the size of one indentation level */
224 int block_comment_max_line_length; 224 int block_comment_max_line_length;
225 int local_decl_indent; /* like decl_indent but for locals */ 225 int local_decl_indent; /* like decl_indent but for locals */
226 bool lineup_to_parens_always; /* whether to not(?) attempt to keep 226 bool lineup_to_parens_always; /* whether to not(?) attempt to keep
227 * lined-up code within the margin */ 227 * lined-up code within the margin */
228 bool lineup_to_parens; /* whether continued code within parens will be 228 bool lineup_to_parens; /* whether continued code within parens will be
229 * lined up to the open paren */ 229 * lined up to the open paren */
230 bool proc_calls_space; /* whether function calls look like: foo (bar) 230 bool proc_calls_space; /* whether function calls look like: foo (bar)
231 * rather than foo(bar) */ 231 * rather than foo(bar) */
232 bool procnames_start_line; /* whether the names of functions being 232 bool procnames_start_line; /* whether the names of functions being
233 * defined get placed in column 1 (i.e. 233 * defined get placed in column 1 (i.e.
234 * a newline is placed between the type 234 * a newline is placed between the type
235 * of the function and its name) */ 235 * of the function and its name) */
236 bool space_after_cast; /* "b = (int) a" vs. "b = (int)a" */ 236 bool space_after_cast; /* "b = (int) a" vs. "b = (int)a" */
237 bool star_comment_cont; /* whether comment continuation lines should 237 bool star_comment_cont; /* whether comment continuation lines should
238 * have stars at the beginning of each line */ 238 * have stars at the beginning of each line */
239 bool swallow_optional_blanklines; 239 bool swallow_optional_blanklines;
240 bool auto_typedefs; /* whether to recognize identifiers ending in 240 bool auto_typedefs; /* whether to recognize identifiers ending in
241 * "_t" like typedefs */ 241 * "_t" like typedefs */
242 int tabsize; /* the size of a tab */ 242 int tabsize; /* the size of a tab */
243 int max_line_length; 243 int max_line_length;
244 bool use_tabs; /* set true to use tabs for spacing, false uses 244 bool use_tabs; /* set true to use tabs for spacing, false uses
245 * all spaces */ 245 * all spaces */
246 bool verbose; /* print configuration to stderr */ 246 bool verbose; /* print configuration to stderr */
247} opt; 247} opt;
248 248
249extern bool found_err; 249extern bool found_err;
250extern bool had_eof; /* whether input is exhausted */ 250extern bool had_eof; /* whether input is exhausted */
251extern int line_no; /* the current line number. */ 251extern int line_no; /* the current line number. */
252extern enum indent_enabled { 252extern enum indent_enabled {
253 indent_on, 253 indent_on,
254 indent_off, 254 indent_off,
255 indent_last_off_line, 255 indent_last_off_line,
256} indent_enabled; 256} indent_enabled;
257 257
258#define STACKSIZE 256 258#define STACKSIZE 256
259 259
260/* Properties of each level of parentheses or brackets. */ 260/* Properties of each level of parentheses or brackets. */
261typedef struct paren_level_props { 261typedef struct paren_level_props {
262 int indent; /* indentation of the operand/argument, 262 int indent; /* indentation of the operand/argument,
263 * relative to the enclosing statement; if 263 * relative to the enclosing statement; if
264 * negative, reflected at -1 */ 264 * negative, reflected at -1 */
265 enum paren_level_cast { 265 enum paren_level_cast {
266 cast_unknown, 266 cast_unknown,
267 cast_maybe, 267 cast_maybe,
268 cast_no, 268 cast_no,
269 } cast; /* whether the parentheses form a type cast */ 269 } cast; /* whether the parentheses form a type cast */
270} paren_level_props; 270} paren_level_props;
271 271
272struct psym_stack { 272struct psym_stack {
273 int top; /* pointer to top of stack */ 273 int top; /* pointer to top of stack */
274 parser_symbol sym[STACKSIZE]; 274 parser_symbol sym[STACKSIZE];
275 int ind_level[STACKSIZE]; 275 int ind_level[STACKSIZE];
276}; 276};
277 277
278/* 278/*
279 * The parser state determines the layout of the formatted text. 279 * The parser state determines the layout of the formatted text.
280 * 280 *
281 * At each '#if', the parser state is copied so that the corresponding '#else' 281 * At each '#if', the parser state is copied so that the corresponding '#else'
282 * lines start in the same state. 282 * lines start in the same state.
283 * 283 *
284 * In a function body, the number of block braces determines the indentation 284 * In a function body, the number of block braces determines the indentation
285 * of statements and declarations. 285 * of statements and declarations.
286 * 286 *
287 * In a statement, the number of parentheses or brackets determines the 287 * In a statement, the number of parentheses or brackets determines the
288 * indentation of follow-up lines. 288 * indentation of follow-up lines.
289 * 289 *
290 * In an expression, the token type determine whether to put spaces around. 290 * In an expression, the token type determine whether to put spaces around.
291 * 291 *
292 * In a source file, the types of line determine the vertical spacing, such as 292 * In a source file, the types of line determine the vertical spacing, such as
293 * around preprocessing directives or function bodies, or above block 293 * around preprocessing directives or function bodies, or above block
294 * comments. 294 * comments.
295 */ 295 */
296extern struct parser_state { 296extern struct parser_state {
297 lexer_symbol prev_lsym; /* the previous token, but never comment, 297 lexer_symbol prev_lsym; /* the previous token, but never comment,
298 * newline or preprocessing line */ 298 * newline or preprocessing line */
299 299
300 /* Token classification */ 300 /* Token classification */
301 301
302 int quest_level; /* when this is positive, we have seen a '?' 302 int quest_level; /* when this is positive, we have seen a '?'
303 * without the matching ':' in a '?:' 303 * without the matching ':' in a '?:'
304 * expression */ 304 * expression */
305 bool is_function_definition; /* starts either at the 'name(' from a 305 bool is_function_definition; /* starts either at the 'name(' from a
306 * function definition if it occurs at 306 * function definition if it occurs at
307 * the beginning of a line, or at the 307 * the beginning of a line, or at the
308 * first '*' from inside a declaration 308 * first '*' from inside a declaration
309 * when the line starts with words 309 * when the line starts with words
310 * followed by a '('; ends at the end 310 * followed by a '('; ends at the end
311 * of that line */ 311 * of that line */
312 bool block_init; /* whether inside a block initialization */ 312 bool block_init; /* whether inside a block initialization */
313 int block_init_level; /* the level of brace nesting in an 313 int block_init_level; /* the level of brace nesting in an
314 * initialization */ 314 * initialization */
315 bool init_or_struct; /* whether there has been a type name and no 315 bool init_or_struct; /* whether there has been a type name and no
316 * left parenthesis since the last semicolon. 316 * left parenthesis since the last semicolon.
317 * When true, a '{' starts a structure 317 * When true, a '{' starts a structure
318 * definition or an initialization list */ 318 * definition or an initialization list */
319 bool decl_on_line; /* whether this line of code has part of a 319 bool decl_on_line; /* whether this line of code has part of a
320 * declaration on it */ 320 * declaration on it; used for indenting
 321 * comments */
321 bool in_stmt_or_decl; /* whether in a statement or a struct 322 bool in_stmt_or_decl; /* whether in a statement or a struct
322 * declaration or a plain declaration */ 323 * declaration or a plain declaration */
323 bool in_decl; /* whether we are in a declaration. The 324 bool in_decl; /* XXX: double-check the exact meaning */
324 * processing of braces is then slightly 
325 * different */ 
326 bool in_func_def_params; 325 bool in_func_def_params;
327 bool seen_case; /* whether there was a 'case' or 'default', to 326 bool seen_case; /* whether there was a 'case' or 'default', to
328 * properly space the following ':' */ 327 * properly space the following ':' */
329 parser_symbol spaced_expr_psym; /* the parser symbol to be shifted 328 parser_symbol spaced_expr_psym; /* the parser symbol to be shifted
330 * after the parenthesized expression 329 * after the parenthesized expression
331 * from a 'for', 'if', 'switch' or 330 * from a 'for', 'if', 'switch' or
332 * 'while'; or psym_0 */ 331 * 'while'; or psym_0 */
333 parser_symbol lbrace_kind; /* the kind of brace to be pushed to 332 parser_symbol lbrace_kind; /* the kind of brace to be pushed to
334 * the parser symbol stack next */ 333 * the parser symbol stack next */
335 334
336 /* Indentation of statements and declarations */ 335 /* Indentation of statements and declarations */
337 336
338 int ind_level; /* the indentation level for the line that is 337 int ind_level; /* the indentation level for the line that is
339 * currently prepared for output */ 338 * currently prepared for output */
340 int ind_level_follow; /* the level to which ind_level should be set 339 int ind_level_follow; /* the level to which ind_level should be set
341 * after the current line is printed */ 340 * after the current line is printed */
342 bool in_stmt_cont; /* whether the current line should have an 341 bool in_stmt_cont; /* whether the current line should have an
343 * extra indentation level because we are in 342 * extra indentation level because we are in
344 * the middle of a statement */ 343 * the middle of a statement */
345 int decl_level; /* current nesting level for a structure 344 int decl_level; /* current nesting level for a structure
346 * declaration or an initializer */ 345 * declaration or an initializer */
347 int di_stack[20]; /* a stack of structure indentation levels */ 346 int di_stack[20]; /* a stack of structure indentation levels */
348 bool decl_indent_done; /* whether the indentation for a declaration 347 bool decl_indent_done; /* whether the indentation for a declaration
349 * has been added to the code buffer. */ 348 * has been added to the code buffer. */
350 int decl_ind; /* current indentation for declarations */ 349 int decl_ind; /* current indentation for declarations */
351 bool tabs_to_var; /* true if using tabs to indent to var name */ 350 bool tabs_to_var; /* true if using tabs to indent to var name */
352 351
353 enum { 352 enum {
354 eei_no, 353 eei_no,
355 eei_yes, 354 eei_yes,
356 eei_last 355 eei_last
357 } extra_expr_indent; 356 } extra_expr_indent;
358 357
359 struct psym_stack psyms; 358 struct psym_stack psyms;
360 359
361 /* Spacing inside a statement or declaration */ 360 /* Spacing inside a statement or declaration */
362 361
363 bool next_unary; /* whether the following operator should be 362 bool next_unary; /* whether the following operator should be
364 * unary; is used in declarations for '*', as 363 * unary; is used in declarations for '*', as
365 * well as in expressions */ 364 * well as in expressions */
366 bool want_blank; /* whether the following token should be 365 bool want_blank; /* whether the following token should be
367 * prefixed by a blank. (Said prefixing is 366 * prefixed by a blank. (Said prefixing is
368 * ignored in some cases.) */ 367 * ignored in some cases.) */
369 int line_start_nparen; /* the number of parentheses or brackets that 368 int line_start_nparen; /* the number of parentheses or brackets that
370 * were open at the beginning of the current 369 * were open at the beginning of the current
371 * line; used to indent within statements, 370 * line; used to indent within statements,
372 * initializers and declarations */ 371 * initializers and declarations */
373 int nparen; /* the number of parentheses or brackets that 372 int nparen; /* the number of parentheses or brackets that
374 * are currently open; used to indent the 373 * are currently open; used to indent the
375 * remaining lines of the statement, 374 * remaining lines of the statement,
376 * initializer or declaration */ 375 * initializer or declaration */
377 paren_level_props paren[20]; 376 paren_level_props paren[20];
378 enum { 377 enum {
379 dp_start, /* the beginning of a declaration */ 378 dp_start, /* the beginning of a declaration */
380 dp_word, /* seen a type name */ 379 dp_word, /* seen a type name */
381 dp_word_asterisk, /* seen a type name and some '*' */ 380 dp_word_asterisk, /* seen a type name and some '*' */
382 dp_other, 381 dp_other,
383 } decl_ptr; /* detects declarations like 'typename *x', to 382 } decl_ptr; /* detects declarations like 'typename *x', to
384 * prevent the '*' from being interpreted as a 383 * prevent the '*' from being interpreted as a
385 * binary operator */ 384 * binary operator */
386 385
387 /* Horizontal spacing for comments */ 386 /* Horizontal spacing for comments */
388 387
389 int comment_delta; /* used to set up indentation for all lines of 388 int comment_delta; /* used to set up indentation for all lines of
390 * a boxed comment after the first one */ 389 * a boxed comment after the first one */
391 int n_comment_delta; /* remembers how many columns there were before 390 int n_comment_delta; /* remembers how many columns there were before
392 * the start of a box comment so that 391 * the start of a box comment so that
393 * forthcoming lines of the comment are 392 * forthcoming lines of the comment are
394 * indented properly */ 393 * indented properly */
395 int com_ind; /* indentation of the current comment */ 394 int com_ind; /* indentation of the current comment */
396 395
397 /* Vertical spacing */ 396 /* Vertical spacing */
398 397
399 bool break_after_comma; /* whether to add a newline after the next 398 bool break_after_comma; /* whether to add a newline after the next
400 * comma; used in declarations but not in 399 * comma; used in declarations but not in
401 * initializer lists */ 400 * initializer lists */
402 bool force_nl; /* whether the next token is forced to go to a 401 bool force_nl; /* whether the next token is forced to go to a
403 * new line; used after 'if (expr)' and in 402 * new line; used after 'if (expr)' and in
404 * similar situations; tokens like '{' may 403 * similar situations; tokens like '{' may
405 * ignore this */ 404 * ignore this */
406 405
407 enum declaration { 406 enum declaration {
408 decl_no, /* no declaration anywhere nearby */ 407 decl_no, /* no declaration anywhere nearby */
409 decl_begin, /* collecting tokens of a declaration */ 408 decl_begin, /* collecting tokens of a declaration */
410 decl_end, /* finished a declaration */ 409 decl_end, /* finished a declaration */
411 } declaration; 410 } declaration;
412 bool blank_line_after_decl; 411 bool blank_line_after_decl;
413 412
414 /* Comments */ 413 /* Comments */
415 414
416 bool curr_col_1; /* whether the current token started in column 415 bool curr_col_1; /* whether the current token started in column
417 * 1 of the original input */ 416 * 1 of the original input */
418 bool next_col_1; 417 bool next_col_1;
419} ps; 418} ps;
420 419
421extern struct output_state { 420extern struct output_state {
422 enum line_kind { 421 enum line_kind {
423 lk_other, 422 lk_other,
424 lk_blank, 423 lk_blank,
425 lk_if, /* #if, #ifdef, #ifndef */ 424 lk_if, /* #if, #ifdef, #ifndef */
426 lk_endif, /* #endif */ 425 lk_endif, /* #endif */
427 lk_stmt_head, /* the ')' of an incomplete statement such as 426 lk_stmt_head, /* the ')' of an incomplete statement such as
428 * 'if (expr)' or 'for (expr; expr; expr)' */ 427 * 'if (expr)' or 'for (expr; expr; expr)' */
429 lk_func_end, /* the last '}' of a function body */ 428 lk_func_end, /* the last '}' of a function body */
430 lk_block_comment, 429 lk_block_comment,
431 lk_case_or_default, 430 lk_case_or_default,
432 } line_kind; /* kind of the line that is being prepared for 431 } line_kind; /* kind of the line that is being prepared for
433 * output; is reset to lk_other each time after 432 * output; is reset to lk_other each time after
434 * trying to send a line to the output, even if 433 * trying to send a line to the output, even if
435 * that line was a suppressed blank line; used 434 * that line was a suppressed blank line; used
436 * for inserting or removing blank lines */ 435 * for inserting or removing blank lines */
437 enum line_kind prev_line_kind; /* the kind of line that was actually 436 enum line_kind prev_line_kind; /* the kind of line that was actually
438 * sent to the output */ 437 * sent to the output */
439 438
440 struct buffer indent_off_text; /* text from between 'INDENT OFF' and 439 struct buffer indent_off_text; /* text from between 'INDENT OFF' and
441 * 'INDENT ON', both inclusive */ 440 * 'INDENT ON', both inclusive */
442} out; 441} out;
443 442
444 443
445#define array_length(array) (sizeof(array) / sizeof((array)[0])) 444#define array_length(array) (sizeof(array) / sizeof((array)[0]))
446 445
447#ifdef debug 446#ifdef debug
448void debug_printf(const char *, ...) __printflike(1, 2); 447void debug_printf(const char *, ...) __printflike(1, 2);
449void debug_println(const char *, ...) __printflike(1, 2); 448void debug_println(const char *, ...) __printflike(1, 2);
450void debug_blank_line(void); 449void debug_blank_line(void);
451void debug_vis_range(const char *, const char *, size_t, const char *); 450void debug_vis_range(const char *, const char *, size_t, const char *);
452void debug_parser_state(void); 451void debug_parser_state(void);
453void debug_parse_stack(const char *); 452void debug_parse_stack(const char *);
454void debug_print_buf(const char *, const struct buffer *); 453void debug_print_buf(const char *, const struct buffer *);
455void debug_buffers(void); 454void debug_buffers(void);
456extern const char *const lsym_name[]; 455extern const char *const lsym_name[];
457extern const char *const psym_name[]; 456extern const char *const psym_name[];
458extern const char *const paren_level_cast_name[]; 457extern const char *const paren_level_cast_name[];
459extern const char *const line_kind_name[]; 458extern const char *const line_kind_name[];
460#else 459#else
461#define debug_noop() do { } while (false) 460#define debug_noop() do { } while (false)
462#define debug_printf(fmt, ...) debug_noop() 461#define debug_printf(fmt, ...) debug_noop()
463#define debug_println(fmt, ...) debug_noop() 462#define debug_println(fmt, ...) debug_noop()
464#define debug_blank_line() debug_noop() 463#define debug_blank_line() debug_noop()
465#define debug_vis_range(prefix, s, e, suffix) debug_noop() 464#define debug_vis_range(prefix, s, e, suffix) debug_noop()
466#define debug_parser_state() debug_noop() 465#define debug_parser_state() debug_noop()
467#define debug_parse_stack(situation) debug_noop() 466#define debug_parse_stack(situation) debug_noop()
468#define debug_print_buf(name, buf) debug_noop() 467#define debug_print_buf(name, buf) debug_noop()
469#define debug_buffers() debug_noop() 468#define debug_buffers() debug_noop()
470#endif 469#endif
471 470
472void register_typename(const char *); 471void register_typename(const char *);
473int compute_code_indent(void); 472int compute_code_indent(void);
474int compute_label_indent(void); 473int compute_label_indent(void);
475int ind_add(int, const char *, size_t); 474int ind_add(int, const char *, size_t);
476 475
477void inp_skip(void); 476void inp_skip(void);
478char inp_next(void); 477char inp_next(void);
479 478
480lexer_symbol lexi(void); 479lexer_symbol lexi(void);
481void diag(int, const char *, ...) __printflike(2, 3); 480void diag(int, const char *, ...) __printflike(2, 3);
482void output_line(void); 481void output_line(void);
483void inp_read_line(void); 482void inp_read_line(void);
484void parse(parser_symbol); 483void parse(parser_symbol);
485void process_comment(void); 484void process_comment(void);
486void set_option(const char *, const char *); 485void set_option(const char *, const char *);
487void load_profile_files(const char *); 486void load_profile_files(const char *);
488 487
489void *nonnull(void *); 488void *nonnull(void *);
490 489
491void buf_add_char(struct buffer *, char); 490void buf_add_char(struct buffer *, char);
492void buf_add_chars(struct buffer *, const char *, size_t); 491void buf_add_chars(struct buffer *, const char *, size_t);
493 492
494static inline bool 493static inline bool
495ch_isalnum(char ch) 494ch_isalnum(char ch)
496{ 495{
497 return isalnum((unsigned char)ch) != 0; 496 return isalnum((unsigned char)ch) != 0;
498} 497}
499 498
500static inline bool 499static inline bool
501ch_isalpha(char ch) 500ch_isalpha(char ch)
502{ 501{
503 return isalpha((unsigned char)ch) != 0; 502 return isalpha((unsigned char)ch) != 0;
504} 503}
505 504
506static inline bool 505static inline bool
507ch_isblank(char ch) 506ch_isblank(char ch)
508{ 507{
509 return ch == ' ' || ch == '\t'; 508 return ch == ' ' || ch == '\t';
510} 509}
511 510
512static inline bool 511static inline bool
513ch_isdigit(char ch) 512ch_isdigit(char ch)
514{ 513{
515 return '0' <= ch && ch <= '9'; 514 return '0' <= ch && ch <= '9';
516} 515}
517 516
518static inline bool 517static inline bool
519ch_isspace(char ch) 518ch_isspace(char ch)
520{ 519{
521 return isspace((unsigned char)ch) != 0; 520 return isspace((unsigned char)ch) != 0;
522} 521}
523 522
524static inline int 523static inline int
525next_tab(int ind) 524next_tab(int ind)
526{ 525{
527 return ind - ind % opt.tabsize + opt.tabsize; 526 return ind - ind % opt.tabsize + opt.tabsize;
528} 527}

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

--- src/usr.bin/indent/io.c 2023/06/07 15:46:12 1.202
+++ src/usr.bin/indent/io.c 2023/06/08 06:47:13 1.203
@@ -1,392 +1,392 @@ @@ -1,392 +1,392 @@
1/* $NetBSD: io.c,v 1.202 2023/06/07 15:46:12 rillig Exp $ */ 1/* $NetBSD: io.c,v 1.203 2023/06/08 06:47:13 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-4-Clause 4 * SPDX-License-Identifier: BSD-4-Clause
5 * 5 *
6 * Copyright (c) 1985 Sun Microsystems, Inc. 6 * Copyright (c) 1985 Sun Microsystems, Inc.
7 * Copyright (c) 1980, 1993 7 * Copyright (c) 1980, 1993
8 * The Regents of the University of California. All rights reserved. 8 * The Regents of the University of California. All rights reserved.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software 19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement: 20 * must display the following acknowledgement:
21 * This product includes software developed by the University of 21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors. 22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors 23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software 24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission. 25 * without specific prior written permission.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE. 37 * SUCH DAMAGE.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__RCSID("$NetBSD: io.c,v 1.202 2023/06/07 15:46:12 rillig Exp $"); 41__RCSID("$NetBSD: io.c,v 1.203 2023/06/08 06:47:13 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;
51static int out_ind; /* width of the line that is being written */ 51static int out_ind; /* width of the line that is being written */
52static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after a 52static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after a
53 * single '\n', > 1 means there were (n 53 * single '\n', > 1 means there were (n
54 * - 1) blank lines above */ 54 * - 1) blank lines above */
55static int paren_indent; 55static int paren_indent;
56 56
57 57
58static void 58static void
59inp_read_next_line(FILE *f) 59inp_read_next_line(FILE *f)
60{ 60{
61 inp.len = 0; 61 inp.len = 0;
62 62
63 for (;;) { 63 for (;;) {
64 int ch = getc(f); 64 int ch = getc(f);
65 if (ch == EOF) { 65 if (ch == EOF) {
66 if (indent_enabled == indent_on) { 66 if (indent_enabled == indent_on) {
67 buf_add_char(&inp, ' '); 67 buf_add_char(&inp, ' ');
68 buf_add_char(&inp, '\n'); 68 buf_add_char(&inp, '\n');
69 } 69 }
70 had_eof = true; 70 had_eof = true;
71 break; 71 break;
72 } 72 }
73 73
74 if (ch != '\0') 74 if (ch != '\0')
75 buf_add_char(&inp, (char)ch); 75 buf_add_char(&inp, (char)ch);
76 if (ch == '\n') 76 if (ch == '\n')
77 break; 77 break;
78 } 78 }
79 inp_p = inp.s; 79 inp_p = inp.s;
80} 80}
81 81
82void 82void
83inp_read_line(void) 83inp_read_line(void)
84{ 84{
85 if (indent_enabled == indent_on) 85 if (indent_enabled == indent_on)
86 out.indent_off_text.len = 0; 86 out.indent_off_text.len = 0;
87 buf_add_chars(&out.indent_off_text, inp.s, inp.len); 87 buf_add_chars(&out.indent_off_text, inp.s, inp.len);
88 inp_read_next_line(input); 88 inp_read_next_line(input);
89} 89}
90 90
91void 91void
92inp_skip(void) 92inp_skip(void)
93{ 93{
94 inp_p++; 94 inp_p++;
95 if ((size_t)(inp_p - inp.s) >= inp.len) 95 if ((size_t)(inp_p - inp.s) >= inp.len)
96 inp_read_line(); 96 inp_read_line();
97} 97}
98 98
99char 99char
100inp_next(void) 100inp_next(void)
101{ 101{
102 char ch = inp_p[0]; 102 char ch = inp_p[0];
103 inp_skip(); 103 inp_skip();
104 return ch; 104 return ch;
105} 105}
106 106
107 107
108static void 108static void
109output_newline(void) 109output_newline(void)
110{ 110{
111 fputc('\n', output); 111 fputc('\n', output);
112 debug_println("output_newline"); 112 debug_println("output_newline");
113 wrote_newlines++; 113 wrote_newlines++;
114 out_ind = 0; 114 out_ind = 0;
115} 115}
116 116
117static void 117static void
118output_range(const char *s, size_t len) 118output_range(const char *s, size_t len)
119{ 119{
120 fwrite(s, 1, len, output); 120 fwrite(s, 1, len, output);
121 debug_vis_range("output_range \"", s, len, "\"\n"); 121 debug_vis_range("output_range \"", s, len, "\"\n");
122 for (size_t i = 0; i < len; i++) 122 for (size_t i = 0; i < len; i++)
123 wrote_newlines = s[i] == '\n' ? wrote_newlines + 1 : 0; 123 wrote_newlines = s[i] == '\n' ? wrote_newlines + 1 : 0;
124 out_ind = ind_add(out_ind, s, len); 124 out_ind = ind_add(out_ind, s, len);
125} 125}
126 126
127static void 127static void
128output_indent(int new_ind) 128output_indent(int new_ind)
129{ 129{
130 int ind = out_ind; 130 int ind = out_ind;
131 131
132 if (opt.use_tabs) { 132 if (opt.use_tabs) {
133 int n = new_ind / opt.tabsize - ind / opt.tabsize; 133 int n = new_ind / opt.tabsize - ind / opt.tabsize;
134 if (n > 0) { 134 if (n > 0) {
135 ind = ind - ind % opt.tabsize + n * opt.tabsize; 135 ind = ind - ind % opt.tabsize + n * opt.tabsize;
136 while (n-- > 0) 136 while (n-- > 0)
137 fputc('\t', output); 137 fputc('\t', output);
138 wrote_newlines = 0; 138 wrote_newlines = 0;
139 } 139 }
140 } 140 }
141 141
142 for (; ind < new_ind; ind++) { 142 for (; ind < new_ind; ind++) {
143 fputc(' ', output); 143 fputc(' ', output);
144 wrote_newlines = 0; 144 wrote_newlines = 0;
145 } 145 }
146 146
147 debug_println("output_indent %d", ind); 147 debug_println("output_indent %d", ind);
148 out_ind = ind; 148 out_ind = ind;
149} 149}
150 150
151static bool 151static bool
152want_blank_line(void) 152want_blank_line(void)
153{ 153{
154 debug_println("%s: %s -> %s", __func__, 154 debug_println("%s: %s -> %s", __func__,
155 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]); 155 line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]);
156 156
157 if (ps.blank_line_after_decl && ps.declaration == decl_no) { 157 if (ps.blank_line_after_decl && ps.declaration == decl_no) {
158 ps.blank_line_after_decl = false; 158 ps.blank_line_after_decl = false;
159 return true; 159 return true;
160 } 160 }
161 if (opt.blanklines_around_conditional_compilation) { 161 if (opt.blanklines_around_conditional_compilation) {
162 if (out.prev_line_kind != lk_if && out.line_kind == lk_if) 162 if (out.prev_line_kind != lk_if && out.line_kind == lk_if)
163 return true; 163 return true;
164 if (out.prev_line_kind == lk_endif 164 if (out.prev_line_kind == lk_endif
165 && out.line_kind != lk_endif) 165 && out.line_kind != lk_endif)
166 return true; 166 return true;
167 } 167 }
168 if (opt.blanklines_after_procs && out.prev_line_kind == lk_func_end 168 if (opt.blanklines_after_procs && out.prev_line_kind == lk_func_end
169 && out.line_kind != lk_endif) 169 && out.line_kind != lk_endif)
170 return true; 170 return true;
171 if (opt.blanklines_before_block_comments 171 if (opt.blanklines_before_block_comments
172 && out.line_kind == lk_block_comment) 172 && out.line_kind == lk_block_comment)
173 return true; 173 return true;
174 return false; 174 return false;
175} 175}
176 176
177static bool 177static bool
178is_blank_line_optional(void) 178is_blank_line_optional(void)
179{ 179{
180 if (out.prev_line_kind == lk_stmt_head) 180 if (out.prev_line_kind == lk_stmt_head)
181 return wrote_newlines >= 1; 181 return wrote_newlines >= 1;
182 if (ps.psyms.top >= 2) 182 if (ps.psyms.top >= 2)
183 return wrote_newlines >= 2; 183 return wrote_newlines >= 2;
184 return wrote_newlines >= 3; 184 return wrote_newlines >= 3;
185} 185}
186 186
187static int 187static int
188compute_case_label_indent(void) 188compute_case_label_indent(void)
189{ 189{
190 int i = ps.psyms.top; 190 int i = ps.psyms.top;
191 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr) 191 while (i > 0 && ps.psyms.sym[i] != psym_switch_expr)
192 i--; 192 i--;
193 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent; 193 float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent;
194 return (int)(case_ind * (float)opt.indent_size); 194 return (int)(case_ind * (float)opt.indent_size);
195} 195}
196 196
197int 197int
198compute_label_indent(void) 198compute_label_indent(void)
199{ 199{
200 if (out.line_kind == lk_case_or_default) 200 if (out.line_kind == lk_case_or_default)
201 return compute_case_label_indent(); 201 return compute_case_label_indent();
202 if (lab.s[0] == '#') 202 if (lab.s[0] == '#')
203 return 0; 203 return 0;
204 return opt.indent_size * (ps.ind_level - 2); 204 return opt.indent_size * (ps.ind_level - 2);
205} 205}
206 206
207static void 207static void
208output_line_label(void) 208output_line_label(void)
209{ 209{
210 output_indent(compute_label_indent()); 210 output_indent(compute_label_indent());
211 output_range(lab.s, lab.len); 211 output_range(lab.s, lab.len);
212} 212}
213 213
214static int 214static int
215compute_code_indent_lineup(int base_ind) 215compute_code_indent_lineup(int base_ind)
216{ 216{
217 int ind = paren_indent; 217 int ind = paren_indent;
218 int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; 218 int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length;
219 if (overflow < 0) 219 if (overflow < 0)
220 return ind; 220 return ind;
221 221
222 if (ind_add(base_ind, code.s, code.len) < opt.max_line_length) { 222 if (ind_add(base_ind, code.s, code.len) < opt.max_line_length) {
223 ind -= overflow + 2; 223 ind -= overflow + 2;
224 if (ind > base_ind) 224 if (ind > base_ind)
225 return ind; 225 return ind;
226 return base_ind; 226 return base_ind;
227 } 227 }
228 228
229 return ind; 229 return ind;
230} 230}
231 231
232int 232int
233compute_code_indent(void) 233compute_code_indent(void)
234{ 234{
235 int base_ind = ps.ind_level * opt.indent_size; 235 int base_ind = ps.ind_level * opt.indent_size;
236 236
237 if (ps.line_start_nparen == 0) { 237 if (ps.line_start_nparen == 0) {
238 if (ps.psyms.top >= 1 238 if (ps.psyms.top >= 1
239 && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum) 239 && ps.psyms.sym[ps.psyms.top - 1] == psym_lbrace_enum)
240 return base_ind; 240 return base_ind;
241 if (ps.in_stmt_cont) 241 if (ps.in_stmt_cont)
242 return base_ind + opt.continuation_indent; 242 return base_ind + opt.continuation_indent;
243 return base_ind; 243 return base_ind;
244 } 244 }
245 245
246 if (opt.lineup_to_parens) { 246 if (opt.lineup_to_parens) {
247 if (opt.lineup_to_parens_always) 247 if (opt.lineup_to_parens_always)
248 return paren_indent; 248 return paren_indent;
249 return compute_code_indent_lineup(base_ind); 249 return compute_code_indent_lineup(base_ind);
250 } 250 }
251 251
252 if (ps.extra_expr_indent != eei_no) 252 if (ps.extra_expr_indent != eei_no)
253 return base_ind + 2 * opt.continuation_indent; 253 return base_ind + 2 * opt.continuation_indent;
254 254
255 if (2 * opt.continuation_indent == opt.indent_size) 255 if (2 * opt.continuation_indent == opt.indent_size)
256 return base_ind + opt.continuation_indent; 256 return base_ind + opt.continuation_indent;
257 else 257 else
258 return base_ind + 258 return base_ind +
259 opt.continuation_indent * ps.line_start_nparen; 259 opt.continuation_indent * ps.line_start_nparen;
260} 260}
261 261
262static void 262static void
263output_line_code(void) 263output_line_code(void)
264{ 264{
265 int target_ind = compute_code_indent(); 265 int target_ind = compute_code_indent();
266 for (int i = 0; i < ps.nparen; i++) { 266 for (int i = 0; i < ps.nparen; i++) {
267 int paren_ind = ps.paren[i].indent; 267 int paren_ind = ps.paren[i].indent;
268 if (paren_ind >= 0) { 268 if (paren_ind >= 0) {
269 ps.paren[i].indent = -1 - (paren_ind + target_ind); 269 ps.paren[i].indent = -1 - (paren_ind + target_ind);
270 debug_println( 270 debug_println(
271 "setting paren_indents[%d] from %d to %d " 271 "setting paren_indents[%d] from %d to %d "
272 "for column %d", 272 "for column %d",
273 i, paren_ind, ps.paren[i].indent, target_ind + 1); 273 i, paren_ind, ps.paren[i].indent, target_ind + 1);
274 } 274 }
275 } 275 }
276 276
277 if (lab.len > 0 && target_ind <= out_ind) 277 if (lab.len > 0 && target_ind <= out_ind)
278 output_range(" ", 1); 278 output_range(" ", 1);
279 output_indent(target_ind); 279 output_indent(target_ind);
280 output_range(code.s, code.len); 280 output_range(code.s, code.len);
281} 281}
282 282
283static void 283static void
284output_line_comment(void) 284output_line_comment(void)
285{ 285{
286 int target_ind = ps.com_ind + ps.comment_delta; 286 int target_ind = ps.com_ind + ps.comment_delta;
287 const char *p; 287 const char *p;
288 288
289 /* consider original indentation in case this is a box comment */ 289 /* consider original indentation in case this is a box comment */
290 for (p = com.s; *p == '\t'; p++) 290 for (p = com.s; *p == '\t'; p++)
291 target_ind += opt.tabsize; 291 target_ind += opt.tabsize;
292 292
293 for (; target_ind < 0; p++) { 293 for (; target_ind < 0; p++) {
294 if (*p == ' ') 294 if (*p == ' ')
295 target_ind++; 295 target_ind++;
296 else if (*p == '\t') 296 else if (*p == '\t')
297 target_ind = next_tab(target_ind); 297 target_ind = next_tab(target_ind);
298 else { 298 else {
299 target_ind = 0; 299 target_ind = 0;
300 break; 300 break;
301 } 301 }
302 } 302 }
303 303
304 if (out_ind > target_ind) 304 if (out_ind > target_ind)
305 output_newline(); 305 output_newline();
306 306
307 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1])) 307 while (com.s + com.len > p && ch_isspace(com.s[com.len - 1]))
308 com.len--; 308 com.len--;
309 309
310 output_indent(target_ind); 310 output_indent(target_ind);
311 output_range(p, com.len - (size_t)(p - com.s)); 311 output_range(p, com.len - (size_t)(p - com.s));
312 312
313 ps.comment_delta = ps.n_comment_delta; 313 ps.comment_delta = ps.n_comment_delta;
314} 314}
315 315
316/* 316/*
317 * Write a line of formatted source to the output file. The line consists of 317 * Write a line of formatted source to the output file. The line consists of
318 * the label, the code and the comment. 318 * the label, the code and the comment.
319 */ 319 */
320void 320void
321output_line(void) 321output_line(void)
322{ 322{
323 debug_blank_line(); 323 debug_blank_line();
324 debug_printf("%s", __func__); 324 debug_printf("%s", __func__);
325 debug_buffers(); 325 debug_buffers();
326 326
327 ps.is_function_definition = false; 327 ps.is_function_definition = false;
328 328
329 if (indent_enabled == indent_on) { 329 if (indent_enabled == indent_on) {
330 if (lab.len == 0 && code.len == 0 && com.len == 0) 330 if (lab.len == 0 && code.len == 0 && com.len == 0)
331 out.line_kind = lk_blank; 331 out.line_kind = lk_blank;
332 332
333 if (want_blank_line() && wrote_newlines < 2 333 if (want_blank_line() && wrote_newlines < 2
334 && out.line_kind != lk_blank) 334 && out.line_kind != lk_blank)
335 output_newline(); 335 output_newline();
336 336
337 /* This kludge aligns function definitions correctly. */ 337 /* This kludge aligns function definitions correctly. */
338 if (ps.ind_level == 0) 338 if (ps.ind_level == 0)
339 ps.in_stmt_cont = false; 339 ps.in_stmt_cont = false;
340 340
341 if (opt.blank_line_after_decl && ps.declaration == decl_end 341 if (opt.blank_line_after_decl && ps.declaration == decl_end
342 && ps.psyms.top > 1) { 342 && ps.psyms.top > 1) {
343 ps.declaration = decl_no; 343 ps.declaration = decl_no;
344 ps.blank_line_after_decl = true; 344 ps.blank_line_after_decl = true;
345 } 345 }
346 346
347 if (opt.swallow_optional_blanklines 347 if (opt.swallow_optional_blanklines
348 && out.line_kind == lk_blank 348 && out.line_kind == lk_blank
349 && is_blank_line_optional()) 349 && is_blank_line_optional())
350 goto dont_write_line; 350 goto prepare_next_line;
351 351
352 if (lab.len > 0) 352 if (lab.len > 0)
353 output_line_label(); 353 output_line_label();
354 if (code.len > 0) 354 if (code.len > 0)
355 output_line_code(); 355 output_line_code();
356 if (com.len > 0) 356 if (com.len > 0)
357 output_line_comment(); 357 output_line_comment();
358 358
359 output_newline(); 359 output_newline();
360 out.prev_line_kind = out.line_kind; 360 out.prev_line_kind = out.line_kind;
361 } 361 }
362 362
363 if (indent_enabled == indent_last_off_line) { 363 if (indent_enabled == indent_last_off_line) {
364 indent_enabled = indent_on; 364 indent_enabled = indent_on;
365 output_range(out.indent_off_text.s, out.indent_off_text.len); 365 output_range(out.indent_off_text.s, out.indent_off_text.len);
366 out.indent_off_text.len = 0; 366 out.indent_off_text.len = 0;
367 } 367 }
368 368
369dont_write_line: 369prepare_next_line:
370 ps.decl_on_line = ps.in_decl; /* for proper comment indentation */ 370 lab.len = 0;
 371 code.len = 0;
 372 com.len = 0;
 373
 374 ps.decl_on_line = ps.in_decl;
 375 // XXX: don't reset in_stmt_cont here; see process_colon_question.
371 ps.in_stmt_cont = ps.in_stmt_or_decl 376 ps.in_stmt_cont = ps.in_stmt_or_decl
372 && !ps.in_decl && ps.block_init_level == 0; 377 && !ps.in_decl && ps.block_init_level == 0;
373 ps.decl_indent_done = false; 378 ps.decl_indent_done = false;
374 if (ps.extra_expr_indent == eei_last) 379 if (ps.extra_expr_indent == eei_last)
375 ps.extra_expr_indent = eei_no; 380 ps.extra_expr_indent = eei_no;
376 
377 lab.len = 0; 
378 code.len = 0; 
379 com.len = 0; 
380 
381 ps.ind_level = ps.ind_level_follow; 381 ps.ind_level = ps.ind_level_follow;
382 ps.line_start_nparen = ps.nparen; 382 ps.line_start_nparen = ps.nparen;
 383 ps.want_blank = false;
383 384
384 if (ps.nparen > 0) { 385 if (ps.nparen > 0) {
385 /* TODO: explain what negative indentation means */ 386 /* TODO: explain what negative indentation means */
386 paren_indent = -1 - ps.paren[ps.nparen - 1].indent; 387 paren_indent = -1 - ps.paren[ps.nparen - 1].indent;
387 debug_println("paren_indent is now %d", paren_indent); 388 debug_println("paren_indent is now %d", paren_indent);
388 } 389 }
389 390
390 ps.want_blank = false; 
391 out.line_kind = lk_other; 391 out.line_kind = lk_other;
392} 392}