Fri Jun 16 12:55:57 2023 UTC ()
indent: improve heuristics for casts


(rillig)
diff -r1.8 -r1.9 src/tests/usr.bin/indent/fmt_expr.c
diff -r1.10 -r1.11 src/tests/usr.bin/indent/lsym_unary_op.c
diff -r1.374 -r1.375 src/usr.bin/indent/indent.c

cvs diff -r1.8 -r1.9 src/tests/usr.bin/indent/fmt_expr.c (switch to unified diff)

--- src/tests/usr.bin/indent/fmt_expr.c 2023/06/14 17:07:32 1.8
+++ src/tests/usr.bin/indent/fmt_expr.c 2023/06/16 12:55:57 1.9
@@ -1,60 +1,59 @@ @@ -1,60 +1,59 @@
1/* $NetBSD: fmt_expr.c,v 1.8 2023/06/14 17:07:32 rillig Exp $ */ 1/* $NetBSD: fmt_expr.c,v 1.9 2023/06/16 12:55:57 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for all kinds of expressions that are not directly related to unary 4 * Tests for all kinds of expressions that are not directly related to unary
5 * or binary operators. 5 * or binary operators.
6 * 6 *
7 * See also: 7 * See also:
8 * lsym_binary_op.c 8 * lsym_binary_op.c
9 * lsym_unary_op.c 9 * lsym_unary_op.c
10 */ 10 */
11 11
12//indent input 12//indent input
13{ 13{
14 // See lsym_offsetof.c. 14 // See lsym_offsetof.c.
15 malloc(offsetof(struct s, f) + 1); 15 malloc(offsetof(struct s, f) + 1);
16 16
17 // C99 compound literals use initializer braces. 17 // C99 compound literals use initializer braces.
18 println((const char[3]){'-', c, '\0'}); 18 println((const char[3]){'-', c, '\0'});
19 x = ((struct point){0, 0}).x; 19 x = ((struct point){0, 0}).x;
20 20
21 for (ln = gnodes->first; ln != NULL; ln = ln->next) 21 for (ln = gnodes->first; ln != NULL; ln = ln->next)
22// $ FIXME: No space after the cast. 22 *(GNode **)Vector_Push(&vec) = ln->datum;
23 *(GNode **) Vector_Push(&vec) = ln->datum; 
24} 23}
25//indent end 24//indent end
26 25
27//indent run-equals-input 26//indent run-equals-input
28 27
29 28
30/* 29/*
31 * GCC statement expressions are not supported yet. 30 * GCC statement expressions are not supported yet.
32 */ 31 */
33//indent input 32//indent input
34{ 33{
35 int var = ({1}); 34 int var = ({1});
36 int var = ({ 35 int var = ({
37 1 36 1
38 }); 37 });
39 int var = ({ 38 int var = ({
40 int decl = 1; 39 int decl = 1;
41 stmt; 40 stmt;
42 }); 41 });
43} 42}
44//indent end 43//indent end
45 44
46//indent run -di0 45//indent run -di0
47{ 46{
48 int var = ({1}); 47 int var = ({1});
49 int var = ({ 48 int var = ({
50 1 49 1
51 }); 50 });
52 int var = ({ 51 int var = ({
53 int decl = 1; 52 int decl = 1;
54 stmt; 53 stmt;
55 }); 54 });
56} 55}
57exit 1 56exit 1
58error: Standard Input:7: Unbalanced parentheses 57error: Standard Input:7: Unbalanced parentheses
59warning: Standard Input:9: Extra ')' 58warning: Standard Input:9: Extra ')'
60//indent end 59//indent end

cvs diff -r1.10 -r1.11 src/tests/usr.bin/indent/lsym_unary_op.c (switch to unified diff)

--- src/tests/usr.bin/indent/lsym_unary_op.c 2023/06/08 21:18:54 1.10
+++ src/tests/usr.bin/indent/lsym_unary_op.c 2023/06/16 12:55:57 1.11
@@ -1,101 +1,94 @@ @@ -1,101 +1,94 @@
1/* $NetBSD: lsym_unary_op.c,v 1.10 2023/06/08 21:18:54 rillig Exp $ */ 1/* $NetBSD: lsym_unary_op.c,v 1.11 2023/06/16 12:55:57 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the token lsym_unary_op, which represents a unary operator. 4 * Tests for the token lsym_unary_op, which represents a unary operator.
5 * 5 *
6 * In an expression, a unary operator is written without blank next to its 6 * In an expression, a unary operator is written without blank next to its
7 * argument. 7 * argument.
8 * 8 *
9 * In a type name, the "unary operator" '*' represents the derivation of a 9 * In a type name, the "unary operator" '*' represents the derivation of a
10 * pointer type. 10 * pointer type.
11 * 11 *
12 * See also: 12 * See also:
13 * lsym_binary_op.c 13 * lsym_binary_op.c
14 * lsym_postfix_op.c 14 * lsym_postfix_op.c
15 * C11 6.4.6 "Punctuators" 15 * C11 6.4.6 "Punctuators"
16 * C11 6.5 "Expressions" 16 * C11 6.5 "Expressions"
17 */ 17 */
18 18
19//indent input 19//indent input
20void 20void
21unary_operators(void) 21unary_operators(void)
22{ 22{
23 /* In the order of appearance in C11 6.5. */ 23 /* In the order of appearance in C11 6.5. */
24 function(a++, a--, ++a, --a, &a, *a, +a, -a, ~a, !a); 24 function(a++, a--, ++a, --a, &a, *a, +a, -a, ~a, !a);
25} 25}
26//indent end 26//indent end
27 27
28//indent run-equals-input 28//indent run-equals-input
29 29
30 30
31/* 31/*
32 * The unary operators '+' and '-' can occur in long chains. In these chains, 32 * The unary operators '+' and '-' can occur in long chains. In these chains,
33 * adjacent '+' must not be merged to '++' since that would be a different 33 * adjacent '+' must not be merged to '++' since that would be a different
34 * token. The same applies to '&', but that case is irrelevant in practice 34 * token. The same applies to '&', but that case is irrelevant in practice
35 * since the address of an address cannot be taken. 35 * since the address of an address cannot be taken.
36 */ 36 */
37//indent input 37//indent input
38int var=+3; 38int var=+3;
39int mixed=+-+-+-+-+-+-+-+-+-+-+-+-+-3; 39int mixed=+-+-+-+-+-+-+-+-+-+-+-+-+-3;
40int count=~-~-~-~-~-~-~-~-~-~-~-~-~-3; 40int count=~-~-~-~-~-~-~-~-~-~-~-~-~-3;
41int same = + + + + + - - - - - 3; 41int same = + + + + + - - - - - 3;
42//indent end 42//indent end
43 43
44//indent run -di0 44//indent run -di0
45int var = +3; 45int var = +3;
46int mixed = +-+-+-+-+-+-+-+-+-+-+-+-+-3; 46int mixed = +-+-+-+-+-+-+-+-+-+-+-+-+-3;
47int count = ~-~-~-~-~-~-~-~-~-~-~-~-~-3; 47int count = ~-~-~-~-~-~-~-~-~-~-~-~-~-3;
48int same = + + + + +- - - - -3; 48int same = + + + + +- - - - -3;
49//indent end 49//indent end
50 50
51 51
52/* 52/*
53 * A special kind of unary operator is '->', which additionally suppresses the 53 * A special kind of unary operator is '->', which additionally suppresses the
54 * next space. 54 * next space.
55 */ 55 */
56//indent input 56//indent input
57int var = p -> member; 57int var = p -> member;
58//indent end 58//indent end
59 59
60//indent run -di0 60//indent run -di0
61int var = p->member; 61int var = p->member;
62//indent end 62//indent end
63 63
64 64
65//indent input 65//indent input
66void 66void
67unary_operators(void) 67unary_operators(void)
68{ 68{
69 ++prefix_increment; 69 ++prefix_increment;
70 --prefix_decrement; 70 --prefix_decrement;
71 int *address = &lvalue; 71 int *address = &lvalue;
72 int dereferenced = *address; 72 int dereferenced = *address;
73 int positive = +number; 73 int positive = +number;
74 int negative = -number; 74 int negative = -number;
75 bool negated = !condition; 75 bool negated = !condition;
76} 76}
77//indent end 77//indent end
78 78
79//indent run-equals-input -di0 79//indent run-equals-input -di0
80 80
81 81
82/* 82/*
83 * Ensure that a '*' is not interpreted as unary operator in situations that 83 * Ensure that a '*' is not interpreted as unary operator in situations that
84 * may look like a cast expression. 84 * may look like a cast expression.
85 */ 85 */
86//indent input 86//indent input
87{ 87{
88sbuf_t *sb = *(sbuf_t **)sp; 88 sbuf_t *sb = *(sbuf_t **)sp;
89return (int)(a * (float)b); 
90a = (2 * b == c); 
91} 
92//indent end 
93 
94//indent run -di0 
95{ 
96// $ FIXME: Wrong spacing after the cast. 
97 sbuf_t *sb = *(sbuf_t **) sp; 
98 return (int)(a * (float)b); 89 return (int)(a * (float)b);
99 a = (2 * b == c); 90 a = (2 * b == c);
100} 91}
101//indent end 92//indent end
 93
 94//indent run-equals-input -di0

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

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