indent: clean up and condense code No functional change.diff -r1.6 -r1.7 src/tests/usr.bin/indent/lsym_rbrace.c
(rillig)
--- 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 | |
25 | void | 25 | void | |
26 | function(void) | 26 | function(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 | |
40 | void function(void) {{{ body(); }}} | 40 | void function(void) {{{ body(); }}} | |
41 | //indent end | 41 | //indent end | |
42 | 42 | |||
43 | //indent run | 43 | //indent run | |
44 | void | 44 | void | |
45 | function(void) | 45 | function(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 | |
58 | struct point | 58 | struct point | |
59 | origin(void) | 59 | origin(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 | { | |||
73 | int numbers[][] = { | |||
74 | {11}, | |||
75 | {21}, | |||
76 | {31}, | |||
77 | }; | |||
78 | int 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 |
--- 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 | |||
54 | struct options opt = { | 54 | struct 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 | |||
75 | struct parser_state ps; | 75 | struct parser_state ps; | |
76 | 76 | |||
77 | struct buffer token; | 77 | struct buffer token; | |
78 | 78 | |||
79 | struct buffer lab; | 79 | struct buffer lab; | |
80 | struct buffer code; | 80 | struct buffer code; | |
81 | struct buffer com; | 81 | struct buffer com; | |
82 | 82 | |||
83 | bool found_err; | 83 | bool found_err; | |
84 | bool had_eof; | 84 | bool had_eof; | |
85 | int line_no = 1; | 85 | int line_no = 1; | |
86 | enum indent_enabled indent_enabled; | 86 | enum indent_enabled indent_enabled; | |
87 | 87 | |||
88 | static int ifdef_level; | 88 | static int ifdef_level; | |
89 | static struct parser_state state_stack[5]; | 89 | static struct parser_state state_stack[5]; | |
90 | 90 | |||
91 | FILE *input; | 91 | FILE *input; | |
92 | FILE *output; | 92 | FILE *output; | |
93 | 93 | |||
94 | static const char *in_name = "Standard Input"; | 94 | static const char *in_name = "Standard Input"; | |
95 | static const char *out_name = "Standard Output"; | 95 | static const char *out_name = "Standard Output"; | |
96 | static const char *backup_suffix = ".BAK"; | 96 | static const char *backup_suffix = ".BAK"; | |
97 | static char bakfile[MAXPATHLEN] = ""; | 97 | static char bakfile[MAXPATHLEN] = ""; | |
98 | 98 | |||
99 | 99 | |||
100 | void * | 100 | void * | |
101 | nonnull(void *p) | 101 | nonnull(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 | |||
108 | static void | 108 | static void | |
109 | buf_expand(struct buffer *buf, size_t add_size) | 109 | buf_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 | |||
115 | void | 115 | void | |
116 | buf_add_char(struct buffer *buf, char ch) | 116 | buf_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 | |||
123 | void | 123 | void | |
124 | buf_add_chars(struct buffer *buf, const char *s, size_t len) | 124 | buf_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 | |||
134 | static void | 134 | static void | |
135 | buf_add_buf(struct buffer *buf, const struct buffer *add) | 135 | buf_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 | |||
140 | void | 140 | void | |
141 | diag(int level, const char *msg, ...) | 141 | diag(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 | */ | |
160 | int | 160 | int | |
161 | ind_add(int ind, const char *s, size_t len) | 161 | ind_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 | |||
176 | static void | 176 | static void | |
177 | init_globals(void) | 177 | init_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 | */ | |
193 | static void | 193 | static void | |
194 | bakcopy(void) | 194 | bakcopy(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 | |||
230 | static void | 230 | static void | |
231 | load_profiles(int argc, char **argv) | 231 | load_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 | |||
247 | static void | 247 | static void | |
248 | parse_command_line(int argc, char **argv) | 248 | parse_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 | |||
296 | static void | 296 | static void | |
297 | set_initial_indentation(void) | 297 | set_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 | |||
314 | static void | 314 | static void | |
315 | code_add_decl_indent(int decl_ind, bool tabs_to_var) | 315 | indent_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 | |||
335 | static void | 336 | static void | |
336 | update_ps_decl_ptr(lexer_symbol lsym) | 337 | update_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 | |||
354 | static void | 355 | static void | |
355 | update_ps_prev_tag(lexer_symbol lsym) | 356 | update_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 | |||
367 | static int | 368 | static int | |
368 | process_eof(void) | 369 | process_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 | |||
384 | static void | 385 | static void | |
385 | maybe_break_line(lexer_symbol lsym) | 386 | maybe_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 | |||
399 | static void | 400 | static void | |
400 | move_com_to_code(lexer_symbol lsym) | 401 | move_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 | |||
409 | static void | 410 | static void | |
410 | process_newline(void) | 411 | process_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 | |||
426 | stay_in_line: | 427 | stay_in_line: | |
427 | ++line_no; | 428 | ++line_no; | |
428 | } | 429 | } | |
429 | 430 | |||
430 | static bool | 431 | static bool | |
431 | is_function_pointer_declaration(void) | 432 | is_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 | |||
440 | static bool | 441 | static bool | |
441 | want_blank_before_lparen(void) | 442 | want_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 | |||
458 | static void | 459 | static void | |
459 | process_lparen(void) | 460 | process_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 | |||
507 | static bool | |||
508 | want_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 | ||||
519 | static void | 507 | static void | |
520 | process_lbracket(void) | 508 | process_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 | |||
540 | static void | 528 | static void | |
541 | process_rparen(void) | 529 | process_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 | |||
561 | unbalanced: | 549 | unbalanced: | |
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 | |||
577 | static void | 565 | static void | |
578 | process_rbracket(void) | 566 | process_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 | |||
590 | unbalanced: | 578 | unbalanced: | |
591 | buf_add_char(&code, token.s[0]); | 579 | buf_add_char(&code, token.s[0]); | |
592 | } | 580 | } | |
593 | 581 | |||
594 | static bool | |||
595 | want_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 | ||||
604 | static void | 582 | static void | |
605 | process_unary_op(void) | 583 | process_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 | |||
620 | static void | 593 | if (ps.want_blank) | |
621 | process_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 | |||
629 | static void | 599 | static void | |
630 | process_postfix_op(void) | 600 | process_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 | |||
636 | static void | 606 | static void | |
637 | process_question(void) | 607 | process_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 | |||
651 | static void | 617 | static void | |
652 | process_colon_question(void) | 618 | process_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 | |||
665 | static void | 627 | static void | |
666 | process_colon_label(void) | 628 | process_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 | |||
680 | static void | 642 | static void | |
681 | process_colon_other(void) | 643 | process_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 | |||
687 | static void | 649 | static void | |
688 | process_semicolon(void) | 650 | process_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 | |||
735 | static void | 696 | static void | |
736 | process_lbrace(void) | 697 | process_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 | |||
808 | static void | 769 | static void | |
809 | process_rbrace(void) | 770 | process_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 | |||
850 | static void | 811 | static void | |
851 | process_do(void) | 812 | process_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 | |||
863 | static void | 824 | static void | |
864 | process_else(void) | 825 | process_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 | |||
876 | static void | 837 | static void | |
877 | process_type(void) | 838 | process_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 | |||
905 | static void | 864 | static void | |
906 | process_ident(lexer_symbol lsym) | 865 | process_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 | |||
937 | static void | 894 | static void | |
938 | process_period(void) | 895 | process_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 | |||
946 | static void | 903 | static void | |
947 | process_comma(void) | 904 | process_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 */ | |
973 | static void | 929 | static void | |
974 | read_preprocessing_line(void) | 930 | read_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 | |||
1020 | static void | 976 | static void | |
1021 | process_preprocessing(void) | 977 | process_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 | |||
1062 | static void | 1014 | static void | |
1063 | process_lsym(lexer_symbol lsym) | 1015 | process_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); | |
1175 | copy_token: | 1065 | copy_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 | |||
1204 | static int | 1078 | static int | |
1205 | indent(void) | 1079 | indent(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 | |||
1252 | int | 1122 | int | |
1253 | main(int argc, char **argv) | 1123 | main(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 | } |
--- 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 | |||
71 | typedef enum lexer_symbol { | 71 | typedef 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 | */ | |
119 | typedef enum parser_symbol { | 119 | typedef 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. */ | |
141 | struct buffer { | 141 | struct 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 | |||
147 | extern FILE *input; | 147 | extern FILE *input; | |
148 | extern FILE *output; | 148 | extern 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 | */ | |
157 | extern struct buffer inp; | 157 | extern struct buffer inp; | |
158 | extern const char *inp_p; | 158 | extern const char *inp_p; | |
159 | 159 | |||
160 | extern struct buffer token; /* the current token to be processed, is | 160 | extern 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 | |||
164 | extern struct buffer lab; /* the label or preprocessor directive */ | 164 | extern struct buffer lab; /* the label or preprocessor directive */ | |
165 | extern struct buffer code; /* the main part of the current line of code, | 165 | extern struct buffer code; /* the main part of the current line of code, | |
166 | * containing declarations or statements */ | 166 | * containing declarations or statements */ | |
167 | extern struct buffer com; /* the trailing comment of the line, or the | 167 | extern 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 | |||
172 | extern struct options { | 172 | extern 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 | |||
249 | extern bool found_err; | 249 | extern bool found_err; | |
250 | extern bool had_eof; /* whether input is exhausted */ | 250 | extern bool had_eof; /* whether input is exhausted */ | |
251 | extern int line_no; /* the current line number. */ | 251 | extern int line_no; /* the current line number. */ | |
252 | extern enum indent_enabled { | 252 | extern 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. */ | |
261 | typedef struct paren_level_props { | 261 | typedef 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 | |||
272 | struct psym_stack { | 272 | struct 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 | */ | |
296 | extern struct parser_state { | 296 | extern 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 | |||
421 | extern struct output_state { | 420 | extern 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 | |
448 | void debug_printf(const char *, ...) __printflike(1, 2); | 447 | void debug_printf(const char *, ...) __printflike(1, 2); | |
449 | void debug_println(const char *, ...) __printflike(1, 2); | 448 | void debug_println(const char *, ...) __printflike(1, 2); | |
450 | void debug_blank_line(void); | 449 | void debug_blank_line(void); | |
451 | void debug_vis_range(const char *, const char *, size_t, const char *); | 450 | void debug_vis_range(const char *, const char *, size_t, const char *); | |
452 | void debug_parser_state(void); | 451 | void debug_parser_state(void); | |
453 | void debug_parse_stack(const char *); | 452 | void debug_parse_stack(const char *); | |
454 | void debug_print_buf(const char *, const struct buffer *); | 453 | void debug_print_buf(const char *, const struct buffer *); | |
455 | void debug_buffers(void); | 454 | void debug_buffers(void); | |
456 | extern const char *const lsym_name[]; | 455 | extern const char *const lsym_name[]; | |
457 | extern const char *const psym_name[]; | 456 | extern const char *const psym_name[]; | |
458 | extern const char *const paren_level_cast_name[]; | 457 | extern const char *const paren_level_cast_name[]; | |
459 | extern const char *const line_kind_name[]; | 458 | extern 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 | |||
472 | void register_typename(const char *); | 471 | void register_typename(const char *); | |
473 | int compute_code_indent(void); | 472 | int compute_code_indent(void); | |
474 | int compute_label_indent(void); | 473 | int compute_label_indent(void); | |
475 | int ind_add(int, const char *, size_t); | 474 | int ind_add(int, const char *, size_t); | |
476 | 475 | |||
477 | void inp_skip(void); | 476 | void inp_skip(void); | |
478 | char inp_next(void); | 477 | char inp_next(void); | |
479 | 478 | |||
480 | lexer_symbol lexi(void); | 479 | lexer_symbol lexi(void); | |
481 | void diag(int, const char *, ...) __printflike(2, 3); | 480 | void diag(int, const char *, ...) __printflike(2, 3); | |
482 | void output_line(void); | 481 | void output_line(void); | |
483 | void inp_read_line(void); | 482 | void inp_read_line(void); | |
484 | void parse(parser_symbol); | 483 | void parse(parser_symbol); | |
485 | void process_comment(void); | 484 | void process_comment(void); | |
486 | void set_option(const char *, const char *); | 485 | void set_option(const char *, const char *); | |
487 | void load_profile_files(const char *); | 486 | void load_profile_files(const char *); | |
488 | 487 | |||
489 | void *nonnull(void *); | 488 | void *nonnull(void *); | |
490 | 489 | |||
491 | void buf_add_char(struct buffer *, char); | 490 | void buf_add_char(struct buffer *, char); | |
492 | void buf_add_chars(struct buffer *, const char *, size_t); | 491 | void buf_add_chars(struct buffer *, const char *, size_t); | |
493 | 492 | |||
494 | static inline bool | 493 | static inline bool | |
495 | ch_isalnum(char ch) | 494 | ch_isalnum(char ch) | |
496 | { | 495 | { | |
497 | return isalnum((unsigned char)ch) != 0; | 496 | return isalnum((unsigned char)ch) != 0; | |
498 | } | 497 | } | |
499 | 498 | |||
500 | static inline bool | 499 | static inline bool | |
501 | ch_isalpha(char ch) | 500 | ch_isalpha(char ch) | |
502 | { | 501 | { | |
503 | return isalpha((unsigned char)ch) != 0; | 502 | return isalpha((unsigned char)ch) != 0; | |
504 | } | 503 | } | |
505 | 504 | |||
506 | static inline bool | 505 | static inline bool | |
507 | ch_isblank(char ch) | 506 | ch_isblank(char ch) | |
508 | { | 507 | { | |
509 | return ch == ' ' || ch == '\t'; | 508 | return ch == ' ' || ch == '\t'; | |
510 | } | 509 | } | |
511 | 510 | |||
512 | static inline bool | 511 | static inline bool | |
513 | ch_isdigit(char ch) | 512 | ch_isdigit(char ch) | |
514 | { | 513 | { | |
515 | return '0' <= ch && ch <= '9'; | 514 | return '0' <= ch && ch <= '9'; | |
516 | } | 515 | } | |
517 | 516 | |||
518 | static inline bool | 517 | static inline bool | |
519 | ch_isspace(char ch) | 518 | ch_isspace(char ch) | |
520 | { | 519 | { | |
521 | return isspace((unsigned char)ch) != 0; | 520 | return isspace((unsigned char)ch) != 0; | |
522 | } | 521 | } | |
523 | 522 | |||
524 | static inline int | 523 | static inline int | |
525 | next_tab(int ind) | 524 | next_tab(int ind) | |
526 | { | 525 | { | |
527 | return ind - ind % opt.tabsize + opt.tabsize; | 526 | return ind - ind % opt.tabsize + opt.tabsize; | |
528 | } | 527 | } |
--- 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 | |||
47 | struct buffer inp; | 47 | struct buffer inp; | |
48 | const char *inp_p; | 48 | const char *inp_p; | |
49 | 49 | |||
50 | struct output_state out; | 50 | struct output_state out; | |
51 | static int out_ind; /* width of the line that is being written */ | 51 | static int out_ind; /* width of the line that is being written */ | |
52 | static unsigned wrote_newlines = 2; /* 0 in the middle of a line, 1 after a | 52 | static 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 */ | |
55 | static int paren_indent; | 55 | static int paren_indent; | |
56 | 56 | |||
57 | 57 | |||
58 | static void | 58 | static void | |
59 | inp_read_next_line(FILE *f) | 59 | inp_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 | |||
82 | void | 82 | void | |
83 | inp_read_line(void) | 83 | inp_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 | |||
91 | void | 91 | void | |
92 | inp_skip(void) | 92 | inp_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 | |||
99 | char | 99 | char | |
100 | inp_next(void) | 100 | inp_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 | |||
108 | static void | 108 | static void | |
109 | output_newline(void) | 109 | output_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 | |||
117 | static void | 117 | static void | |
118 | output_range(const char *s, size_t len) | 118 | output_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 | |||
127 | static void | 127 | static void | |
128 | output_indent(int new_ind) | 128 | output_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 | |||
151 | static bool | 151 | static bool | |
152 | want_blank_line(void) | 152 | want_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 | |||
177 | static bool | 177 | static bool | |
178 | is_blank_line_optional(void) | 178 | is_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 | |||
187 | static int | 187 | static int | |
188 | compute_case_label_indent(void) | 188 | compute_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 | |||
197 | int | 197 | int | |
198 | compute_label_indent(void) | 198 | compute_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 | |||
207 | static void | 207 | static void | |
208 | output_line_label(void) | 208 | output_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 | |||
214 | static int | 214 | static int | |
215 | compute_code_indent_lineup(int base_ind) | 215 | compute_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 | |||
232 | int | 232 | int | |
233 | compute_code_indent(void) | 233 | compute_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 | |||
262 | static void | 262 | static void | |
263 | output_line_code(void) | 263 | output_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 | |||
283 | static void | 283 | static void | |
284 | output_line_comment(void) | 284 | output_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 | */ | |
320 | void | 320 | void | |
321 | output_line(void) | 321 | output_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 | |||
369 | dont_write_line: | 369 | prepare_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 | } |