indent: miscellaneous cleanups No binary change.diff -r1.66 -r1.67 src/usr.bin/indent/debug.c
(rillig)
--- src/usr.bin/indent/debug.c 2023/06/16 23:51:32 1.66
+++ src/usr.bin/indent/debug.c 2023/06/17 22:28:49 1.67
@@ -1,392 +1,392 @@ | @@ -1,392 +1,392 @@ | |||
1 | /* $NetBSD: debug.c,v 1.66 2023/06/16 23:51:32 rillig Exp $ */ | 1 | /* $NetBSD: debug.c,v 1.67 2023/06/17 22:28:49 rillig Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2023 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2023 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Roland Illig <rillig@NetBSD.org>. | 8 | * by Roland Illig <rillig@NetBSD.org>. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __RCSID("$NetBSD: debug.c,v 1.66 2023/06/16 23:51:32 rillig Exp $"); | 33 | __RCSID("$NetBSD: debug.c,v 1.67 2023/06/17 22:28:49 rillig Exp $"); | |
34 | 34 | |||
35 | #include <stdarg.h> | 35 | #include <stdarg.h> | |
36 | #include <string.h> | 36 | #include <string.h> | |
37 | 37 | |||
38 | #include "indent.h" | 38 | #include "indent.h" | |
39 | 39 | |||
40 | #ifdef debug | 40 | #ifdef debug | |
41 | 41 | |||
42 | static struct { | 42 | static struct { | |
43 | // false show only the changes to the parser state | 43 | // false show only the changes to the parser state | |
44 | // true show unchanged parts of the parser state as well | 44 | // true show unchanged parts of the parser state as well | |
45 | bool full_parser_state; | 45 | bool full_parser_state; | |
46 | } config = { | 46 | } config = { | |
47 | .full_parser_state = false, | 47 | .full_parser_state = false, | |
48 | }; | 48 | }; | |
49 | 49 | |||
50 | const char *const lsym_name[] = { | 50 | const char *const lsym_name[] = { | |
51 | "eof", | 51 | "eof", | |
52 | "preprocessing", | 52 | "preprocessing", | |
53 | "newline", | 53 | "newline", | |
54 | "comment", | 54 | "comment", | |
55 | "lparen", | 55 | "lparen", | |
56 | "rparen", | 56 | "rparen", | |
57 | "lbracket", | 57 | "lbracket", | |
58 | "rbracket", | 58 | "rbracket", | |
59 | "lbrace", | 59 | "lbrace", | |
60 | "rbrace", | 60 | "rbrace", | |
61 | "period", | 61 | "period", | |
62 | "unary_op", | 62 | "unary_op", | |
63 | "sizeof", | 63 | "sizeof", | |
64 | "offsetof", | 64 | "offsetof", | |
65 | "postfix_op", | 65 | "postfix_op", | |
66 | "binary_op", | 66 | "binary_op", | |
67 | "question", | 67 | "question", | |
68 | "question_colon", | 68 | "question_colon", | |
69 | "comma", | 69 | "comma", | |
70 | "typedef", | 70 | "typedef", | |
71 | "modifier", | 71 | "modifier", | |
72 | "tag", | 72 | "tag", | |
73 | "type", | 73 | "type", | |
74 | "word", | 74 | "word", | |
75 | "funcname", | 75 | "funcname", | |
76 | "label_colon", | 76 | "label_colon", | |
77 | "other_colon", | 77 | "other_colon", | |
78 | "semicolon", | 78 | "semicolon", | |
79 | "case", | 79 | "case", | |
80 | "default", | 80 | "default", | |
81 | "do", | 81 | "do", | |
82 | "else", | 82 | "else", | |
83 | "for", | 83 | "for", | |
84 | "if", | 84 | "if", | |
85 | "switch", | 85 | "switch", | |
86 | "while", | 86 | "while", | |
87 | "return", | 87 | "return", | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | const char *const psym_name[] = { | 90 | const char *const psym_name[] = { | |
91 | "-", | 91 | "-", | |
92 | "{block", | 92 | "{block", | |
93 | "{struct", | 93 | "{struct", | |
94 | "{union", | 94 | "{union", | |
95 | "{enum", | 95 | "{enum", | |
96 | "}", | 96 | "}", | |
97 | "decl", | 97 | "decl", | |
98 | "stmt", | 98 | "stmt", | |
99 | "for_exprs", | 99 | "for_exprs", | |
100 | "if_expr", | 100 | "if_expr", | |
101 | "if_expr_stmt", | 101 | "if_expr_stmt", | |
102 | "if_expr_stmt_else", | 102 | "if_expr_stmt_else", | |
103 | "else", | 103 | "else", | |
104 | "switch_expr", | 104 | "switch_expr", | |
105 | "do", | 105 | "do", | |
106 | "do_stmt", | 106 | "do_stmt", | |
107 | "while_expr", | 107 | "while_expr", | |
108 | }; | 108 | }; | |
109 | 109 | |||
110 | static const char *const declaration_name[] = { | 110 | static const char *const declaration_name[] = { | |
111 | "no", | 111 | "no", | |
112 | "begin", | 112 | "begin", | |
113 | "end", | 113 | "end", | |
114 | }; | 114 | }; | |
115 | 115 | |||
116 | const char *const paren_level_cast_name[] = { | 116 | const char *const paren_level_cast_name[] = { | |
117 | "(unknown cast)", | 117 | "(unknown cast)", | |
118 | "(maybe cast)", | 118 | "(maybe cast)", | |
119 | "(no cast)", | 119 | "(no cast)", | |
120 | }; | 120 | }; | |
121 | 121 | |||
122 | const char *const line_kind_name[] = { | 122 | const char *const line_kind_name[] = { | |
123 | "other", | 123 | "other", | |
124 | "blank", | 124 | "blank", | |
125 | "#if", | 125 | "#if", | |
126 | "#endif", | 126 | "#endif", | |
127 | "#other", | 127 | "#other", | |
128 | "stmt head", | 128 | "stmt head", | |
129 | "}", | 129 | "}", | |
130 | "block comment", | 130 | "block comment", | |
131 | "case/default", | 131 | "case/default", | |
132 | }; | 132 | }; | |
133 | 133 | |||
134 | static const char *const extra_expr_indent_name[] = { | 134 | static const char *const extra_expr_indent_name[] = { | |
135 | "no", | 135 | "no", | |
136 | "maybe", | 136 | "maybe", | |
137 | "last", | 137 | "last", | |
138 | }; | 138 | }; | |
139 | 139 | |||
140 | static struct { | 140 | static struct { | |
141 | struct parser_state prev_ps; | 141 | struct parser_state prev_ps; | |
142 | bool ps_first; | 142 | bool ps_first; | |
143 | const char *heading; | 143 | const char *heading; | |
144 | unsigned wrote_newlines; | 144 | unsigned wrote_newlines; | |
145 | } state = { | 145 | } state = { | |
146 | .ps_first = true, | 146 | .ps_first = true, | |
147 | .wrote_newlines = 1, | 147 | .wrote_newlines = 1, | |
148 | }; | 148 | }; | |
149 | 149 | |||
150 | void | 150 | void | |
151 | debug_printf(const char *fmt, ...) | 151 | debug_printf(const char *fmt, ...) | |
152 | { | 152 | { | |
153 | FILE *f = output == stdout ? stderr : stdout; | 153 | FILE *f = output == stdout ? stderr : stdout; | |
154 | va_list ap; | 154 | va_list ap; | |
155 | 155 | |||
156 | if (state.heading != NULL) { | 156 | if (state.heading != NULL) { | |
157 | fprintf(f, "%s\n", state.heading); | 157 | fprintf(f, "%s\n", state.heading); | |
158 | state.heading = NULL; | 158 | state.heading = NULL; | |
159 | } | 159 | } | |
160 | va_start(ap, fmt); | 160 | va_start(ap, fmt); | |
161 | vfprintf(f, fmt, ap); | 161 | vfprintf(f, fmt, ap); | |
162 | va_end(ap); | 162 | va_end(ap); | |
163 | state.wrote_newlines = 0; | 163 | state.wrote_newlines = 0; | |
164 | } | 164 | } | |
165 | 165 | |||
166 | void | 166 | void | |
167 | debug_println(const char *fmt, ...) | 167 | debug_println(const char *fmt, ...) | |
168 | { | 168 | { | |
169 | FILE *f = output == stdout ? stderr : stdout; | 169 | FILE *f = output == stdout ? stderr : stdout; | |
170 | va_list ap; | 170 | va_list ap; | |
171 | 171 | |||
172 | if (state.heading != NULL) { | 172 | if (state.heading != NULL) { | |
173 | fprintf(f, "%s\n", state.heading); | 173 | fprintf(f, "%s\n", state.heading); | |
174 | state.heading = NULL; | 174 | state.heading = NULL; | |
175 | state.wrote_newlines = 1; | 175 | state.wrote_newlines = 1; | |
176 | } | 176 | } | |
177 | va_start(ap, fmt); | 177 | va_start(ap, fmt); | |
178 | vfprintf(f, fmt, ap); | 178 | vfprintf(f, fmt, ap); | |
179 | va_end(ap); | 179 | va_end(ap); | |
180 | fprintf(f, "\n"); | 180 | fprintf(f, "\n"); | |
181 | state.wrote_newlines = fmt[0] == '\0' ? state.wrote_newlines + 1 : 1; | 181 | state.wrote_newlines = fmt[0] == '\0' ? state.wrote_newlines + 1 : 1; | |
182 | } | 182 | } | |
183 | 183 | |||
184 | void | 184 | void | |
185 | debug_blank_line(void) | 185 | debug_blank_line(void) | |
186 | { | 186 | { | |
187 | while (state.wrote_newlines < 2) | 187 | while (state.wrote_newlines < 2) | |
188 | debug_println(""); | 188 | debug_println(""); | |
189 | } | 189 | } | |
190 | 190 | |||
191 | void | 191 | void | |
192 | debug_vis_range(const char *s, size_t len) | 192 | debug_vis_range(const char *s, size_t len) | |
193 | { | 193 | { | |
194 | debug_printf("\""); | 194 | debug_printf("\""); | |
195 | for (size_t i = 0; i < len; i++) { | 195 | for (size_t i = 0; i < len; i++) { | |
196 | const char *p = s + i; | 196 | const char *p = s + i; | |
197 | if (*p == '\\' || *p == '"') | 197 | if (*p == '\\' || *p == '"') | |
198 | debug_printf("\\%c", *p); | 198 | debug_printf("\\%c", *p); | |
199 | else if (isprint((unsigned char)*p)) | 199 | else if (isprint((unsigned char)*p)) | |
200 | debug_printf("%c", *p); | 200 | debug_printf("%c", *p); | |
201 | else if (*p == '\n') | 201 | else if (*p == '\n') | |
202 | debug_printf("\\n"); | 202 | debug_printf("\\n"); | |
203 | else if (*p == '\t') | 203 | else if (*p == '\t') | |
204 | debug_printf("\\t"); | 204 | debug_printf("\\t"); | |
205 | else | 205 | else | |
206 | debug_printf("\\x%02x", (unsigned char)*p); | 206 | debug_printf("\\x%02x", (unsigned char)*p); | |
207 | } | 207 | } | |
208 | debug_printf("\""); | 208 | debug_printf("\""); | |
209 | } | 209 | } | |
210 | 210 | |||
211 | void | 211 | void | |
212 | debug_print_buf(const char *name, const struct buffer *buf) | 212 | debug_print_buf(const char *name, const struct buffer *buf) | |
213 | { | 213 | { | |
214 | if (buf->len > 0) { | 214 | if (buf->len > 0) { | |
215 | debug_printf(" %s ", name); | 215 | debug_printf(" %s ", name); | |
216 | debug_vis_range(buf->s, buf->len); | 216 | debug_vis_range(buf->s, buf->len); | |
217 | } | 217 | } | |
218 | } | 218 | } | |
219 | 219 | |||
220 | void | 220 | void | |
221 | debug_buffers(void) | 221 | debug_buffers(void) | |
222 | { | 222 | { | |
223 | debug_print_buf("label", &lab); | 223 | debug_print_buf("label", &lab); | |
224 | debug_print_buf("code", &code); | 224 | debug_print_buf("code", &code); | |
225 | debug_print_buf("comment", &com); | 225 | debug_print_buf("comment", &com); | |
226 | debug_blank_line(); | 226 | debug_blank_line(); | |
227 | } | 227 | } | |
228 | 228 | |||
229 | static void | 229 | static void | |
230 | debug_ps_bool_member(const char *name, bool prev, bool curr) | 230 | debug_ps_bool_member(const char *name, bool prev, bool curr) | |
231 | { | 231 | { | |
232 | if (!state.ps_first && curr != prev) { | 232 | if (!state.ps_first && curr != prev) { | |
233 | char diff = " -+x"[(prev ? 1 : 0) + (curr ? 2 : 0)]; | 233 | char diff = " -+x"[(prev ? 1 : 0) + (curr ? 2 : 0)]; | |
234 | debug_println(" [%c] ps.%s", diff, name); | 234 | debug_println(" [%c] ps.%s", diff, name); | |
235 | } else if (config.full_parser_state || state.ps_first) | 235 | } else if (config.full_parser_state || state.ps_first) | |
236 | debug_println(" [%c] ps.%s", curr ? 'x' : ' ', name); | 236 | debug_println(" [%c] ps.%s", curr ? 'x' : ' ', name); | |
237 | } | 237 | } | |
238 | 238 | |||
239 | static void | 239 | static void | |
240 | debug_ps_int_member(const char *name, int prev, int curr) | 240 | debug_ps_int_member(const char *name, int prev, int curr) | |
241 | { | 241 | { | |
242 | if (!state.ps_first && curr != prev) | 242 | if (!state.ps_first && curr != prev) | |
243 | debug_println(" %3d -> %3d ps.%s", prev, curr, name); | 243 | debug_println(" %3d -> %3d ps.%s", prev, curr, name); | |
244 | else if (config.full_parser_state || state.ps_first) | 244 | else if (config.full_parser_state || state.ps_first) | |
245 | debug_println(" %3d ps.%s", curr, name); | 245 | debug_println(" %3d ps.%s", curr, name); | |
246 | } | 246 | } | |
247 | 247 | |||
248 | static void | 248 | static void | |
249 | debug_ps_enum_member(const char *name, const char *prev, const char *curr) | 249 | debug_ps_enum_member(const char *name, const char *prev, const char *curr) | |
250 | { | 250 | { | |
251 | if (!state.ps_first && strcmp(prev, curr) != 0) | 251 | if (!state.ps_first && strcmp(prev, curr) != 0) | |
252 | debug_println(" %3s -> %3s ps.%s", prev, curr, name); | 252 | debug_println(" %3s -> %3s ps.%s", prev, curr, name); | |
253 | else if (config.full_parser_state || state.ps_first) | 253 | else if (config.full_parser_state || state.ps_first) | |
254 | debug_println(" %10s ps.%s", curr, name); | 254 | debug_println(" %10s ps.%s", curr, name); | |
255 | } | 255 | } | |
256 | 256 | |||
257 | static bool | 257 | static bool | |
258 | paren_stack_equal(const struct paren_stack *a, const struct paren_stack *b) | 258 | paren_stack_equal(const struct paren_stack *a, const struct paren_stack *b) | |
259 | { | 259 | { | |
260 | if (a->len != b->len) | 260 | if (a->len != b->len) | |
261 | return false; | 261 | return false; | |
262 | 262 | |||
263 | for (size_t i = 0, n = a->len; i < n; i++) | 263 | for (size_t i = 0, n = a->len; i < n; i++) | |
264 | if (a->item[i].indent != b->item[i].indent | 264 | if (a->item[i].indent != b->item[i].indent | |
265 | || a->item[i].cast != b->item[i].cast) | 265 | || a->item[i].cast != b->item[i].cast) | |
266 | return true; | 266 | return true; | |
267 | return false; | 267 | return false; | |
268 | } | 268 | } | |
269 | 269 | |||
270 | static void | 270 | static void | |
271 | debug_ps_paren(void) | 271 | debug_ps_paren(void) | |
272 | { | 272 | { | |
273 | if (!config.full_parser_state | 273 | if (!config.full_parser_state | |
274 | && paren_stack_equal(&state.prev_ps.paren, &ps.paren) | 274 | && paren_stack_equal(&state.prev_ps.paren, &ps.paren) | |
275 | && !state.ps_first) | 275 | && !state.ps_first) | |
276 | return; | 276 | return; | |
277 | 277 | |||
278 | debug_printf(" ps.paren:"); | 278 | debug_printf(" ps.paren:"); | |
279 | for (size_t i = 0; i < ps.paren.len; i++) { | 279 | for (size_t i = 0; i < ps.paren.len; i++) { | |
280 | debug_printf(" %s%d", | 280 | debug_printf(" %s%d", | |
281 | paren_level_cast_name[ps.paren.item[i].cast], | 281 | paren_level_cast_name[ps.paren.item[i].cast], | |
282 | ps.paren.item[i].indent); | 282 | ps.paren.item[i].indent); | |
283 | } | 283 | } | |
284 | if (ps.paren.len == 0) | 284 | if (ps.paren.len == 0) | |
285 | debug_printf(" none"); | 285 | debug_printf(" none"); | |
286 | debug_println(""); | 286 | debug_println(""); | |
287 | } | 287 | } | |
288 | 288 | |||
289 | static bool | 289 | static bool | |
290 | ps_di_stack_has_changed(void) | 290 | ps_di_stack_has_changed(void) | |
291 | { | 291 | { | |
292 | if (state.prev_ps.decl_level != ps.decl_level) | 292 | if (state.prev_ps.decl_level != ps.decl_level) | |
293 | return true; | 293 | return true; | |
294 | for (int i = 0; i < ps.decl_level; i++) | 294 | for (int i = 0; i < ps.decl_level; i++) | |
295 | if (state.prev_ps.di_stack[i] != ps.di_stack[i]) | 295 | if (state.prev_ps.di_stack[i] != ps.di_stack[i]) | |
296 | return true; | 296 | return true; | |
297 | return false; | 297 | return false; | |
298 | } | 298 | } | |
299 | 299 | |||
300 | static void | 300 | static void | |
301 | debug_ps_di_stack(void) | 301 | debug_ps_di_stack(void) | |
302 | { | 302 | { | |
303 | bool changed = ps_di_stack_has_changed(); | 303 | bool changed = ps_di_stack_has_changed(); | |
304 | if (!config.full_parser_state && !changed && !state.ps_first) | 304 | if (!config.full_parser_state && !changed && !state.ps_first) | |
305 | return; | 305 | return; | |
306 | 306 | |||
307 | debug_printf(" %s ps.di_stack:", changed ? "->" : " "); | 307 | debug_printf(" %s ps.di_stack:", changed ? "->" : " "); | |
308 | for (int i = 0; i < ps.decl_level; i++) | 308 | for (int i = 0; i < ps.decl_level; i++) | |
309 | debug_printf(" %d", ps.di_stack[i]); | 309 | debug_printf(" %d", ps.di_stack[i]); | |
310 | if (ps.decl_level == 0) | 310 | if (ps.decl_level == 0) | |
311 | debug_printf(" none"); | 311 | debug_printf(" none"); | |
312 | debug_println(""); | 312 | debug_println(""); | |
313 | } | 313 | } | |
314 | 314 | |||
315 | #define debug_ps_bool(name) \ | 315 | #define debug_ps_bool(name) \ | |
316 | debug_ps_bool_member(#name, state.prev_ps.name, ps.name) | 316 | debug_ps_bool_member(#name, state.prev_ps.name, ps.name) | |
317 | #define debug_ps_int(name) \ | 317 | #define debug_ps_int(name) \ | |
318 | debug_ps_int_member(#name, state.prev_ps.name, ps.name) | 318 | debug_ps_int_member(#name, state.prev_ps.name, ps.name) | |
319 | #define debug_ps_enum(name, names) \ | 319 | #define debug_ps_enum(name, names) \ | |
320 | debug_ps_enum_member(#name, (names)[state.prev_ps.name], \ | 320 | debug_ps_enum_member(#name, (names)[state.prev_ps.name], \ | |
321 | (names)[ps.name]) | 321 | (names)[ps.name]) | |
322 | 322 | |||
323 | void | 323 | void | |
324 | debug_parser_state(void) | 324 | debug_parser_state(void) | |
325 | { | 325 | { | |
326 | debug_blank_line(); | 326 | debug_blank_line(); | |
327 | 327 | |||
328 | state.heading = "token classification"; | 328 | state.heading = "token classification"; | |
329 | debug_ps_enum(prev_lsym, lsym_name); | 329 | debug_ps_enum(prev_lsym, lsym_name); | |
330 | debug_ps_bool(in_stmt_or_decl); | 330 | debug_ps_bool(in_stmt_or_decl); | |
331 | debug_ps_bool(in_decl); | 331 | debug_ps_bool(in_decl); | |
332 | debug_ps_bool(in_typedef_decl); | 332 | debug_ps_bool(in_typedef_decl); | |
333 | debug_ps_bool(in_var_decl); | 333 | debug_ps_bool(in_var_decl); | |
334 | debug_ps_bool(in_init); | 334 | debug_ps_bool(in_init); | |
335 | debug_ps_int(init_level); | 335 | debug_ps_int(init_level); | |
336 | debug_ps_bool(line_has_func_def); | 336 | debug_ps_bool(line_has_func_def); | |
337 | debug_ps_bool(in_func_def_params); | 337 | debug_ps_bool(in_func_def_params); | |
338 | debug_ps_bool(line_has_decl); | 338 | debug_ps_bool(line_has_decl); | |
339 | debug_ps_enum(lbrace_kind, psym_name); | 339 | debug_ps_enum(lbrace_kind, psym_name); | |
340 | debug_ps_enum(spaced_expr_psym, psym_name); | 340 | debug_ps_enum(spaced_expr_psym, psym_name); | |
341 | debug_ps_bool(seen_case); | 341 | debug_ps_bool(seen_case); | |
342 | debug_ps_bool(prev_paren_was_cast); | 342 | debug_ps_bool(prev_paren_was_cast); | |
343 | debug_ps_int(quest_level); | 343 | debug_ps_int(quest_level); | |
344 | 344 | |||
345 | state.heading = "indentation of statements and declarations"; | 345 | state.heading = "indentation of statements and declarations"; | |
346 | debug_ps_int(ind_level); | 346 | debug_ps_int(ind_level); | |
347 | debug_ps_int(ind_level_follow); | 347 | debug_ps_int(ind_level_follow); | |
348 | debug_ps_bool(line_is_stmt_cont); | 348 | debug_ps_bool(line_is_stmt_cont); | |
349 | debug_ps_int(decl_level); | 349 | debug_ps_int(decl_level); | |
350 | debug_ps_di_stack(); | 350 | debug_ps_di_stack(); | |
351 | debug_ps_bool(decl_indent_done); | 351 | debug_ps_bool(decl_indent_done); | |
352 | debug_ps_int(decl_ind); | 352 | debug_ps_int(decl_ind); | |
353 | debug_ps_bool(tabs_to_var); | 353 | debug_ps_bool(tabs_to_var); | |
354 | debug_ps_enum(extra_expr_indent, extra_expr_indent_name); | 354 | debug_ps_enum(extra_expr_indent, extra_expr_indent_name); | |
355 | 355 | |||
356 | // The parser symbol stack is printed in debug_psyms_stack instead. | 356 | // The parser symbol stack is printed in debug_psyms_stack instead. | |
357 | 357 | |||
358 | state.heading = "spacing inside a statement or declaration"; | 358 | state.heading = "spacing inside a statement or declaration"; | |
359 | debug_ps_bool(next_unary); | 359 | debug_ps_bool(next_unary); | |
360 | debug_ps_bool(want_blank); | 360 | debug_ps_bool(want_blank); | |
361 | debug_ps_int(ind_paren_level); | 361 | debug_ps_int(ind_paren_level); | |
362 | debug_ps_paren(); | 362 | debug_ps_paren(); | |
363 | 363 | |||
364 | state.heading = "indentation of comments"; | 364 | state.heading = "indentation of comments"; | |
365 | debug_ps_int(comment_ind); | 365 | debug_ps_int(comment_ind); | |
366 | debug_ps_int(comment_shift); | 366 | debug_ps_int(comment_shift); | |
367 | debug_ps_bool(comment_cont); | 367 | debug_ps_bool(comment_cont); | |
368 | 368 | |||
369 | state.heading = "vertical spacing"; | 369 | state.heading = "vertical spacing"; | |
370 | debug_ps_bool(break_after_comma); | 370 | debug_ps_bool(break_after_comma); | |
371 | debug_ps_bool(want_newline); | 371 | debug_ps_bool(want_newline); | |
372 | debug_ps_enum(declaration, declaration_name); | 372 | debug_ps_enum(declaration, declaration_name); | |
373 | debug_ps_bool(blank_line_after_decl); | 373 | debug_ps_bool(blank_line_after_decl); | |
374 | 374 | |||
375 | state.heading = NULL; | 375 | state.heading = NULL; | |
376 | debug_blank_line(); | 376 | debug_blank_line(); | |
377 | 377 | |||
378 | state.prev_ps = ps; | 378 | state.prev_ps = ps; | |
379 | state.ps_first = false; | 379 | state.ps_first = false; | |
380 | } | 380 | } | |
381 | 381 | |||
382 | void | 382 | void | |
383 | debug_psyms_stack(const char *situation) | 383 | debug_psyms_stack(const char *situation) | |
384 | { | 384 | { | |
385 | debug_printf("parse stack %s:", situation); | 385 | debug_printf("parse stack %s:", situation); | |
386 | const struct psym_stack *psyms = &ps.psyms; | 386 | const struct psym_stack *psyms = &ps.psyms; | |
387 | for (size_t i = 0; i < psyms->len; ++i) | 387 | for (size_t i = 0; i < psyms->len; i++) | |
388 | debug_printf(" %d %s", | 388 | debug_printf(" %d %s", | |
389 | psyms->ind_level[i], psym_name[psyms->sym[i]]); | 389 | psyms->ind_level[i], psym_name[psyms->sym[i]]); | |
390 | debug_println(""); | 390 | debug_println(""); | |
391 | } | 391 | } | |
392 | #endif | 392 | #endif |
--- src/usr.bin/indent/indent.c 2023/06/16 23:51:32 1.379
+++ src/usr.bin/indent/indent.c 2023/06/17 22:28:49 1.380
@@ -1,1137 +1,1137 @@ | @@ -1,1137 +1,1137 @@ | |||
1 | /* $NetBSD: indent.c,v 1.379 2023/06/16 23:51:32 rillig Exp $ */ | 1 | /* $NetBSD: indent.c,v 1.380 2023/06/17 22:28:49 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.379 2023/06/16 23:51:32 rillig Exp $"); | 41 | __RCSID("$NetBSD: indent.c,v 1.380 2023/06/17 22:28:49 rillig Exp $"); | |
42 | 42 | |||
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <err.h> | 44 | #include <err.h> | |
45 | #include <stdarg.h> | 45 | #include <stdarg.h> | |
46 | #include <stdio.h> | 46 | #include <stdio.h> | |
47 | #include <stdlib.h> | 47 | #include <stdlib.h> | |
48 | #include <string.h> | 48 | #include <string.h> | |
49 | 49 | |||
50 | #include "indent.h" | 50 | #include "indent.h" | |
51 | 51 | |||
52 | struct options opt = { | 52 | struct options opt = { | |
53 | .brace_same_line = true, | 53 | .brace_same_line = true, | |
54 | .comment_delimiter_on_blank_line = true, | 54 | .comment_delimiter_on_blank_line = true, | |
55 | .cuddle_else = true, | 55 | .cuddle_else = true, | |
56 | .comment_column = 33, | 56 | .comment_column = 33, | |
57 | .decl_indent = 16, | 57 | .decl_indent = 16, | |
58 | .else_if_in_same_line = true, | 58 | .else_if_in_same_line = true, | |
59 | .function_brace_split = true, | 59 | .function_brace_split = true, | |
60 | .format_col1_comments = true, | 60 | .format_col1_comments = true, | |
61 | .format_block_comments = true, | 61 | .format_block_comments = true, | |
62 | .indent_parameters = true, | 62 | .indent_parameters = true, | |
63 | .indent_size = 8, | 63 | .indent_size = 8, | |
64 | .local_decl_indent = -1, | 64 | .local_decl_indent = -1, | |
65 | .lineup_to_parens = true, | 65 | .lineup_to_parens = true, | |
66 | .procnames_start_line = true, | 66 | .procnames_start_line = true, | |
67 | .star_comment_cont = true, | 67 | .star_comment_cont = true, | |
68 | .tabsize = 8, | 68 | .tabsize = 8, | |
69 | .max_line_length = 78, | 69 | .max_line_length = 78, | |
70 | .use_tabs = true, | 70 | .use_tabs = true, | |
71 | }; | 71 | }; | |
72 | 72 | |||
73 | struct parser_state ps; | 73 | struct parser_state ps; | |
74 | 74 | |||
75 | struct buffer token; | 75 | struct buffer token; | |
76 | 76 | |||
77 | struct buffer lab; | 77 | struct buffer lab; | |
78 | struct buffer code; | 78 | struct buffer code; | |
79 | struct buffer com; | 79 | struct buffer com; | |
80 | 80 | |||
81 | bool found_err; | 81 | bool found_err; | |
82 | bool had_eof; | 82 | bool had_eof; | |
83 | int line_no = 1; | 83 | int line_no = 1; | |
84 | 84 | |||
85 | static struct { | 85 | static struct { | |
86 | struct parser_state *item; | 86 | struct parser_state *item; | |
87 | size_t len; | 87 | size_t len; | |
88 | size_t cap; | 88 | size_t cap; | |
89 | } ifdef; | 89 | } ifdef; | |
90 | 90 | |||
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 char backup_name[PATH_MAX]; | 95 | static char backup_name[PATH_MAX]; | |
96 | static const char *backup_suffix = ".BAK"; | 96 | static const char *backup_suffix = ".BAK"; | |
97 | 97 | |||
98 | 98 | |||
99 | void * | 99 | void * | |
100 | nonnull(void *p) | 100 | nonnull(void *p) | |
101 | { | 101 | { | |
102 | if (p == NULL) | 102 | if (p == NULL) | |
103 | err(EXIT_FAILURE, NULL); | 103 | err(EXIT_FAILURE, NULL); | |
104 | return p; | 104 | return p; | |
105 | } | 105 | } | |
106 | 106 | |||
107 | static void | 107 | static void | |
108 | buf_expand(struct buffer *buf, size_t add_size) | 108 | buf_expand(struct buffer *buf, size_t add_size) | |
109 | { | 109 | { | |
110 | buf->cap = buf->cap + add_size + 400; | 110 | buf->cap = buf->cap + add_size + 400; | |
111 | buf->s = nonnull(realloc(buf->s, buf->cap)); | 111 | buf->s = nonnull(realloc(buf->s, buf->cap)); | |
112 | } | 112 | } | |
113 | 113 | |||
114 | #ifdef debug | 114 | #ifdef debug | |
115 | void | 115 | void | |
116 | buf_terminate(struct buffer *buf) | 116 | buf_terminate(struct buffer *buf) | |
117 | { | 117 | { | |
118 | if (buf->len == buf->cap) | 118 | if (buf->len == buf->cap) | |
119 | buf_expand(buf, 1); | 119 | buf_expand(buf, 1); | |
120 | buf->s[buf->len] = '\0'; | 120 | buf->s[buf->len] = '\0'; | |
121 | } | 121 | } | |
122 | #endif | 122 | #endif | |
123 | 123 | |||
124 | void | 124 | void | |
125 | buf_add_char(struct buffer *buf, char ch) | 125 | buf_add_char(struct buffer *buf, char ch) | |
126 | { | 126 | { | |
127 | if (buf->len == buf->cap) | 127 | if (buf->len == buf->cap) | |
128 | buf_expand(buf, 1); | 128 | buf_expand(buf, 1); | |
129 | buf->s[buf->len++] = ch; | 129 | buf->s[buf->len++] = ch; | |
130 | buf_terminate(buf); | 130 | buf_terminate(buf); | |
131 | } | 131 | } | |
132 | 132 | |||
133 | void | 133 | void | |
134 | buf_add_chars(struct buffer *buf, const char *s, size_t len) | 134 | buf_add_chars(struct buffer *buf, const char *s, size_t len) | |
135 | { | 135 | { | |
136 | if (len == 0) | 136 | if (len == 0) | |
137 | return; | 137 | return; | |
138 | if (len > buf->cap - buf->len) | 138 | if (len > buf->cap - buf->len) | |
139 | buf_expand(buf, len); | 139 | buf_expand(buf, len); | |
140 | memcpy(buf->s + buf->len, s, len); | 140 | memcpy(buf->s + buf->len, s, len); | |
141 | buf->len += len; | 141 | buf->len += len; | |
142 | buf_terminate(buf); | 142 | buf_terminate(buf); | |
143 | } | 143 | } | |
144 | 144 | |||
145 | static void | 145 | static void | |
146 | buf_add_buf(struct buffer *buf, const struct buffer *add) | 146 | buf_add_buf(struct buffer *buf, const struct buffer *add) | |
147 | { | 147 | { | |
148 | buf_add_chars(buf, add->s, add->len); | 148 | buf_add_chars(buf, add->s, add->len); | |
149 | } | 149 | } | |
150 | 150 | |||
151 | void | 151 | void | |
152 | diag(int level, const char *msg, ...) | 152 | diag(int level, const char *msg, ...) | |
153 | { | 153 | { | |
154 | va_list ap; | 154 | va_list ap; | |
155 | 155 | |||
156 | if (level != 0) | 156 | if (level != 0) | |
157 | found_err = true; | 157 | found_err = true; | |
158 | 158 | |||
159 | va_start(ap, msg); | 159 | va_start(ap, msg); | |
160 | fprintf(stderr, "%s: %s:%d: ", | 160 | fprintf(stderr, "%s: %s:%d: ", | |
161 | level == 0 ? "warning" : "error", in_name, line_no); | 161 | level == 0 ? "warning" : "error", in_name, line_no); | |
162 | vfprintf(stderr, msg, ap); | 162 | vfprintf(stderr, msg, ap); | |
163 | fprintf(stderr, "\n"); | 163 | fprintf(stderr, "\n"); | |
164 | va_end(ap); | 164 | va_end(ap); | |
165 | } | 165 | } | |
166 | 166 | |||
167 | /* | 167 | /* | |
168 | * Compute the indentation from starting at 'ind' and adding the text starting | 168 | * Compute the indentation from starting at 'ind' and adding the text starting | |
169 | * at 's'. | 169 | * at 's'. | |
170 | */ | 170 | */ | |
171 | int | 171 | int | |
172 | ind_add(int ind, const char *s, size_t len) | 172 | ind_add(int ind, const char *s, size_t len) | |
173 | { | 173 | { | |
174 | for (const char *p = s; len > 0; p++, len--) { | 174 | for (const char *p = s; len > 0; p++, len--) { | |
175 | if (*p == '\n') | 175 | if (*p == '\n') | |
176 | ind = 0; | 176 | ind = 0; | |
177 | else if (*p == '\t') | 177 | else if (*p == '\t') | |
178 | ind = next_tab(ind); | 178 | ind = next_tab(ind); | |
179 | else if (*p == '\b') | 179 | else if (*p == '\b') | |
180 | --ind; | 180 | ind--; | |
181 | else | 181 | else | |
182 | ++ind; | 182 | ind++; | |
183 | } | 183 | } | |
184 | return ind; | 184 | return ind; | |
185 | } | 185 | } | |
186 | 186 | |||
187 | static void | 187 | static void | |
188 | init_globals(void) | 188 | init_globals(void) | |
189 | { | 189 | { | |
190 | ps_push(psym_stmt, false); /* as a stop symbol */ | 190 | ps_push(psym_stmt, false); /* as a stop symbol */ | |
191 | ps.prev_lsym = lsym_semicolon; | 191 | ps.prev_lsym = lsym_semicolon; | |
192 | ps.lbrace_kind = psym_lbrace_block; | 192 | ps.lbrace_kind = psym_lbrace_block; | |
193 | 193 | |||
194 | const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX"); | 194 | const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX"); | |
195 | if (suffix != NULL) | 195 | if (suffix != NULL) | |
196 | backup_suffix = suffix; | 196 | backup_suffix = suffix; | |
197 | } | 197 | } | |
198 | 198 | |||
199 | static void | 199 | static void | |
200 | load_profiles(int argc, char **argv) | 200 | load_profiles(int argc, char **argv) | |
201 | { | 201 | { | |
202 | const char *profile_name = NULL; | 202 | const char *profile_name = NULL; | |
203 | 203 | |||
204 | for (int i = 1; i < argc; ++i) { | 204 | for (int i = 1; i < argc; i++) { | |
205 | const char *arg = argv[i]; | 205 | const char *arg = argv[i]; | |
206 | 206 | |||
207 | if (strcmp(arg, "-npro") == 0) | 207 | if (strcmp(arg, "-npro") == 0) | |
208 | return; | 208 | return; | |
209 | if (arg[0] == '-' && arg[1] == 'P' && arg[2] != '\0') | 209 | if (arg[0] == '-' && arg[1] == 'P' && arg[2] != '\0') | |
210 | profile_name = arg + 2; | 210 | profile_name = arg + 2; | |
211 | } | 211 | } | |
212 | 212 | |||
213 | load_profile_files(profile_name); | 213 | load_profile_files(profile_name); | |
214 | } | 214 | } | |
215 | 215 | |||
216 | /* | 216 | /* | |
217 | * Copy the input file to the backup file, then make the backup file the input | 217 | * Copy the input file to the backup file, then make the backup file the input | |
218 | * and the original input file the output. | 218 | * and the original input file the output. | |
219 | */ | 219 | */ | |
220 | static void | 220 | static void | |
221 | copy_to_bak_file(void) | 221 | copy_to_bak_file(void) | |
222 | { | 222 | { | |
223 | size_t n; | 223 | size_t n; | |
224 | char buff[BUFSIZ]; | 224 | char buff[BUFSIZ]; | |
225 | 225 | |||
226 | const char *last_slash = strrchr(in_name, '/'); | 226 | const char *last_slash = strrchr(in_name, '/'); | |
227 | const char *base = last_slash != NULL ? last_slash + 1 : in_name; | 227 | const char *base = last_slash != NULL ? last_slash + 1 : in_name; | |
228 | snprintf(backup_name, sizeof(backup_name), "%s%s", base, backup_suffix); | 228 | snprintf(backup_name, sizeof(backup_name), "%s%s", base, backup_suffix); | |
229 | 229 | |||
230 | /* copy the input file to the backup file */ | 230 | /* copy the input file to the backup file */ | |
231 | FILE *bak = fopen(backup_name, "w"); | 231 | FILE *bak = fopen(backup_name, "w"); | |
232 | if (bak == NULL) | 232 | if (bak == NULL) | |
233 | err(1, "%s", backup_name); | 233 | err(1, "%s", backup_name); | |
234 | 234 | |||
235 | while ((n = fread(buff, 1, sizeof(buff), input)) > 0) | 235 | while ((n = fread(buff, 1, sizeof(buff), input)) > 0) | |
236 | if (fwrite(buff, 1, n, bak) != n) | 236 | if (fwrite(buff, 1, n, bak) != n) | |
237 | err(1, "%s", backup_name); | 237 | err(1, "%s", backup_name); | |
238 | if (fclose(input) != 0) | 238 | if (fclose(input) != 0) | |
239 | err(1, "%s", in_name); | 239 | err(1, "%s", in_name); | |
240 | if (fclose(bak) != 0) | 240 | if (fclose(bak) != 0) | |
241 | err(1, "%s", backup_name); | 241 | err(1, "%s", backup_name); | |
242 | 242 | |||
243 | /* re-open the backup file as the input file */ | 243 | /* re-open the backup file as the input file */ | |
244 | input = fopen(backup_name, "r"); | 244 | input = fopen(backup_name, "r"); | |
245 | if (input == NULL) | 245 | if (input == NULL) | |
246 | err(1, "%s", backup_name); | 246 | err(1, "%s", backup_name); | |
247 | /* now the original input file will be the output */ | 247 | /* now the original input file will be the output */ | |
248 | output = fopen(in_name, "w"); | 248 | output = fopen(in_name, "w"); | |
249 | if (output == NULL) { | 249 | if (output == NULL) { | |
250 | remove(backup_name); | 250 | remove(backup_name); | |
251 | err(1, "%s", in_name); | 251 | err(1, "%s", in_name); | |
252 | } | 252 | } | |
253 | } | 253 | } | |
254 | 254 | |||
255 | static void | 255 | static void | |
256 | parse_command_line(int argc, char **argv) | 256 | parse_command_line(int argc, char **argv) | |
257 | { | 257 | { | |
258 | for (int i = 1; i < argc; ++i) { | 258 | for (int i = 1; i < argc; i++) { | |
259 | const char *arg = argv[i]; | 259 | const char *arg = argv[i]; | |
260 | 260 | |||
261 | if (arg[0] == '-') { | 261 | if (arg[0] == '-') { | |
262 | set_option(arg, "Command line"); | 262 | set_option(arg, "Command line"); | |
263 | 263 | |||
264 | } else if (input == NULL) { | 264 | } else if (input == NULL) { | |
265 | in_name = arg; | 265 | in_name = arg; | |
266 | if ((input = fopen(in_name, "r")) == NULL) | 266 | if ((input = fopen(in_name, "r")) == NULL) | |
267 | err(1, "%s", in_name); | 267 | err(1, "%s", in_name); | |
268 | 268 | |||
269 | } else if (output == NULL) { | 269 | } else if (output == NULL) { | |
270 | if (strcmp(arg, in_name) == 0) | 270 | if (strcmp(arg, in_name) == 0) | |
271 | errx(1, "input and output files " | 271 | errx(1, "input and output files " | |
272 | "must be different"); | 272 | "must be different"); | |
273 | if ((output = fopen(arg, "w")) == NULL) | 273 | if ((output = fopen(arg, "w")) == NULL) | |
274 | err(1, "%s", arg); | 274 | err(1, "%s", arg); | |
275 | 275 | |||
276 | } else | 276 | } else | |
277 | errx(1, "too many arguments: %s", arg); | 277 | errx(1, "too many arguments: %s", arg); | |
278 | } | 278 | } | |
279 | 279 | |||
280 | if (input == NULL) { | 280 | if (input == NULL) { | |
281 | input = stdin; | 281 | input = stdin; | |
282 | output = stdout; | 282 | output = stdout; | |
283 | } else if (output == NULL) | 283 | } else if (output == NULL) | |
284 | copy_to_bak_file(); | 284 | copy_to_bak_file(); | |
285 | 285 | |||
286 | if (opt.comment_column <= 1) | 286 | if (opt.comment_column <= 1) | |
287 | opt.comment_column = 2; /* don't put normal comments in column | 287 | opt.comment_column = 2; /* don't put normal comments in column | |
288 | * 1, see opt.format_col1_comments */ | 288 | * 1, see opt.format_col1_comments */ | |
289 | if (opt.block_comment_max_line_length <= 0) | 289 | if (opt.block_comment_max_line_length <= 0) | |
290 | opt.block_comment_max_line_length = opt.max_line_length; | 290 | opt.block_comment_max_line_length = opt.max_line_length; | |
291 | if (opt.local_decl_indent < 0) | 291 | if (opt.local_decl_indent < 0) | |
292 | opt.local_decl_indent = opt.decl_indent; | 292 | opt.local_decl_indent = opt.decl_indent; | |
293 | if (opt.decl_comment_column <= 0) | 293 | if (opt.decl_comment_column <= 0) | |
294 | opt.decl_comment_column = opt.left_justify_decl | 294 | opt.decl_comment_column = opt.left_justify_decl | |
295 | ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8) | 295 | ? (opt.comment_column <= 10 ? 2 : opt.comment_column - 8) | |
296 | : opt.comment_column; | 296 | : opt.comment_column; | |
297 | if (opt.continuation_indent == 0) | 297 | if (opt.continuation_indent == 0) | |
298 | opt.continuation_indent = opt.indent_size; | 298 | opt.continuation_indent = opt.indent_size; | |
299 | } | 299 | } | |
300 | 300 | |||
301 | static void | 301 | static void | |
302 | set_initial_indentation(void) | 302 | set_initial_indentation(void) | |
303 | { | 303 | { | |
304 | inp_read_line(); | 304 | inp_read_line(); | |
305 | 305 | |||
306 | int ind = 0; | 306 | int ind = 0; | |
307 | for (const char *p = inp_p;; p++) { | 307 | for (const char *p = inp_p;; p++) { | |
308 | if (*p == ' ') | 308 | if (*p == ' ') | |
309 | ind++; | 309 | ind++; | |
310 | else if (*p == '\t') | 310 | else if (*p == '\t') | |
311 | ind = next_tab(ind); | 311 | ind = next_tab(ind); | |
312 | else | 312 | else | |
313 | break; | 313 | break; | |
314 | } | 314 | } | |
315 | 315 | |||
316 | ps.ind_level = ps.ind_level_follow = ind / opt.indent_size; | 316 | ps.ind_level = ps.ind_level_follow = ind / opt.indent_size; | |
317 | } | 317 | } | |
318 | 318 | |||
319 | static bool | 319 | static bool | |
320 | should_break_line(lexer_symbol lsym) | 320 | should_break_line(lexer_symbol lsym) | |
321 | { | 321 | { | |
322 | if (lsym == lsym_semicolon) | 322 | if (lsym == lsym_semicolon) | |
323 | return false; | 323 | return false; | |
324 | if (ps.prev_lsym == lsym_lbrace || ps.prev_lsym == lsym_semicolon) | 324 | if (ps.prev_lsym == lsym_lbrace || ps.prev_lsym == lsym_semicolon) | |
325 | return true; | 325 | return true; | |
326 | if (lsym == lsym_lbrace && opt.brace_same_line) | 326 | if (lsym == lsym_lbrace && opt.brace_same_line) | |
327 | return false; | 327 | return false; | |
328 | return true; | 328 | return true; | |
329 | } | 329 | } | |
330 | 330 | |||
331 | static void | 331 | static void | |
332 | move_com_to_code(lexer_symbol lsym) | 332 | move_com_to_code(lexer_symbol lsym) | |
333 | { | 333 | { | |
334 | if (ps.want_blank) | 334 | if (ps.want_blank) | |
335 | buf_add_char(&code, ' '); | 335 | buf_add_char(&code, ' '); | |
336 | buf_add_buf(&code, &com); | 336 | buf_add_buf(&code, &com); | |
337 | buf_clear(&com); | 337 | buf_clear(&com); | |
338 | ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket; | 338 | ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket; | |
339 | } | 339 | } | |
340 | 340 | |||
341 | static void | 341 | static void | |
342 | update_ps_lbrace_kind(lexer_symbol lsym) | 342 | update_ps_lbrace_kind(lexer_symbol lsym) | |
343 | { | 343 | { | |
344 | if (lsym == lsym_tag) { | 344 | if (lsym == lsym_tag) { | |
345 | ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct : | 345 | ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct : | |
346 | token.s[0] == 'u' ? psym_lbrace_union : | 346 | token.s[0] == 'u' ? psym_lbrace_union : | |
347 | psym_lbrace_enum; | 347 | psym_lbrace_enum; | |
348 | } else if ((lsym == lsym_type && ps.paren.len == 0) | 348 | } else if ((lsym == lsym_type && ps.paren.len == 0) | |
349 | || lsym == lsym_word | 349 | || lsym == lsym_word | |
350 | || lsym == lsym_lbrace) { | 350 | || lsym == lsym_lbrace) { | |
351 | /* Keep the current '{' kind. */ | 351 | /* Keep the current '{' kind. */ | |
352 | } else | 352 | } else | |
353 | ps.lbrace_kind = psym_lbrace_block; | 353 | ps.lbrace_kind = psym_lbrace_block; | |
354 | } | 354 | } | |
355 | 355 | |||
356 | static void | 356 | static void | |
357 | indent_declarator(int decl_ind, bool tabs_to_var) | 357 | indent_declarator(int decl_ind, bool tabs_to_var) | |
358 | { | 358 | { | |
359 | int base = ps.ind_level * opt.indent_size; | 359 | int base = ps.ind_level * opt.indent_size; | |
360 | int ind = ind_add(base, code.s, code.len); | 360 | int ind = ind_add(base, code.s, code.len); | |
361 | int target = base + decl_ind; | 361 | int target = base + decl_ind; | |
362 | size_t orig_code_len = code.len; | 362 | size_t orig_code_len = code.len; | |
363 | 363 | |||
364 | if (tabs_to_var) | 364 | if (tabs_to_var) | |
365 | for (int next; (next = next_tab(ind)) <= target; ind = next) | 365 | for (int next; (next = next_tab(ind)) <= target; ind = next) | |
366 | buf_add_char(&code, '\t'); | 366 | buf_add_char(&code, '\t'); | |
367 | for (; ind < target; ind++) | 367 | for (; ind < target; ind++) | |
368 | buf_add_char(&code, ' '); | 368 | buf_add_char(&code, ' '); | |
369 | if (code.len == orig_code_len && ps.want_blank) | 369 | if (code.len == orig_code_len && ps.want_blank) | |
370 | buf_add_char(&code, ' '); | 370 | buf_add_char(&code, ' '); | |
371 | 371 | |||
372 | ps.want_blank = false; | 372 | ps.want_blank = false; | |
373 | ps.decl_indent_done = true; | 373 | ps.decl_indent_done = true; | |
374 | } | 374 | } | |
375 | 375 | |||
376 | static bool | 376 | static bool | |
377 | is_function_pointer_declaration(void) | 377 | is_function_pointer_declaration(void) | |
378 | { | 378 | { | |
379 | return ps.in_decl | 379 | return ps.in_decl | |
380 | && !ps.in_typedef_decl | 380 | && !ps.in_typedef_decl | |
381 | && !ps.in_init | 381 | && !ps.in_init | |
382 | && !ps.decl_indent_done | 382 | && !ps.decl_indent_done | |
383 | && !ps.line_has_func_def | 383 | && !ps.line_has_func_def | |
384 | && ps.ind_paren_level == 0; | 384 | && ps.ind_paren_level == 0; | |
385 | } | 385 | } | |
386 | 386 | |||
387 | static int | 387 | static int | |
388 | process_eof(void) | 388 | process_eof(void) | |
389 | { | 389 | { | |
390 | finish_output(); | 390 | finish_output(); | |
391 | 391 | |||
392 | if (ps.psyms.len > 2) /* check for balanced braces */ | 392 | if (ps.psyms.len > 2) /* check for balanced braces */ | |
393 | diag(1, "Stuff missing from end of file"); | 393 | diag(1, "Stuff missing from end of file"); | |
394 | 394 | |||
395 | return found_err ? EXIT_FAILURE : EXIT_SUCCESS; | 395 | return found_err ? EXIT_FAILURE : EXIT_SUCCESS; | |
396 | } | 396 | } | |
397 | 397 | |||
398 | /* move the whole line to the 'label' buffer */ | 398 | /* move the whole line to the 'label' buffer */ | |
399 | static void | 399 | static void | |
400 | read_preprocessing_line(void) | 400 | read_preprocessing_line(void) | |
401 | { | 401 | { | |
402 | enum { | 402 | enum { | |
403 | PLAIN, STR, CHR, COMM | 403 | PLAIN, STR, CHR, COMM | |
404 | } state = PLAIN; | 404 | } state = PLAIN; | |
405 | 405 | |||
406 | buf_add_char(&lab, '#'); | 406 | buf_add_char(&lab, '#'); | |
407 | 407 | |||
408 | while (inp_p[0] != '\n' || (state == COMM && !had_eof)) { | 408 | while (inp_p[0] != '\n' || (state == COMM && !had_eof)) { | |
409 | buf_add_char(&lab, inp_next()); | 409 | buf_add_char(&lab, inp_next()); | |
410 | switch (lab.s[lab.len - 1]) { | 410 | switch (lab.s[lab.len - 1]) { | |
411 | case '\\': | 411 | case '\\': | |
412 | if (state != COMM) | 412 | if (state != COMM) | |
413 | buf_add_char(&lab, inp_next()); | 413 | buf_add_char(&lab, inp_next()); | |
414 | break; | 414 | break; | |
415 | case '/': | 415 | case '/': | |
416 | if (inp_p[0] == '*' && state == PLAIN) { | 416 | if (inp_p[0] == '*' && state == PLAIN) { | |
417 | state = COMM; | 417 | state = COMM; | |
418 | buf_add_char(&lab, *inp_p++); | 418 | buf_add_char(&lab, *inp_p++); | |
419 | } | 419 | } | |
420 | break; | 420 | break; | |
421 | case '"': | 421 | case '"': | |
422 | if (state == STR) | 422 | if (state == STR) | |
423 | state = PLAIN; | 423 | state = PLAIN; | |
424 | else if (state == PLAIN) | 424 | else if (state == PLAIN) | |
425 | state = STR; | 425 | state = STR; | |
426 | break; | 426 | break; | |
427 | case '\'': | 427 | case '\'': | |
428 | if (state == CHR) | 428 | if (state == CHR) | |
429 | state = PLAIN; | 429 | state = PLAIN; | |
430 | else if (state == PLAIN) | 430 | else if (state == PLAIN) | |
431 | state = CHR; | 431 | state = CHR; | |
432 | break; | 432 | break; | |
433 | case '*': | 433 | case '*': | |
434 | if (inp_p[0] == '/' && state == COMM) { | 434 | if (inp_p[0] == '/' && state == COMM) { | |
435 | state = PLAIN; | 435 | state = PLAIN; | |
436 | buf_add_char(&lab, *inp_p++); | 436 | buf_add_char(&lab, *inp_p++); | |
437 | } | 437 | } | |
438 | break; | 438 | break; | |
439 | } | 439 | } | |
440 | } | 440 | } | |
441 | 441 | |||
442 | while (lab.len > 0 && ch_isblank(lab.s[lab.len - 1])) | 442 | while (lab.len > 0 && ch_isblank(lab.s[lab.len - 1])) | |
443 | lab.len--; | 443 | lab.len--; | |
444 | buf_terminate(&lab); | 444 | buf_terminate(&lab); | |
445 | } | 445 | } | |
446 | 446 | |||
447 | static void | 447 | static void | |
448 | paren_stack_push(struct paren_stack *s, int indent, enum paren_level_cast cast) | 448 | paren_stack_push(struct paren_stack *s, int indent, enum paren_level_cast cast) | |
449 | { | 449 | { | |
450 | if (s->len == s->cap) { | 450 | if (s->len == s->cap) { | |
451 | s->cap = 10 + s->cap; | 451 | s->cap = 10 + s->cap; | |
452 | s->item = nonnull(realloc(s->item, | 452 | s->item = nonnull(realloc(s->item, | |
453 | sizeof(s->item[0]) * s->cap)); | 453 | sizeof(s->item[0]) * s->cap)); | |
454 | } | 454 | } | |
455 | s->item[s->len++] = (struct paren_level){indent, cast}; | 455 | s->item[s->len++] = (struct paren_level){indent, cast}; | |
456 | } | 456 | } | |
457 | 457 | |||
458 | static void * | 458 | static void * | |
459 | dup_mem(const void *src, size_t size) | 459 | dup_mem(const void *src, size_t size) | |
460 | { | 460 | { | |
461 | return memcpy(nonnull(malloc(size)), src, size); | 461 | return memcpy(nonnull(malloc(size)), src, size); | |
462 | } | 462 | } | |
463 | 463 | |||
464 | #define dup_array(src, len) \ | 464 | #define dup_array(src, len) \ | |
465 | dup_mem((src), sizeof((src)[0]) * (len)) | 465 | dup_mem((src), sizeof((src)[0]) * (len)) | |
466 | #define copy_array(dst, src, len) \ | 466 | #define copy_array(dst, src, len) \ | |
467 | memcpy((dst), (src), sizeof((dst)[0]) * (len)) | 467 | memcpy((dst), (src), sizeof((dst)[0]) * (len)) | |
468 | 468 | |||
469 | static void | 469 | static void | |
470 | parser_state_back_up(struct parser_state *dst) | 470 | parser_state_back_up(struct parser_state *dst) | |
471 | { | 471 | { | |
472 | *dst = ps; | 472 | *dst = ps; | |
473 | 473 | |||
474 | dst->paren.item = dup_array(ps.paren.item, ps.paren.len); | 474 | dst->paren.item = dup_array(ps.paren.item, ps.paren.len); | |
475 | dst->psyms.sym = dup_array(ps.psyms.sym, ps.psyms.len); | 475 | dst->psyms.sym = dup_array(ps.psyms.sym, ps.psyms.len); | |
476 | dst->psyms.ind_level = dup_array(ps.psyms.ind_level, ps.psyms.len); | 476 | dst->psyms.ind_level = dup_array(ps.psyms.ind_level, ps.psyms.len); | |
477 | } | 477 | } | |
478 | 478 | |||
479 | static void | 479 | static void | |
480 | parser_state_restore(const struct parser_state *src) | 480 | parser_state_restore(const struct parser_state *src) | |
481 | { | 481 | { | |
482 | struct paren_level *ps_paren_item = ps.paren.item; | 482 | struct paren_level *ps_paren_item = ps.paren.item; | |
483 | size_t ps_paren_cap = ps.paren.cap; | 483 | size_t ps_paren_cap = ps.paren.cap; | |
484 | enum parser_symbol *ps_psyms_sym = ps.psyms.sym; | 484 | enum parser_symbol *ps_psyms_sym = ps.psyms.sym; | |
485 | int *ps_psyms_ind_level = ps.psyms.ind_level; | 485 | int *ps_psyms_ind_level = ps.psyms.ind_level; | |
486 | size_t ps_psyms_cap = ps.psyms.cap; | 486 | size_t ps_psyms_cap = ps.psyms.cap; | |
487 | 487 | |||
488 | ps = *src; | 488 | ps = *src; | |
489 | 489 | |||
490 | ps.paren.item = ps_paren_item; | 490 | ps.paren.item = ps_paren_item; | |
491 | ps.paren.cap = ps_paren_cap; | 491 | ps.paren.cap = ps_paren_cap; | |
492 | ps.psyms.sym = ps_psyms_sym; | 492 | ps.psyms.sym = ps_psyms_sym; | |
493 | ps.psyms.ind_level = ps_psyms_ind_level; | 493 | ps.psyms.ind_level = ps_psyms_ind_level; | |
494 | ps.psyms.cap = ps_psyms_cap; | 494 | ps.psyms.cap = ps_psyms_cap; | |
495 | 495 | |||
496 | copy_array(ps.paren.item, src->paren.item, src->paren.len); | 496 | copy_array(ps.paren.item, src->paren.item, src->paren.len); | |
497 | copy_array(ps.psyms.sym, src->psyms.sym, src->psyms.len); | 497 | copy_array(ps.psyms.sym, src->psyms.sym, src->psyms.len); | |
498 | copy_array(ps.psyms.ind_level, src->psyms.ind_level, src->psyms.len); | 498 | copy_array(ps.psyms.ind_level, src->psyms.ind_level, src->psyms.len); | |
499 | } | 499 | } | |
500 | 500 | |||
501 | static void | 501 | static void | |
502 | parser_state_free(struct parser_state *pst) | 502 | parser_state_free(struct parser_state *pst) | |
503 | { | 503 | { | |
504 | free(pst->paren.item); | 504 | free(pst->paren.item); | |
505 | free(pst->psyms.sym); | 505 | free(pst->psyms.sym); | |
506 | free(pst->psyms.ind_level); | 506 | free(pst->psyms.ind_level); | |
507 | } | 507 | } | |
508 | 508 | |||
509 | static void | 509 | static void | |
510 | process_preprocessing(void) | 510 | process_preprocessing(void) | |
511 | { | 511 | { | |
512 | if (lab.len > 0 || code.len > 0 || com.len > 0) | 512 | if (lab.len > 0 || code.len > 0 || com.len > 0) | |
513 | output_line(); | 513 | output_line(); | |
514 | 514 | |||
515 | read_preprocessing_line(); | 515 | read_preprocessing_line(); | |
516 | 516 | |||
517 | const char *dir = lab.s + 1, *line_end = lab.s + lab.len; | 517 | const char *dir = lab.s + 1, *line_end = lab.s + lab.len; | |
518 | while (dir < line_end && ch_isblank(*dir)) | 518 | while (dir < line_end && ch_isblank(*dir)) | |
519 | dir++; | 519 | dir++; | |
520 | size_t dir_len = 0; | 520 | size_t dir_len = 0; | |
521 | while (dir + dir_len < line_end && ch_isalpha(dir[dir_len])) | 521 | while (dir + dir_len < line_end && ch_isalpha(dir[dir_len])) | |
522 | dir_len++; | 522 | dir_len++; | |
523 | 523 | |||
524 | if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) { | 524 | if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) { | |
525 | if (ifdef.len >= ifdef.cap) { | 525 | if (ifdef.len >= ifdef.cap) { | |
526 | ifdef.cap += 5; | 526 | ifdef.cap += 5; | |
527 | ifdef.item = nonnull(realloc(ifdef.item, | 527 | ifdef.item = nonnull(realloc(ifdef.item, | |
528 | sizeof(ifdef.item[0]) * ifdef.cap)); | 528 | sizeof(ifdef.item[0]) * ifdef.cap)); | |
529 | } | 529 | } | |
530 | parser_state_back_up(ifdef.item + ifdef.len++); | 530 | parser_state_back_up(ifdef.item + ifdef.len++); | |
531 | out.line_kind = lk_pre_if; | 531 | out.line_kind = lk_pre_if; | |
532 | 532 | |||
533 | } else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) { | 533 | } else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) { | |
534 | if (ifdef.len == 0) | 534 | if (ifdef.len == 0) | |
535 | diag(1, "Unmatched #%.*s", (int)dir_len, dir); | 535 | diag(1, "Unmatched #%.*s", (int)dir_len, dir); | |
536 | else | 536 | else | |
537 | parser_state_restore(ifdef.item + ifdef.len - 1); | 537 | parser_state_restore(ifdef.item + ifdef.len - 1); | |
538 | out.line_kind = lk_pre_other; | 538 | out.line_kind = lk_pre_other; | |
539 | 539 | |||
540 | } else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) { | 540 | } else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) { | |
541 | if (ifdef.len == 0) | 541 | if (ifdef.len == 0) | |
542 | diag(1, "Unmatched #endif"); | 542 | diag(1, "Unmatched #endif"); | |
543 | else | 543 | else | |
544 | parser_state_free(ifdef.item + --ifdef.len); | 544 | parser_state_free(ifdef.item + --ifdef.len); | |
545 | out.line_kind = lk_pre_endif; | 545 | out.line_kind = lk_pre_endif; | |
546 | } else | 546 | } else | |
547 | out.line_kind = lk_pre_other; | 547 | out.line_kind = lk_pre_other; | |
548 | } | 548 | } | |
549 | 549 | |||
550 | static void | 550 | static void | |
551 | process_newline(void) | 551 | process_newline(void) | |
552 | { | 552 | { | |
553 | if (ps.prev_lsym == lsym_comma | 553 | if (ps.prev_lsym == lsym_comma | |
554 | && ps.paren.len == 0 && !ps.in_init | 554 | && ps.paren.len == 0 && !ps.in_init | |
555 | && !opt.break_after_comma && ps.break_after_comma | 555 | && !opt.break_after_comma && ps.break_after_comma | |
556 | && lab.len == 0 /* for preprocessing lines */ | 556 | && lab.len == 0 /* for preprocessing lines */ | |
557 | && com.len == 0) | 557 | && com.len == 0) | |
558 | goto stay_in_line; | 558 | goto stay_in_line; | |
559 | if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr | 559 | if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr | |
560 | && opt.brace_same_line | 560 | && opt.brace_same_line | |
561 | && com.len == 0) { | 561 | && com.len == 0) { | |
562 | ps.want_newline = true; | 562 | ps.want_newline = true; | |
563 | goto stay_in_line; | 563 | goto stay_in_line; | |
564 | } | 564 | } | |
565 | 565 | |||
566 | output_line(); | 566 | output_line(); | |
567 | 567 | |||
568 | stay_in_line: | 568 | stay_in_line: | |
569 | ++line_no; | 569 | line_no++; | |
570 | } | 570 | } | |
571 | 571 | |||
572 | static bool | 572 | static bool | |
573 | want_blank_before_lparen(void) | 573 | want_blank_before_lparen(void) | |
574 | { | 574 | { | |
575 | if (opt.proc_calls_space) | 575 | if (opt.proc_calls_space) | |
576 | return true; | 576 | return true; | |
577 | if (ps.prev_lsym == lsym_sizeof) | 577 | if (ps.prev_lsym == lsym_sizeof) | |
578 | return opt.blank_after_sizeof; | 578 | return opt.blank_after_sizeof; | |
579 | if (ps.prev_lsym == lsym_rparen | 579 | if (ps.prev_lsym == lsym_rparen | |
580 | || ps.prev_lsym == lsym_rbracket | 580 | || ps.prev_lsym == lsym_rbracket | |
581 | || ps.prev_lsym == lsym_postfix_op | 581 | || ps.prev_lsym == lsym_postfix_op | |
582 | || ps.prev_lsym == lsym_offsetof | 582 | || ps.prev_lsym == lsym_offsetof | |
583 | || ps.prev_lsym == lsym_word | 583 | || ps.prev_lsym == lsym_word | |
584 | || ps.prev_lsym == lsym_funcname) | 584 | || ps.prev_lsym == lsym_funcname) | |
585 | return false; | 585 | return false; | |
586 | return true; | 586 | return true; | |
587 | } | 587 | } | |
588 | 588 | |||
589 | static void | 589 | static void | |
590 | process_lparen(void) | 590 | process_lparen(void) | |
591 | { | 591 | { | |
592 | 592 | |||
593 | if (is_function_pointer_declaration()) | 593 | if (is_function_pointer_declaration()) | |
594 | indent_declarator(ps.decl_ind, ps.tabs_to_var); | 594 | indent_declarator(ps.decl_ind, ps.tabs_to_var); | |
595 | else if (ps.want_blank && want_blank_before_lparen()) | 595 | else if (ps.want_blank && want_blank_before_lparen()) | |
596 | buf_add_char(&code, ' '); | 596 | buf_add_char(&code, ' '); | |
597 | ps.want_blank = false; | 597 | ps.want_blank = false; | |
598 | buf_add_buf(&code, &token); | 598 | buf_add_buf(&code, &token); | |
599 | 599 | |||
600 | if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0) | 600 | if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0) | |
601 | ps.extra_expr_indent = eei_maybe; | 601 | ps.extra_expr_indent = eei_maybe; | |
602 | 602 | |||
603 | if (ps.in_var_decl && ps.psyms.len <= 3 && !ps.in_init) { | 603 | if (ps.in_var_decl && ps.psyms.len <= 3 && !ps.in_init) { | |
604 | parse(psym_stmt); /* prepare for function definition */ | 604 | parse(psym_stmt); /* prepare for function definition */ | |
605 | ps.in_var_decl = false; | 605 | ps.in_var_decl = false; | |
606 | } | 606 | } | |
607 | 607 | |||
608 | enum paren_level_cast cast = cast_unknown; | 608 | enum paren_level_cast cast = cast_unknown; | |
609 | if (ps.prev_lsym == lsym_offsetof | 609 | if (ps.prev_lsym == lsym_offsetof | |
610 | || ps.prev_lsym == lsym_sizeof | 610 | || ps.prev_lsym == lsym_sizeof | |
611 | || ps.prev_lsym == lsym_for | 611 | || ps.prev_lsym == lsym_for | |
612 | || ps.prev_lsym == lsym_if | 612 | || ps.prev_lsym == lsym_if | |
613 | || ps.prev_lsym == lsym_switch | 613 | || ps.prev_lsym == lsym_switch | |
614 | || ps.prev_lsym == lsym_while | 614 | || ps.prev_lsym == lsym_while | |
615 | || ps.line_has_func_def) | 615 | || ps.line_has_func_def) | |
616 | cast = cast_no; | 616 | cast = cast_no; | |
617 | 617 | |||
618 | paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast); | 618 | paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast); | |
619 | } | 619 | } | |
620 | 620 | |||
621 | static bool | 621 | static bool | |
622 | rparen_is_cast(bool paren_cast) | 622 | rparen_is_cast(bool paren_cast) | |
623 | { | 623 | { | |
624 | if (ps.in_func_def_params) | 624 | if (ps.in_func_def_params) | |
625 | return false; | 625 | return false; | |
626 | if (ps.line_has_decl && !ps.in_init) | 626 | if (ps.line_has_decl && !ps.in_init) | |
627 | return false; | 627 | return false; | |
628 | if (ps.prev_lsym == lsym_unary_op) | 628 | if (ps.prev_lsym == lsym_unary_op) | |
629 | return true; | 629 | return true; | |
630 | if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) | 630 | if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) | |
631 | return false; | 631 | return false; | |
632 | return paren_cast || ch_isalpha(inp_p[0]) || inp_p[0] == '{'; | 632 | return paren_cast || ch_isalpha(inp_p[0]) || inp_p[0] == '{'; | |
633 | } | 633 | } | |
634 | 634 | |||
635 | static void | 635 | static void | |
636 | process_rparen(void) | 636 | process_rparen(void) | |
637 | { | 637 | { | |
638 | if (ps.paren.len == 0) | 638 | if (ps.paren.len == 0) | |
639 | diag(0, "Extra '%c'", *token.s); | 639 | diag(0, "Extra '%c'", *token.s); | |
640 | 640 | |||
641 | bool paren_cast = ps.paren.len > 0 | 641 | bool paren_cast = ps.paren.len > 0 | |
642 | && ps.paren.item[--ps.paren.len].cast == cast_maybe; | 642 | && ps.paren.item[--ps.paren.len].cast == cast_maybe; | |
643 | ps.prev_paren_was_cast = rparen_is_cast(paren_cast); | 643 | ps.prev_paren_was_cast = rparen_is_cast(paren_cast); | |
644 | if (ps.prev_paren_was_cast) { | 644 | if (ps.prev_paren_was_cast) { | |
645 | ps.next_unary = true; | 645 | ps.next_unary = true; | |
646 | ps.want_blank = opt.space_after_cast; | 646 | ps.want_blank = opt.space_after_cast; | |
647 | } else | 647 | } else | |
648 | ps.want_blank = true; | 648 | ps.want_blank = true; | |
649 | 649 | |||
650 | if (code.len == 0) | 650 | if (code.len == 0) | |
651 | ps.ind_paren_level = (int)ps.paren.len; | 651 | ps.ind_paren_level = (int)ps.paren.len; | |
652 | 652 | |||
653 | buf_add_buf(&code, &token); | 653 | buf_add_buf(&code, &token); | |
654 | 654 | |||
655 | if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { | 655 | if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { | |
656 | parse(ps.spaced_expr_psym); | 656 | parse(ps.spaced_expr_psym); | |
657 | ps.spaced_expr_psym = psym_0; | 657 | ps.spaced_expr_psym = psym_0; | |
658 | 658 | |||
659 | ps.want_newline = true; | 659 | ps.want_newline = true; | |
660 | ps.next_unary = true; | 660 | ps.next_unary = true; | |
661 | ps.in_stmt_or_decl = false; | 661 | ps.in_stmt_or_decl = false; | |
662 | ps.want_blank = true; | 662 | ps.want_blank = true; | |
663 | out.line_kind = lk_stmt_head; | 663 | out.line_kind = lk_stmt_head; | |
664 | if (ps.extra_expr_indent == eei_maybe) | 664 | if (ps.extra_expr_indent == eei_maybe) | |
665 | ps.extra_expr_indent = eei_last; | 665 | ps.extra_expr_indent = eei_last; | |
666 | } | 666 | } | |
667 | } | 667 | } | |
668 | 668 | |||
669 | static void | 669 | static void | |
670 | process_lbracket(void) | 670 | process_lbracket(void) | |
671 | { | 671 | { | |
672 | if (code.len > 0 | 672 | if (code.len > 0 | |
673 | && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op)) | 673 | && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op)) | |
674 | buf_add_char(&code, ' '); | 674 | buf_add_char(&code, ' '); | |
675 | buf_add_buf(&code, &token); | 675 | buf_add_buf(&code, &token); | |
676 | ps.want_blank = false; | 676 | ps.want_blank = false; | |
677 | 677 | |||
678 | paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast_no); | 678 | paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast_no); | |
679 | } | 679 | } | |
680 | 680 | |||
681 | static void | 681 | static void | |
682 | process_rbracket(void) | 682 | process_rbracket(void) | |
683 | { | 683 | { | |
684 | if (ps.paren.len == 0) | 684 | if (ps.paren.len == 0) | |
685 | diag(0, "Extra '%c'", *token.s); | 685 | diag(0, "Extra '%c'", *token.s); | |
686 | if (ps.paren.len > 0) | 686 | if (ps.paren.len > 0) | |
687 | ps.paren.len--; | 687 | ps.paren.len--; | |
688 | 688 | |||
689 | if (code.len == 0) | 689 | if (code.len == 0) | |
690 | ps.ind_paren_level = (int)ps.paren.len; | 690 | ps.ind_paren_level = (int)ps.paren.len; | |
691 | 691 | |||
692 | buf_add_buf(&code, &token); | 692 | buf_add_buf(&code, &token); | |
693 | ps.want_blank = true; | 693 | ps.want_blank = true; | |
694 | } | 694 | } | |
695 | 695 | |||
696 | static void | 696 | static void | |
697 | process_lbrace(void) | 697 | process_lbrace(void) | |
698 | { | 698 | { | |
699 | if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) { | 699 | if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) { | |
700 | ps.in_var_decl = true; // XXX: not really | 700 | ps.in_var_decl = true; // XXX: not really | |
701 | ps.in_init = true; | 701 | ps.in_init = true; | |
702 | } | 702 | } | |
703 | 703 | |||
704 | if (out.line_kind == lk_stmt_head) | 704 | if (out.line_kind == lk_stmt_head) | |
705 | out.line_kind = lk_other; | 705 | out.line_kind = lk_other; | |
706 | 706 | |||
707 | ps.in_stmt_or_decl = false; /* don't indent the {} */ | 707 | ps.in_stmt_or_decl = false; /* don't indent the {} */ | |
708 | 708 | |||
709 | if (ps.in_init) | 709 | if (ps.in_init) | |
710 | ps.init_level++; | 710 | ps.init_level++; | |
711 | else | 711 | else | |
712 | ps.want_newline = true; | 712 | ps.want_newline = true; | |
713 | 713 | |||
714 | if (code.len > 0 && !ps.in_init) { | 714 | if (code.len > 0 && !ps.in_init) { | |
715 | if (!opt.brace_same_line || | 715 | if (!opt.brace_same_line || | |
716 | (code.len > 0 && code.s[code.len - 1] == '}')) | 716 | (code.len > 0 && code.s[code.len - 1] == '}')) | |
717 | output_line(); | 717 | output_line(); | |
718 | else if (ps.in_func_def_params && !ps.in_var_decl) { | 718 | else if (ps.in_func_def_params && !ps.in_var_decl) { | |
719 | ps.ind_level_follow = 0; | 719 | ps.ind_level_follow = 0; | |
720 | if (opt.function_brace_split) | 720 | if (opt.function_brace_split) | |
721 | output_line(); | 721 | output_line(); | |
722 | else | 722 | else | |
723 | ps.want_blank = true; | 723 | ps.want_blank = true; | |
724 | } | 724 | } | |
725 | } | 725 | } | |
726 | 726 | |||
727 | if (ps.paren.len > 0 && ps.init_level == 0) { | 727 | if (ps.paren.len > 0 && ps.init_level == 0) { | |
728 | diag(1, "Unbalanced parentheses"); | 728 | diag(1, "Unbalanced parentheses"); | |
729 | ps.paren.len = 0; | 729 | ps.paren.len = 0; | |
730 | if (ps.spaced_expr_psym != psym_0) { | 730 | if (ps.spaced_expr_psym != psym_0) { | |
731 | parse(ps.spaced_expr_psym); | 731 | parse(ps.spaced_expr_psym); | |
732 | ps.spaced_expr_psym = psym_0; | 732 | ps.spaced_expr_psym = psym_0; | |
733 | ps.ind_level = ps.ind_level_follow; | 733 | ps.ind_level = ps.ind_level_follow; | |
734 | } | 734 | } | |
735 | } | 735 | } | |
736 | 736 | |||
737 | if (code.len == 0) | 737 | if (code.len == 0) | |
738 | ps.line_is_stmt_cont = false; | 738 | ps.line_is_stmt_cont = false; | |
739 | if (ps.in_decl && ps.in_var_decl) { | 739 | if (ps.in_decl && ps.in_var_decl) { | |
740 | ps.di_stack[ps.decl_level] = ps.decl_ind; | 740 | ps.di_stack[ps.decl_level] = ps.decl_ind; | |
741 | if (++ps.decl_level == (int)array_length(ps.di_stack)) { | 741 | if (++ps.decl_level == (int)array_length(ps.di_stack)) { | |
742 | diag(0, "Reached internal limit of %zu struct levels", | 742 | diag(0, "Reached internal limit of %zu struct levels", | |
743 | array_length(ps.di_stack)); | 743 | array_length(ps.di_stack)); | |
744 | ps.decl_level--; | 744 | ps.decl_level--; | |
745 | } | 745 | } | |
746 | } else { | 746 | } else { | |
747 | ps.line_has_decl = false; /* don't do special indentation | 747 | ps.line_has_decl = false; /* don't do special indentation | |
748 | * of comments */ | 748 | * of comments */ | |
749 | ps.in_func_def_params = false; | 749 | ps.in_func_def_params = false; | |
750 | ps.in_decl = false; | 750 | ps.in_decl = false; | |
751 | } | 751 | } | |
752 | 752 | |||
753 | ps.decl_ind = 0; | 753 | ps.decl_ind = 0; | |
754 | parse(ps.lbrace_kind); | 754 | parse(ps.lbrace_kind); | |
755 | if (ps.want_blank) | 755 | if (ps.want_blank) | |
756 | buf_add_char(&code, ' '); | 756 | buf_add_char(&code, ' '); | |
757 | ps.want_blank = false; | 757 | ps.want_blank = false; | |
758 | buf_add_char(&code, '{'); | 758 | buf_add_char(&code, '{'); | |
759 | ps.declaration = decl_no; | 759 | ps.declaration = decl_no; | |
760 | } | 760 | } | |
761 | 761 | |||
762 | static void | 762 | static void | |
763 | process_rbrace(void) | 763 | process_rbrace(void) | |
764 | { | 764 | { | |
765 | if (ps.paren.len > 0 && ps.init_level == 0) { | 765 | if (ps.paren.len > 0 && ps.init_level == 0) { | |
766 | diag(1, "Unbalanced parentheses"); | 766 | diag(1, "Unbalanced parentheses"); | |
767 | ps.paren.len = 0; | 767 | ps.paren.len = 0; | |
768 | ps.spaced_expr_psym = psym_0; | 768 | ps.spaced_expr_psym = psym_0; | |
769 | } | 769 | } | |
770 | 770 | |||
771 | ps.declaration = decl_no; | 771 | ps.declaration = decl_no; | |
772 | if (ps.init_level > 0) | 772 | if (ps.init_level > 0) | |
773 | ps.init_level--; | 773 | ps.init_level--; | |
774 | 774 | |||
775 | if (code.len > 0 && !ps.in_init) | 775 | if (code.len > 0 && !ps.in_init) | |
776 | output_line(); | 776 | output_line(); | |
777 | 777 | |||
778 | buf_add_char(&code, '}'); | 778 | buf_add_char(&code, '}'); | |
779 | ps.want_blank = true; | 779 | ps.want_blank = true; | |
780 | ps.in_stmt_or_decl = false; // XXX: Initializers don't end a stmt | 780 | ps.in_stmt_or_decl = false; // XXX: Initializers don't end a stmt | |
781 | ps.line_is_stmt_cont = false; | 781 | ps.line_is_stmt_cont = false; | |
782 | 782 | |||
783 | if (ps.decl_level > 0) { /* multi-level structure declaration */ | 783 | if (ps.decl_level > 0) { /* multi-level structure declaration */ | |
784 | ps.decl_ind = ps.di_stack[--ps.decl_level]; | 784 | ps.decl_ind = ps.di_stack[--ps.decl_level]; | |
785 | if (ps.decl_level == 0 && !ps.in_func_def_params) { | 785 | if (ps.decl_level == 0 && !ps.in_func_def_params) { | |
786 | ps.declaration = decl_begin; | 786 | ps.declaration = decl_begin; | |
787 | ps.decl_ind = ps.ind_level == 0 | 787 | ps.decl_ind = ps.ind_level == 0 | |
788 | ? opt.decl_indent : opt.local_decl_indent; | 788 | ? opt.decl_indent : opt.local_decl_indent; | |
789 | } | 789 | } | |
790 | ps.in_decl = true; | 790 | ps.in_decl = true; | |
791 | } | 791 | } | |
792 | 792 | |||
793 | if (ps.psyms.len == 3) | 793 | if (ps.psyms.len == 3) | |
794 | out.line_kind = lk_func_end; | 794 | out.line_kind = lk_func_end; | |
795 | 795 | |||
796 | parse(psym_rbrace); | 796 | parse(psym_rbrace); | |
797 | 797 | |||
798 | if (!ps.in_var_decl | 798 | if (!ps.in_var_decl | |
799 | && ps.psyms.sym[ps.psyms.len - 1] != psym_do_stmt | 799 | && ps.psyms.sym[ps.psyms.len - 1] != psym_do_stmt | |
800 | && ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt) | 800 | && ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt) | |
801 | ps.want_newline = true; | 801 | ps.want_newline = true; | |
802 | } | 802 | } | |
803 | 803 | |||
804 | static void | 804 | static void | |
805 | process_period(void) | 805 | process_period(void) | |
806 | { | 806 | { | |
807 | if (code.len > 0 && code.s[code.len - 1] == ',') | 807 | if (code.len > 0 && code.s[code.len - 1] == ',') | |
808 | buf_add_char(&code, ' '); | 808 | buf_add_char(&code, ' '); | |
809 | buf_add_char(&code, '.'); | 809 | buf_add_char(&code, '.'); | |
810 | ps.want_blank = false; | 810 | ps.want_blank = false; | |
811 | } | 811 | } | |
812 | 812 | |||
813 | static void | 813 | static void | |
814 | process_unary_op(void) | 814 | process_unary_op(void) | |
815 | { | 815 | { | |
816 | if (is_function_pointer_declaration()) { | 816 | if (is_function_pointer_declaration()) { | |
817 | int ind = ps.decl_ind - (int)token.len; | 817 | int ind = ps.decl_ind - (int)token.len; | |
818 | indent_declarator(ind, ps.tabs_to_var); | 818 | indent_declarator(ind, ps.tabs_to_var); | |
819 | } else if ((token.s[0] == '+' || token.s[0] == '-') | 819 | } else if ((token.s[0] == '+' || token.s[0] == '-') | |
820 | && code.len > 0 && code.s[code.len - 1] == token.s[0]) | 820 | && code.len > 0 && code.s[code.len - 1] == token.s[0]) | |
821 | ps.want_blank = true; | 821 | ps.want_blank = true; | |
822 | 822 | |||
823 | if (ps.want_blank) | 823 | if (ps.want_blank) | |
824 | buf_add_char(&code, ' '); | 824 | buf_add_char(&code, ' '); | |
825 | buf_add_buf(&code, &token); | 825 | buf_add_buf(&code, &token); | |
826 | ps.want_blank = false; | 826 | ps.want_blank = false; | |
827 | } | 827 | } | |
828 | 828 | |||
829 | static void | 829 | static void | |
830 | process_postfix_op(void) | 830 | process_postfix_op(void) | |
831 | { | 831 | { | |
832 | buf_add_buf(&code, &token); | 832 | buf_add_buf(&code, &token); | |
833 | ps.want_blank = true; | 833 | ps.want_blank = true; | |
834 | } | 834 | } | |
835 | 835 | |||
836 | static void | 836 | static void | |
837 | process_comma(void) | 837 | process_comma(void) | |
838 | { | 838 | { | |
839 | ps.want_blank = code.len > 0; /* only put blank after comma if comma | 839 | ps.want_blank = code.len > 0; /* only put blank after comma if comma | |
840 | * does not start the line */ | 840 | * does not start the line */ | |
841 | 841 | |||
842 | if (ps.in_decl && ps.ind_paren_level == 0 | 842 | if (ps.in_decl && ps.ind_paren_level == 0 | |
843 | && !ps.line_has_func_def && !ps.in_init && !ps.decl_indent_done) { | 843 | && !ps.line_has_func_def && !ps.in_init && !ps.decl_indent_done) { | |
844 | /* indent leading commas and not the actual identifiers */ | 844 | /* indent leading commas and not the actual identifiers */ | |
845 | indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); | 845 | indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); | |
846 | } | 846 | } | |
847 | 847 | |||
848 | buf_add_char(&code, ','); | 848 | buf_add_char(&code, ','); | |
849 | 849 | |||
850 | if (ps.paren.len == 0) { | 850 | if (ps.paren.len == 0) { | |
851 | if (ps.init_level == 0) | 851 | if (ps.init_level == 0) | |
852 | ps.in_init = false; | 852 | ps.in_init = false; | |
853 | int typical_varname_length = 8; | 853 | int typical_varname_length = 8; | |
854 | if (ps.break_after_comma && (opt.break_after_comma || | 854 | if (ps.break_after_comma && (opt.break_after_comma || | |
855 | ind_add(compute_code_indent(), code.s, code.len) | 855 | ind_add(compute_code_indent(), code.s, code.len) | |
856 | >= opt.max_line_length - typical_varname_length)) | 856 | >= opt.max_line_length - typical_varname_length)) | |
857 | ps.want_newline = true; | 857 | ps.want_newline = true; | |
858 | } | 858 | } | |
859 | } | 859 | } | |
860 | 860 | |||
861 | static void | 861 | static void | |
862 | process_label_colon(void) | 862 | process_label_colon(void) | |
863 | { | 863 | { | |
864 | buf_add_buf(&lab, &code); | 864 | buf_add_buf(&lab, &code); | |
865 | buf_add_char(&lab, ':'); | 865 | buf_add_char(&lab, ':'); | |
866 | buf_clear(&code); | 866 | buf_clear(&code); | |
867 | 867 | |||
868 | if (ps.seen_case) | 868 | if (ps.seen_case) | |
869 | out.line_kind = lk_case_or_default; | 869 | out.line_kind = lk_case_or_default; | |
870 | ps.in_stmt_or_decl = false; | 870 | ps.in_stmt_or_decl = false; | |
871 | ps.want_newline = ps.seen_case; | 871 | ps.want_newline = ps.seen_case; | |
872 | ps.seen_case = false; | 872 | ps.seen_case = false; | |
873 | ps.want_blank = false; | 873 | ps.want_blank = false; | |
874 | } | 874 | } | |
875 | 875 | |||
876 | static void | 876 | static void | |
877 | process_other_colon(void) | 877 | process_other_colon(void) | |
878 | { | 878 | { | |
879 | buf_add_char(&code, ':'); | 879 | buf_add_char(&code, ':'); | |
880 | ps.want_blank = ps.decl_level == 0; | 880 | ps.want_blank = ps.decl_level == 0; | |
881 | } | 881 | } | |
882 | 882 | |||
883 | static void | 883 | static void | |
884 | process_semicolon(void) | 884 | process_semicolon(void) | |
885 | { | 885 | { | |
886 | if (out.line_kind == lk_stmt_head) | 886 | if (out.line_kind == lk_stmt_head) | |
887 | out.line_kind = lk_other; | 887 | out.line_kind = lk_other; | |
888 | if (ps.decl_level == 0) { | 888 | if (ps.decl_level == 0) { | |
889 | ps.in_var_decl = false; | 889 | ps.in_var_decl = false; | |
890 | ps.in_typedef_decl = false; | 890 | ps.in_typedef_decl = false; | |
891 | } | 891 | } | |
892 | ps.seen_case = false; /* only needs to be reset on error */ | 892 | ps.seen_case = false; /* only needs to be reset on error */ | |
893 | ps.quest_level = 0; /* only needs to be reset on error */ | 893 | ps.quest_level = 0; /* only needs to be reset on error */ | |
894 | if (ps.prev_lsym == lsym_rparen) | 894 | if (ps.prev_lsym == lsym_rparen) | |
895 | ps.in_func_def_params = false; | 895 | ps.in_func_def_params = false; | |
896 | ps.in_init = false; | 896 | ps.in_init = false; | |
897 | ps.init_level = 0; | 897 | ps.init_level = 0; | |
898 | ps.declaration = ps.declaration == decl_begin ? decl_end : decl_no; | 898 | ps.declaration = ps.declaration == decl_begin ? decl_end : decl_no; | |
899 | 899 | |||
900 | if (ps.in_decl && code.len == 0 && !ps.in_init && | 900 | if (ps.in_decl && code.len == 0 && !ps.in_init && | |
901 | !ps.decl_indent_done && ps.ind_paren_level == 0) { | 901 | !ps.decl_indent_done && ps.ind_paren_level == 0) { | |
902 | /* indent stray semicolons in declarations */ | 902 | /* indent stray semicolons in declarations */ | |
903 | indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); | 903 | indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); | |
904 | } | 904 | } | |
905 | 905 | |||
906 | ps.in_decl = ps.decl_level > 0; /* if we were in a first level | 906 | ps.in_decl = ps.decl_level > 0; /* if we were in a first level | |
907 | * structure declaration before, we | 907 | * structure declaration before, we | |
908 | * aren't anymore */ | 908 | * aren't anymore */ | |
909 | 909 | |||
910 | if (ps.paren.len > 0 && ps.spaced_expr_psym != psym_for_exprs) { | 910 | if (ps.paren.len > 0 && ps.spaced_expr_psym != psym_for_exprs) { | |
911 | diag(1, "Unbalanced parentheses"); | 911 | diag(1, "Unbalanced parentheses"); | |
912 | ps.paren.len = 0; | 912 | ps.paren.len = 0; | |
913 | if (ps.spaced_expr_psym != psym_0) { | 913 | if (ps.spaced_expr_psym != psym_0) { | |
914 | parse(ps.spaced_expr_psym); | 914 | parse(ps.spaced_expr_psym); | |
915 | ps.spaced_expr_psym = psym_0; | 915 | ps.spaced_expr_psym = psym_0; | |
916 | } | 916 | } | |
917 | } | 917 | } | |
918 | buf_add_char(&code, ';'); | 918 | buf_add_char(&code, ';'); | |
919 | ps.want_blank = true; | 919 | ps.want_blank = true; | |
920 | ps.in_stmt_or_decl = ps.paren.len > 0; | 920 | ps.in_stmt_or_decl = ps.paren.len > 0; | |
921 | ps.decl_ind = 0; | 921 | ps.decl_ind = 0; | |
922 | 922 | |||
923 | if (ps.spaced_expr_psym == psym_0) { | 923 | if (ps.spaced_expr_psym == psym_0) { | |
924 | parse(psym_stmt); | 924 | parse(psym_stmt); | |
925 | ps.want_newline = true; | 925 | ps.want_newline = true; | |
926 | } | 926 | } | |
927 | } | 927 | } | |
928 | 928 | |||
929 | static void | 929 | static void | |
930 | process_type_outside_parentheses(void) | 930 | process_type_outside_parentheses(void) | |
931 | { | 931 | { | |
932 | parse(psym_decl); /* let the parser worry about indentation */ | 932 | parse(psym_decl); /* let the parser worry about indentation */ | |
933 | 933 | |||
934 | if (ps.prev_lsym == lsym_rparen && ps.psyms.len <= 2 && code.len > 0) | 934 | if (ps.prev_lsym == lsym_rparen && ps.psyms.len <= 2 && code.len > 0) | |
935 | output_line(); | 935 | output_line(); | |
936 | 936 | |||
937 | if (ps.in_func_def_params && opt.indent_parameters && | 937 | if (ps.in_func_def_params && opt.indent_parameters && | |
938 | ps.decl_level == 0) { | 938 | ps.decl_level == 0) { | |
939 | ps.ind_level = ps.ind_level_follow = 1; | 939 | ps.ind_level = ps.ind_level_follow = 1; | |
940 | ps.line_is_stmt_cont = false; | 940 | ps.line_is_stmt_cont = false; | |
941 | } | 941 | } | |
942 | 942 | |||
943 | ps.in_var_decl = /* maybe */ true; | 943 | ps.in_var_decl = /* maybe */ true; | |
944 | ps.in_decl = true; | 944 | ps.in_decl = true; | |
945 | ps.line_has_decl = ps.in_decl; | 945 | ps.line_has_decl = ps.in_decl; | |
946 | if (ps.decl_level == 0) | 946 | if (ps.decl_level == 0) | |
947 | ps.declaration = decl_begin; | 947 | ps.declaration = decl_begin; | |
948 | 948 | |||
949 | int ind = ps.ind_level > 0 && ps.decl_level == 0 | 949 | int ind = ps.ind_level > 0 && ps.decl_level == 0 | |
950 | ? opt.local_decl_indent /* local variable */ | 950 | ? opt.local_decl_indent /* local variable */ | |
951 | : opt.decl_indent; /* global variable, or member */ | 951 | : opt.decl_indent; /* global variable, or member */ | |
952 | if (ind == 0) { | 952 | if (ind == 0) { | |
953 | int ind0 = code.len > 0 ? ind_add(0, code.s, code.len) + 1 : 0; | 953 | int ind0 = code.len > 0 ? ind_add(0, code.s, code.len) + 1 : 0; | |
954 | ps.decl_ind = ind_add(ind0, token.s, token.len) + 1; | 954 | ps.decl_ind = ind_add(ind0, token.s, token.len) + 1; | |
955 | } else | 955 | } else | |
956 | ps.decl_ind = ind; | 956 | ps.decl_ind = ind; | |
957 | ps.tabs_to_var = opt.use_tabs && ind > 0; | 957 | ps.tabs_to_var = opt.use_tabs && ind > 0; | |
958 | } | 958 | } | |
959 | 959 | |||
960 | static void | 960 | static void | |
961 | process_word(lexer_symbol lsym) | 961 | process_word(lexer_symbol lsym) | |
962 | { | 962 | { | |
963 | if (ps.in_decl) { | 963 | if (ps.in_decl) { | |
964 | if (lsym == lsym_funcname) { | 964 | if (lsym == lsym_funcname) { | |
965 | ps.in_decl = false; | 965 | ps.in_decl = false; | |
966 | if (opt.procnames_start_line && code.len > 0) | 966 | if (opt.procnames_start_line && code.len > 0) | |
967 | output_line(); | 967 | output_line(); | |
968 | else if (ps.want_blank) | 968 | else if (ps.want_blank) | |
969 | buf_add_char(&code, ' '); | 969 | buf_add_char(&code, ' '); | |
970 | ps.want_blank = false; | 970 | ps.want_blank = false; | |
971 | } else if (ps.in_typedef_decl && ps.decl_level == 0) { | 971 | } else if (ps.in_typedef_decl && ps.decl_level == 0) { | |
972 | /* Do not indent typedef declarators. */ | 972 | /* Do not indent typedef declarators. */ | |
973 | } else if (!ps.in_init && !ps.decl_indent_done && | 973 | } else if (!ps.in_init && !ps.decl_indent_done && | |
974 | ps.ind_paren_level == 0) { | 974 | ps.ind_paren_level == 0) { | |
975 | if (opt.decl_indent == 0 | 975 | if (opt.decl_indent == 0 | |
976 | && code.len > 0 && code.s[code.len - 1] == '}') | 976 | && code.len > 0 && code.s[code.len - 1] == '}') | |
977 | ps.decl_ind = ind_add(0, code.s, code.len) + 1; | 977 | ps.decl_ind = ind_add(0, code.s, code.len) + 1; | |
978 | indent_declarator(ps.decl_ind, ps.tabs_to_var); | 978 | indent_declarator(ps.decl_ind, ps.tabs_to_var); | |
979 | } | 979 | } | |
980 | 980 | |||
981 | } else if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { | 981 | } else if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { | |
982 | parse(ps.spaced_expr_psym); | 982 | parse(ps.spaced_expr_psym); | |
983 | ps.spaced_expr_psym = psym_0; | 983 | ps.spaced_expr_psym = psym_0; | |
984 | ps.want_newline = true; | 984 | ps.want_newline = true; | |
985 | ps.in_stmt_or_decl = false; | 985 | ps.in_stmt_or_decl = false; | |
986 | ps.next_unary = true; | 986 | ps.next_unary = true; | |
987 | } | 987 | } | |
988 | } | 988 | } | |
989 | 989 | |||
990 | static void | 990 | static void | |
991 | process_do(void) | 991 | process_do(void) | |
992 | { | 992 | { | |
993 | ps.in_stmt_or_decl = false; | 993 | ps.in_stmt_or_decl = false; | |
994 | ps.in_decl = false; | 994 | ps.in_decl = false; | |
995 | 995 | |||
996 | if (code.len > 0) | 996 | if (code.len > 0) | |
997 | output_line(); | 997 | output_line(); | |
998 | 998 | |||
999 | parse(psym_do); | 999 | parse(psym_do); | |
1000 | ps.want_newline = true; | 1000 | ps.want_newline = true; | |
1001 | } | 1001 | } | |
1002 | 1002 | |||
1003 | static void | 1003 | static void | |
1004 | process_else(void) | 1004 | process_else(void) | |
1005 | { | 1005 | { | |
1006 | ps.in_stmt_or_decl = false; | 1006 | ps.in_stmt_or_decl = false; | |
1007 | ps.in_decl = false; | 1007 | ps.in_decl = false; | |
1008 | 1008 | |||
1009 | if (code.len > 0 | 1009 | if (code.len > 0 | |
1010 | && !(opt.cuddle_else && code.s[code.len - 1] == '}')) | 1010 | && !(opt.cuddle_else && code.s[code.len - 1] == '}')) | |
1011 | output_line(); | 1011 | output_line(); | |
1012 | 1012 | |||
1013 | parse(psym_else); | 1013 | parse(psym_else); | |
1014 | ps.want_newline = true; | 1014 | ps.want_newline = true; | |
1015 | } | 1015 | } | |
1016 | 1016 | |||
1017 | static void | 1017 | static void | |
1018 | process_lsym(lexer_symbol lsym) | 1018 | process_lsym(lexer_symbol lsym) | |
1019 | { | 1019 | { | |
1020 | switch (lsym) { | 1020 | switch (lsym) { | |
1021 | /* INDENT OFF */ | 1021 | /* INDENT OFF */ | |
1022 | case lsym_preprocessing: process_preprocessing(); break; | 1022 | case lsym_preprocessing: process_preprocessing(); break; | |
1023 | case lsym_newline: process_newline(); break; | 1023 | case lsym_newline: process_newline(); break; | |
1024 | case lsym_comment: process_comment(); break; | 1024 | case lsym_comment: process_comment(); break; | |
1025 | case lsym_lparen: process_lparen(); break; | 1025 | case lsym_lparen: process_lparen(); break; | |
1026 | case lsym_lbracket: process_lbracket(); break; | 1026 | case lsym_lbracket: process_lbracket(); break; | |
1027 | case lsym_rparen: process_rparen(); break; | 1027 | case lsym_rparen: process_rparen(); break; | |
1028 | case lsym_rbracket: process_rbracket(); break; | 1028 | case lsym_rbracket: process_rbracket(); break; | |
1029 | case lsym_lbrace: process_lbrace(); break; | 1029 | case lsym_lbrace: process_lbrace(); break; | |
1030 | case lsym_rbrace: process_rbrace(); break; | 1030 | case lsym_rbrace: process_rbrace(); break; | |
1031 | case lsym_period: process_period(); break; | 1031 | case lsym_period: process_period(); break; | |
1032 | case lsym_unary_op: process_unary_op(); break; | 1032 | case lsym_unary_op: process_unary_op(); break; | |
1033 | case lsym_postfix_op: process_postfix_op(); break; | 1033 | case lsym_postfix_op: process_postfix_op(); break; | |
1034 | case lsym_binary_op: goto copy_token; | 1034 | case lsym_binary_op: goto copy_token; | |
1035 | case lsym_question: ps.quest_level++; goto copy_token; | 1035 | case lsym_question: ps.quest_level++; goto copy_token; | |
1036 | case lsym_question_colon: goto copy_token; | 1036 | case lsym_question_colon: goto copy_token; | |
1037 | case lsym_label_colon: process_label_colon(); break; | 1037 | case lsym_label_colon: process_label_colon(); break; | |
1038 | case lsym_other_colon: process_other_colon(); break; | 1038 | case lsym_other_colon: process_other_colon(); break; | |
1039 | case lsym_comma: process_comma(); break; | 1039 | case lsym_comma: process_comma(); break; | |
1040 | case lsym_semicolon: process_semicolon(); break; | 1040 | case lsym_semicolon: process_semicolon(); break; | |
1041 | case lsym_typedef: ps.in_typedef_decl = true; goto copy_token; | 1041 | case lsym_typedef: ps.in_typedef_decl = true; goto copy_token; | |
1042 | case lsym_modifier: goto copy_token; | 1042 | case lsym_modifier: goto copy_token; | |
1043 | case lsym_case: ps.seen_case = true; goto copy_token; | 1043 | case lsym_case: ps.seen_case = true; goto copy_token; | |
1044 | case lsym_default: ps.seen_case = true; goto copy_token; | 1044 | case lsym_default: ps.seen_case = true; goto copy_token; | |
1045 | case lsym_do: process_do(); goto copy_token; | 1045 | case lsym_do: process_do(); goto copy_token; | |
1046 | case lsym_else: process_else(); goto copy_token; | 1046 | case lsym_else: process_else(); goto copy_token; | |
1047 | case lsym_for: ps.spaced_expr_psym = psym_for_exprs; goto copy_token; | 1047 | case lsym_for: ps.spaced_expr_psym = psym_for_exprs; goto copy_token; | |
1048 | case lsym_if: ps.spaced_expr_psym = psym_if_expr; goto copy_token; | 1048 | case lsym_if: ps.spaced_expr_psym = psym_if_expr; goto copy_token; | |
1049 | case lsym_switch: ps.spaced_expr_psym = psym_switch_expr; goto copy_token; | 1049 | case lsym_switch: ps.spaced_expr_psym = psym_switch_expr; goto copy_token; | |
1050 | case lsym_while: ps.spaced_expr_psym = psym_while_expr; goto copy_token; | 1050 | case lsym_while: ps.spaced_expr_psym = psym_while_expr; goto copy_token; | |
1051 | /* INDENT ON */ | 1051 | /* INDENT ON */ | |
1052 | 1052 | |||
1053 | case lsym_tag: | 1053 | case lsym_tag: | |
1054 | if (ps.paren.len > 0) | 1054 | if (ps.paren.len > 0) | |
1055 | goto copy_token; | 1055 | goto copy_token; | |
1056 | /* FALLTHROUGH */ | 1056 | /* FALLTHROUGH */ | |
1057 | case lsym_type: | 1057 | case lsym_type: | |
1058 | if (ps.paren.len == 0) { | 1058 | if (ps.paren.len == 0) { | |
1059 | process_type_outside_parentheses(); | 1059 | process_type_outside_parentheses(); | |
1060 | goto copy_token; | 1060 | goto copy_token; | |
1061 | } | 1061 | } | |
1062 | /* FALLTHROUGH */ | 1062 | /* FALLTHROUGH */ | |
1063 | case lsym_sizeof: | 1063 | case lsym_sizeof: | |
1064 | case lsym_offsetof: | 1064 | case lsym_offsetof: | |
1065 | case lsym_word: | 1065 | case lsym_word: | |
1066 | case lsym_funcname: | 1066 | case lsym_funcname: | |
1067 | case lsym_return: | 1067 | case lsym_return: | |
1068 | process_word(lsym); | 1068 | process_word(lsym); | |
1069 | copy_token: | 1069 | copy_token: | |
1070 | if (ps.want_blank) | 1070 | if (ps.want_blank) | |
1071 | buf_add_char(&code, ' '); | 1071 | buf_add_char(&code, ' '); | |
1072 | buf_add_buf(&code, &token); | 1072 | buf_add_buf(&code, &token); | |
1073 | if (lsym != lsym_funcname) | 1073 | if (lsym != lsym_funcname) | |
1074 | ps.want_blank = true; | 1074 | ps.want_blank = true; | |
1075 | break; | 1075 | break; | |
1076 | 1076 | |||
1077 | default: | 1077 | default: | |
1078 | break; | 1078 | break; | |
1079 | } | 1079 | } | |
1080 | } | 1080 | } | |
1081 | 1081 | |||
1082 | static int | 1082 | static int | |
1083 | indent(void) | 1083 | indent(void) | |
1084 | { | 1084 | { | |
1085 | debug_parser_state(); | 1085 | debug_parser_state(); | |
1086 | 1086 | |||
1087 | for (;;) { /* loop until we reach eof */ | 1087 | for (;;) { /* loop until we reach eof */ | |
1088 | lexer_symbol lsym = lexi(); | 1088 | lexer_symbol lsym = lexi(); | |
1089 | 1089 | |||
1090 | debug_blank_line(); | 1090 | debug_blank_line(); | |
1091 | debug_printf("line %d: %s", line_no, lsym_name[lsym]); | 1091 | debug_printf("line %d: %s", line_no, lsym_name[lsym]); | |
1092 | debug_print_buf("token", &token); | 1092 | debug_print_buf("token", &token); | |
1093 | debug_buffers(); | 1093 | debug_buffers(); | |
1094 | debug_blank_line(); | 1094 | debug_blank_line(); | |
1095 | 1095 | |||
1096 | if (lsym == lsym_eof) | 1096 | if (lsym == lsym_eof) | |
1097 | return process_eof(); | 1097 | return process_eof(); | |
1098 | 1098 | |||
1099 | if (lsym == lsym_preprocessing || lsym == lsym_newline) | 1099 | if (lsym == lsym_preprocessing || lsym == lsym_newline) | |
1100 | ps.want_newline = false; | 1100 | ps.want_newline = false; | |
1101 | else if (lsym == lsym_comment) { | 1101 | else if (lsym == lsym_comment) { | |
1102 | /* no special processing */ | 1102 | /* no special processing */ | |
1103 | } else { | 1103 | } else { | |
1104 | if (lsym == lsym_if && ps.prev_lsym == lsym_else | 1104 | if (lsym == lsym_if && ps.prev_lsym == lsym_else | |
1105 | && opt.else_if_in_same_line) | 1105 | && opt.else_if_in_same_line) | |
1106 | ps.want_newline = false; | 1106 | ps.want_newline = false; | |
1107 | 1107 | |||
1108 | if (ps.want_newline && should_break_line(lsym)) { | 1108 | if (ps.want_newline && should_break_line(lsym)) { | |
1109 | ps.want_newline = false; | 1109 | ps.want_newline = false; | |
1110 | output_line(); | 1110 | output_line(); | |
1111 | } | 1111 | } | |
1112 | ps.in_stmt_or_decl = true; | 1112 | ps.in_stmt_or_decl = true; | |
1113 | if (com.len > 0) | 1113 | if (com.len > 0) | |
1114 | move_com_to_code(lsym); | 1114 | move_com_to_code(lsym); | |
1115 | update_ps_lbrace_kind(lsym); | 1115 | update_ps_lbrace_kind(lsym); | |
1116 | } | 1116 | } | |
1117 | 1117 | |||
1118 | process_lsym(lsym); | 1118 | process_lsym(lsym); | |
1119 | 1119 | |||
1120 | if (lsym != lsym_preprocessing | 1120 | if (lsym != lsym_preprocessing | |
1121 | && lsym != lsym_newline | 1121 | && lsym != lsym_newline | |
1122 | && lsym != lsym_comment) | 1122 | && lsym != lsym_comment) | |
1123 | ps.prev_lsym = lsym; | 1123 | ps.prev_lsym = lsym; | |
1124 | 1124 | |||
1125 | debug_parser_state(); | 1125 | debug_parser_state(); | |
1126 | } | 1126 | } | |
1127 | } | 1127 | } | |
1128 | 1128 | |||
1129 | int | 1129 | int | |
1130 | main(int argc, char **argv) | 1130 | main(int argc, char **argv) | |
1131 | { | 1131 | { | |
1132 | init_globals(); | 1132 | init_globals(); | |
1133 | load_profiles(argc, argv); | 1133 | load_profiles(argc, argv); | |
1134 | parse_command_line(argc, argv); | 1134 | parse_command_line(argc, argv); | |
1135 | set_initial_indentation(); | 1135 | set_initial_indentation(); | |
1136 | return indent(); | 1136 | return indent(); | |
1137 | } | 1137 | } |
--- src/usr.bin/indent/io.c 2023/06/16 11:48:32 1.227
+++ src/usr.bin/indent/io.c 2023/06/17 22:28:49 1.228
@@ -1,438 +1,444 @@ | @@ -1,438 +1,444 @@ | |||
1 | /* $NetBSD: io.c,v 1.227 2023/06/16 11:48:32 rillig Exp $ */ | 1 | /* $NetBSD: io.c,v 1.228 2023/06/17 22:28:49 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.227 2023/06/16 11:48:32 rillig Exp $"); | 41 | __RCSID("$NetBSD: io.c,v 1.228 2023/06/17 22:28:49 rillig Exp $"); | |
42 | 42 | |||
43 | #include <stdio.h> | 43 | #include <stdio.h> | |
44 | 44 | |||
45 | #include "indent.h" | 45 | #include "indent.h" | |
46 | 46 | |||
47 | struct buffer inp; | 47 | struct buffer inp; | |
48 | const char *inp_p; | 48 | const char *inp_p; | |
49 | 49 | |||
50 | struct output_state out; | 50 | struct output_state out; | |
51 | enum indent_enabled indent_enabled; | 51 | enum indent_enabled indent_enabled; | |
52 | static int out_ind; /* width of the line that is being written */ | 52 | static int out_ind; /* width of the line that is being written */ | |
53 | static unsigned newlines = 2; /* the total of written and buffered newlines; | 53 | static unsigned newlines = 2; /* the total of written and buffered newlines; | |
54 | * 0 in the middle of a line, 1 after a single | 54 | * 0 in the middle of a line, 1 after a single | |
55 | * finished line, anything > 1 are trailing | 55 | * finished line, anything > 1 are trailing | |
56 | * blank lines */ | 56 | * blank lines */ | |
57 | static unsigned buffered_newlines; /* not yet written */ | 57 | static unsigned buffered_newlines; /* not yet written */ | |
58 | static int paren_indent; /* total indentation when parenthesized */ | 58 | static int paren_indent; /* total indentation when parenthesized */ | |
59 | 59 | |||
60 | 60 | |||
61 | static void | 61 | static void | |
62 | inp_read_next_line(void) | 62 | inp_read_next_line(void) | |
63 | { | 63 | { | |
64 | buf_clear(&inp); | 64 | buf_clear(&inp); | |
65 | 65 | |||
66 | for (;;) { | 66 | for (;;) { | |
67 | int ch = getc(input); | 67 | int ch = getc(input); | |
68 | if (ch == EOF) { | 68 | if (ch == EOF) { | |
69 | if (indent_enabled == indent_on) { | 69 | if (indent_enabled == indent_on) { | |
70 | buf_add_char(&inp, ' '); | 70 | buf_add_char(&inp, ' '); | |
71 | buf_add_char(&inp, '\n'); | 71 | buf_add_char(&inp, '\n'); | |
72 | } | 72 | } | |
73 | had_eof = true; | 73 | had_eof = true; | |
74 | break; | 74 | break; | |
75 | } | 75 | } | |
76 | 76 | |||
77 | if (ch != '\0') | 77 | if (ch != '\0') | |
78 | buf_add_char(&inp, (char)ch); | 78 | buf_add_char(&inp, (char)ch); | |
79 | if (ch == '\n') | 79 | if (ch == '\n') | |
80 | break; | 80 | break; | |
81 | } | 81 | } | |
82 | buf_terminate(&inp); | 82 | buf_terminate(&inp); | |
83 | inp_p = inp.s; | 83 | inp_p = inp.s; | |
84 | } | 84 | } | |
85 | 85 | |||
86 | void | 86 | void | |
87 | inp_read_line(void) | 87 | inp_read_line(void) | |
88 | { | 88 | { | |
89 | if (indent_enabled == indent_on) | 89 | if (indent_enabled == indent_on) | |
90 | buf_clear(&out.indent_off_text); | 90 | buf_clear(&out.indent_off_text); | |
91 | buf_add_chars(&out.indent_off_text, inp.s, inp.len); | 91 | buf_add_chars(&out.indent_off_text, inp.s, inp.len); | |
92 | inp_read_next_line(); | 92 | inp_read_next_line(); | |
93 | } | 93 | } | |
94 | 94 | |||
95 | void | 95 | void | |
96 | inp_skip(void) | 96 | inp_skip(void) | |
97 | { | 97 | { | |
98 | inp_p++; | 98 | inp_p++; | |
99 | if ((size_t)(inp_p - inp.s) >= inp.len) | 99 | if ((size_t)(inp_p - inp.s) >= inp.len) | |
100 | inp_read_line(); | 100 | inp_read_line(); | |
101 | } | 101 | } | |
102 | 102 | |||
103 | char | 103 | char | |
104 | inp_next(void) | 104 | inp_next(void) | |
105 | { | 105 | { | |
106 | char ch = inp_p[0]; | 106 | char ch = inp_p[0]; | |
107 | inp_skip(); | 107 | inp_skip(); | |
108 | return ch; | 108 | return ch; | |
109 | } | 109 | } | |
110 | 110 | |||
111 | 111 | |||
112 | static void | 112 | static void | |
113 | add_buffered_newline(void) | 113 | add_buffered_newline(void) | |
114 | { | 114 | { | |
115 | buffered_newlines++; | 115 | buffered_newlines++; | |
116 | newlines++; | 116 | newlines++; | |
117 | out_ind = 0; | 117 | out_ind = 0; | |
118 | } | 118 | } | |
119 | 119 | |||
120 | static void | 120 | static void | |
121 | write_buffered_newlines(void) | 121 | write_buffered_newlines(void) | |
122 | { | 122 | { | |
123 | for (; buffered_newlines > 0; buffered_newlines--) { | 123 | for (; buffered_newlines > 0; buffered_newlines--) { | |
124 | fputc('\n', output); | 124 | fputc('\n', output); | |
125 | debug_println("write_newline"); | 125 | debug_println("write_newline"); | |
126 | } | 126 | } | |
127 | } | 127 | } | |
128 | 128 | |||
129 | static void | 129 | static void | |
130 | write_range(const char *s, size_t len) | 130 | write_range(const char *s, size_t len) | |
131 | { | 131 | { | |
132 | write_buffered_newlines(); | 132 | write_buffered_newlines(); | |
133 | fwrite(s, 1, len, output); | 133 | fwrite(s, 1, len, output); | |
134 | debug_printf("write_range "); | 134 | debug_printf("write_range "); | |
135 | debug_vis_range(s, len); | 135 | debug_vis_range(s, len); | |
136 | debug_println(""); | 136 | debug_println(""); | |
137 | for (size_t i = 0; i < len; i++) | 137 | for (size_t i = 0; i < len; i++) | |
138 | newlines = s[i] == '\n' ? newlines + 1 : 0; | 138 | newlines = s[i] == '\n' ? newlines + 1 : 0; | |
139 | out_ind = ind_add(out_ind, s, len); | 139 | out_ind = ind_add(out_ind, s, len); | |
140 | } | 140 | } | |
141 | 141 | |||
142 | static void | 142 | static void | |
143 | write_indent(int new_ind) | 143 | write_indent(int new_ind) | |
144 | { | 144 | { | |
145 | write_buffered_newlines(); | 145 | write_buffered_newlines(); | |
146 | 146 | |||
147 | int ind = out_ind; | 147 | int ind = out_ind; | |
148 | 148 | |||
149 | if (opt.use_tabs) { | 149 | if (opt.use_tabs) { | |
150 | int n = new_ind / opt.tabsize - ind / opt.tabsize; | 150 | int n = new_ind / opt.tabsize - ind / opt.tabsize; | |
151 | if (n > 0) { | 151 | if (n > 0) { | |
152 | ind = ind - ind % opt.tabsize + n * opt.tabsize; | 152 | ind = ind - ind % opt.tabsize + n * opt.tabsize; | |
153 | while (n-- > 0) | 153 | while (n-- > 0) | |
154 | fputc('\t', output); | 154 | fputc('\t', output); | |
155 | newlines = 0; | 155 | newlines = 0; | |
156 | } | 156 | } | |
157 | } | 157 | } | |
158 | 158 | |||
159 | for (; ind < new_ind; ind++) { | 159 | for (; ind < new_ind; ind++) { | |
160 | fputc(' ', output); | 160 | fputc(' ', output); | |
161 | newlines = 0; | 161 | newlines = 0; | |
162 | } | 162 | } | |
163 | 163 | |||
164 | debug_println("write_indent %d", ind); | 164 | debug_println("write_indent %d", ind); | |
165 | out_ind = ind; | 165 | out_ind = ind; | |
166 | } | 166 | } | |
167 | 167 | |||
168 | static bool | 168 | static bool | |
169 | want_blank_line(void) | 169 | want_blank_line(void) | |
170 | { | 170 | { | |
171 | debug_println("%s: %s -> %s", __func__, | 171 | debug_println("%s: %s -> %s", __func__, | |
172 | line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]); | 172 | line_kind_name[out.prev_line_kind], line_kind_name[out.line_kind]); | |
173 | 173 | |||
174 | if (ps.blank_line_after_decl && ps.declaration == decl_no) { | 174 | if (ps.blank_line_after_decl && ps.declaration == decl_no) { | |
175 | ps.blank_line_after_decl = false; | 175 | ps.blank_line_after_decl = false; | |
176 | return true; | 176 | return true; | |
177 | } | 177 | } | |
178 | if (opt.blank_line_around_conditional_compilation) { | 178 | if (opt.blank_line_around_conditional_compilation) { | |
179 | if (out.prev_line_kind != lk_pre_if | 179 | if (out.prev_line_kind != lk_pre_if | |
180 | && out.line_kind == lk_pre_if) | 180 | && out.line_kind == lk_pre_if) | |
181 | return true; | 181 | return true; | |
182 | if (out.prev_line_kind == lk_pre_endif | 182 | if (out.prev_line_kind == lk_pre_endif | |
183 | && out.line_kind != lk_pre_endif) | 183 | && out.line_kind != lk_pre_endif) | |
184 | return true; | 184 | return true; | |
185 | } | 185 | } | |
186 | if (opt.blank_line_after_proc && out.prev_line_kind == lk_func_end | 186 | if (opt.blank_line_after_proc && out.prev_line_kind == lk_func_end | |
187 | && out.line_kind != lk_pre_endif && out.line_kind != lk_pre_other) | 187 | && out.line_kind != lk_pre_endif && out.line_kind != lk_pre_other) | |
188 | return true; | 188 | return true; | |
189 | if (opt.blank_line_before_block_comment | 189 | if (opt.blank_line_before_block_comment | |
190 | && out.line_kind == lk_block_comment) | 190 | && out.line_kind == lk_block_comment) | |
191 | return true; | 191 | return true; | |
192 | return false; | 192 | return false; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | static bool | 195 | static bool | |
196 | is_blank_line_optional(void) | 196 | is_blank_line_optional(void) | |
197 | { | 197 | { | |
198 | if (out.prev_line_kind == lk_stmt_head) | 198 | if (out.prev_line_kind == lk_stmt_head) | |
199 | return newlines >= 1; | 199 | return newlines >= 1; | |
200 | if (ps.psyms.len >= 3) | 200 | if (ps.psyms.len >= 3) | |
201 | return newlines >= 2; | 201 | return newlines >= 2; | |
202 | return newlines >= 3; | 202 | return newlines >= 3; | |
203 | } | 203 | } | |
204 | 204 | |||
205 | static int | 205 | static int | |
206 | compute_case_label_indent(void) | 206 | compute_case_label_indent(void) | |
207 | { | 207 | { | |
208 | size_t i = ps.psyms.len - 1; | 208 | size_t i = ps.psyms.len - 1; | |
209 | while (i > 0 && ps.psyms.sym[i] != psym_switch_expr) | 209 | while (i > 0 && ps.psyms.sym[i] != psym_switch_expr) | |
210 | i--; | 210 | i--; | |
211 | float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent; | 211 | float case_ind = (float)ps.psyms.ind_level[i] + opt.case_indent; | |
212 | // TODO: case_ind may become negative here. | 212 | // TODO: case_ind may become negative here. | |
213 | return (int)(case_ind * (float)opt.indent_size); | 213 | return (int)(case_ind * (float)opt.indent_size); | |
214 | } | 214 | } | |
215 | 215 | |||
216 | int | 216 | int | |
217 | compute_label_indent(void) | 217 | compute_label_indent(void) | |
218 | { | 218 | { | |
219 | if (out.line_kind == lk_case_or_default) | 219 | if (out.line_kind == lk_case_or_default) | |
220 | return compute_case_label_indent(); | 220 | return compute_case_label_indent(); | |
221 | if (lab.s[0] == '#') | 221 | if (lab.s[0] == '#') | |
222 | return 0; | 222 | return 0; | |
223 | // TODO: the indentation may become negative here. | 223 | // TODO: the indentation may become negative here. | |
224 | return opt.indent_size * (ps.ind_level - 2); | 224 | return opt.indent_size * (ps.ind_level - 2); | |
225 | } | 225 | } | |
226 | 226 | |||
227 | static void | 227 | static void | |
228 | output_line_label(void) | 228 | output_line_label(void) | |
229 | { | 229 | { | |
230 | write_indent(compute_label_indent()); | 230 | write_indent(compute_label_indent()); | |
231 | write_range(lab.s, lab.len); | 231 | write_range(lab.s, lab.len); | |
232 | } | 232 | } | |
233 | 233 | |||
234 | static int | 234 | static int | |
235 | compute_lined_up_code_indent(int base_ind) | 235 | compute_lined_up_code_indent(int base_ind) | |
236 | { | 236 | { | |
237 | int ind = paren_indent; | 237 | int ind = paren_indent; | |
238 | int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; | 238 | int overflow = ind_add(ind, code.s, code.len) - opt.max_line_length; | |
239 | if (overflow >= 0 | 239 | if (overflow >= 0 | |
240 | && ind_add(base_ind, code.s, code.len) < opt.max_line_length) { | 240 | && ind_add(base_ind, code.s, code.len) < opt.max_line_length) { | |
241 | ind -= 2 + overflow; | 241 | ind -= 2 + overflow; | |
242 | if (ind < base_ind) | 242 | if (ind < base_ind) | |
243 | ind = base_ind; | 243 | ind = base_ind; | |
244 | } | 244 | } | |
245 | 245 | |||
246 | if (ps.extra_expr_indent != eei_no | 246 | if (ps.extra_expr_indent != eei_no | |
247 | && ind == base_ind + opt.indent_size) | 247 | && ind == base_ind + opt.indent_size) | |
248 | ind += opt.continuation_indent; | 248 | ind += opt.continuation_indent; | |
249 | return ind; | 249 | return ind; | |
250 | } | 250 | } | |
251 | 251 | |||
252 | int | 252 | int | |
253 | compute_code_indent(void) | 253 | compute_code_indent(void) | |
254 | { | 254 | { | |
255 | int base_ind = ps.ind_level * opt.indent_size; | 255 | int base_ind = ps.ind_level * opt.indent_size; | |
256 | 256 | |||
257 | if (ps.ind_paren_level == 0) { | 257 | if (ps.ind_paren_level == 0) { | |
258 | if (ps.line_is_stmt_cont) | 258 | if (ps.line_is_stmt_cont) | |
259 | return base_ind + opt.continuation_indent; | 259 | return base_ind + opt.continuation_indent; | |
260 | return base_ind; | 260 | return base_ind; | |
261 | } | 261 | } | |
262 | 262 | |||
263 | if (opt.lineup_to_parens) { | 263 | if (opt.lineup_to_parens) { | |
264 | if (opt.lineup_to_parens_always) | 264 | if (opt.lineup_to_parens_always) | |
265 | return paren_indent; | 265 | return paren_indent; | |
266 | return compute_lined_up_code_indent(base_ind); | 266 | return compute_lined_up_code_indent(base_ind); | |
267 | } | 267 | } | |
268 | 268 | |||
269 | int rel_ind = opt.continuation_indent * ps.ind_paren_level; | 269 | int rel_ind = opt.continuation_indent * ps.ind_paren_level; | |
270 | if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size) | 270 | if (ps.extra_expr_indent != eei_no && rel_ind == opt.indent_size) | |
271 | rel_ind += opt.continuation_indent; | 271 | rel_ind += opt.continuation_indent; | |
272 | return base_ind + rel_ind; | 272 | return base_ind + rel_ind; | |
273 | } | 273 | } | |
274 | 274 | |||
275 | static void | 275 | static void | |
276 | output_line_code(void) | 276 | output_line_code(void) | |
277 | { | 277 | { | |
278 | int target_ind = compute_code_indent(); | 278 | int target_ind = compute_code_indent(); | |
279 | for (size_t i = 0; i < ps.paren.len; i++) { | 279 | for (size_t i = 0; i < ps.paren.len; i++) { | |
280 | int paren_ind = ps.paren.item[i].indent; | 280 | int paren_ind = ps.paren.item[i].indent; | |
281 | if (paren_ind >= 0) { | 281 | if (paren_ind >= 0) { | |
282 | ps.paren.item[i].indent = | 282 | ps.paren.item[i].indent = | |
283 | -1 - (paren_ind + target_ind); | 283 | -1 - (paren_ind + target_ind); | |
284 | debug_println( | 284 | debug_println( | |
285 | "setting paren_indents[%zu] from %d to %d " | 285 | "setting paren_indents[%zu] from %d to %d " | |
286 | "for column %d", | 286 | "for column %d", | |
287 | i, paren_ind, | 287 | i, paren_ind, | |
288 | ps.paren.item[i].indent, target_ind + 1); | 288 | ps.paren.item[i].indent, target_ind + 1); | |
289 | } | 289 | } | |
290 | } | 290 | } | |
291 | 291 | |||
292 | if (lab.len > 0 && target_ind <= out_ind) | 292 | if (lab.len > 0 && target_ind <= out_ind) | |
293 | write_range(" ", 1); | 293 | write_range(" ", 1); | |
294 | write_indent(target_ind); | 294 | write_indent(target_ind); | |
295 | write_range(code.s, code.len); | 295 | write_range(code.s, code.len); | |
296 | } | 296 | } | |
297 | 297 | |||
298 | static void | 298 | static void | |
299 | output_comment(void) | 299 | output_comment(void) | |
300 | { | 300 | { | |
301 | int target_ind = ps.comment_ind; | 301 | int target_ind = ps.comment_ind; | |
302 | const char *p; | 302 | const char *p; | |
303 | 303 | |||
304 | if (ps.comment_cont) | 304 | if (ps.comment_cont) | |
305 | target_ind += ps.comment_shift; | 305 | target_ind += ps.comment_shift; | |
306 | ps.comment_cont = true; | 306 | ps.comment_cont = true; | |
307 | 307 | |||
308 | /* consider the original indentation in case this is a box comment */ | 308 | /* consider the original indentation in case this is a box comment */ | |
309 | for (p = com.s; *p == '\t'; p++) | 309 | for (p = com.s; *p == '\t'; p++) | |
310 | target_ind += opt.tabsize; | 310 | target_ind += opt.tabsize; | |
311 | 311 | |||
312 | for (; target_ind < 0; p++) { | 312 | for (; target_ind < 0; p++) { | |
313 | if (*p == ' ') | 313 | if (*p == ' ') | |
314 | target_ind++; | 314 | target_ind++; | |
315 | else if (*p == '\t') | 315 | else if (*p == '\t') | |
316 | target_ind = next_tab(target_ind); | 316 | target_ind = next_tab(target_ind); | |
317 | else { | 317 | else { | |
318 | target_ind = 0; | 318 | target_ind = 0; | |
319 | break; | 319 | break; | |
320 | } | 320 | } | |
321 | } | 321 | } | |
322 | 322 | |||
323 | if (out_ind > target_ind) | 323 | if (out_ind > target_ind) | |
324 | add_buffered_newline(); | 324 | add_buffered_newline(); | |
325 | 325 | |||
326 | while (com.s + com.len > p && ch_isspace(com.s[com.len - 1])) | 326 | while (com.s + com.len > p && ch_isspace(com.s[com.len - 1])) | |
327 | com.len--; | 327 | com.len--; | |
328 | buf_terminate(&com); | 328 | buf_terminate(&com); | |
329 | 329 | |||
330 | write_indent(target_ind); | 330 | write_indent(target_ind); | |
331 | write_range(p, com.len - (size_t)(p - com.s)); | 331 | write_range(p, com.len - (size_t)(p - com.s)); | |
332 | } | 332 | } | |
333 | 333 | |||
334 | /* | |||
335 | * Write a line of formatted source to the output file. The line consists of | |||
336 | * the label, the code and the comment. | |||
337 | */ | |||
334 | static void | 338 | static void | |
335 | output_indented_line(void) | 339 | output_indented_line(void) | |
336 | { | 340 | { | |
337 | if (lab.len == 0 && code.len == 0 && com.len == 0) | 341 | if (lab.len == 0 && code.len == 0 && com.len == 0) | |
338 | out.line_kind = lk_blank; | 342 | out.line_kind = lk_blank; | |
339 | 343 | |||
340 | if (want_blank_line() && newlines < 2 | 344 | if (want_blank_line() && newlines < 2 | |
341 | && out.line_kind != lk_blank) | 345 | && out.line_kind != lk_blank) | |
342 | add_buffered_newline(); | 346 | add_buffered_newline(); | |
343 | 347 | |||
344 | /* This kludge aligns function definitions correctly. */ | 348 | /* This kludge aligns function definitions correctly. */ | |
345 | if (ps.ind_level == 0) | 349 | if (ps.ind_level == 0) | |
346 | ps.line_is_stmt_cont = false; | 350 | ps.line_is_stmt_cont = false; | |
347 | 351 | |||
348 | if (opt.blank_line_after_decl && ps.declaration == decl_end | 352 | if (opt.blank_line_after_decl && ps.declaration == decl_end | |
349 | && ps.psyms.len > 2) { | 353 | && ps.psyms.len > 2) { | |
350 | ps.declaration = decl_no; | 354 | ps.declaration = decl_no; | |
351 | ps.blank_line_after_decl = true; | 355 | ps.blank_line_after_decl = true; | |
352 | } | 356 | } | |
353 | 357 | |||
354 | if (opt.swallow_optional_blank_lines | 358 | if (opt.swallow_optional_blank_lines | |
355 | && out.line_kind == lk_blank | 359 | && out.line_kind == lk_blank | |
356 | && is_blank_line_optional()) | 360 | && is_blank_line_optional()) | |
357 | return; | 361 | return; | |
358 | 362 | |||
359 | if (lab.len > 0) | 363 | if (lab.len > 0) | |
360 | output_line_label(); | 364 | output_line_label(); | |
361 | if (code.len > 0) | 365 | if (code.len > 0) | |
362 | output_line_code(); | 366 | output_line_code(); | |
363 | if (com.len > 0) | 367 | if (com.len > 0) | |
364 | output_comment(); | 368 | output_comment(); | |
365 | add_buffered_newline(); | 369 | add_buffered_newline(); | |
366 | if (out.line_kind != lk_blank) | 370 | if (out.line_kind != lk_blank) | |
367 | write_buffered_newlines(); | 371 | write_buffered_newlines(); | |
368 | 372 | |||
369 | out.prev_line_kind = out.line_kind; | 373 | out.prev_line_kind = out.line_kind; | |
370 | } | 374 | } | |
371 | 375 | |||
372 | static bool | 376 | static bool | |
373 | is_stmt_cont(void) | 377 | is_stmt_cont(void) | |
374 | { | 378 | { | |
375 | if (ps.psyms.len >= 2 | 379 | if (ps.psyms.len >= 2 | |
376 | && ps.psyms.sym[ps.psyms.len - 2] == psym_lbrace_enum | 380 | && ps.psyms.sym[ps.psyms.len - 2] == psym_lbrace_enum | |
377 | && ps.prev_lsym == lsym_comma | 381 | && ps.prev_lsym == lsym_comma | |
378 | && ps.paren.len == 0) | 382 | && ps.paren.len == 0) | |
379 | return false; | 383 | return false; | |
380 | return ps.in_stmt_or_decl | 384 | return ps.in_stmt_or_decl | |
381 | && (!ps.in_decl || ps.in_init) | 385 | && (!ps.in_decl || ps.in_init) | |
382 | && ps.init_level == 0; | 386 | && ps.init_level == 0; | |
383 | } | 387 | } | |
384 | 388 | |||
385 | /* | 389 | static void | |
386 | * Write a line of formatted source to the output file. The line consists of | 390 | prepare_next_line(void) | |
387 | * the label, the code and the comment. | |||
388 | */ | |||
389 | void | |||
390 | output_line(void) | |||
391 | { | 391 | { | |
392 | debug_blank_line(); | |||
393 | debug_printf("%s", __func__); | |||
394 | debug_buffers(); | |||
395 | ||||
396 | if (indent_enabled == indent_on) | |||
397 | output_indented_line(); | |||
398 | else if (indent_enabled == indent_last_off_line) { | |||
399 | indent_enabled = indent_on; | |||
400 | write_range(out.indent_off_text.s, out.indent_off_text.len); | |||
401 | buf_clear(&out.indent_off_text); | |||
402 | } | |||
403 | ||||
404 | buf_clear(&lab); | |||
405 | buf_clear(&code); | |||
406 | buf_clear(&com); | |||
407 | ||||
408 | ps.line_has_decl = ps.in_decl; | 392 | ps.line_has_decl = ps.in_decl; | |
409 | ps.line_has_func_def = false; | 393 | ps.line_has_func_def = false; | |
410 | ps.line_is_stmt_cont = is_stmt_cont(); | 394 | ps.line_is_stmt_cont = is_stmt_cont(); | |
411 | ps.decl_indent_done = false; | 395 | ps.decl_indent_done = false; | |
412 | if (ps.extra_expr_indent == eei_last) | 396 | if (ps.extra_expr_indent == eei_last) | |
413 | ps.extra_expr_indent = eei_no; | 397 | ps.extra_expr_indent = eei_no; | |
414 | if (!(ps.psyms.sym[ps.psyms.len - 1] == psym_if_expr_stmt_else | 398 | if (!(ps.psyms.sym[ps.psyms.len - 1] == psym_if_expr_stmt_else | |
415 | && ps.paren.len > 0)) | 399 | && ps.paren.len > 0)) | |
416 | ps.ind_level = ps.ind_level_follow; | 400 | ps.ind_level = ps.ind_level_follow; | |
417 | ps.ind_paren_level = (int)ps.paren.len; | 401 | ps.ind_paren_level = (int)ps.paren.len; | |
418 | ps.want_blank = false; | 402 | ps.want_blank = false; | |
419 | 403 | |||
420 | if (ps.paren.len > 0) { | 404 | if (ps.paren.len > 0) { | |
421 | /* TODO: explain what negative indentation means */ | 405 | /* TODO: explain what negative indentation means */ | |
422 | paren_indent = -1 - ps.paren.item[ps.paren.len - 1].indent; | 406 | paren_indent = -1 - ps.paren.item[ps.paren.len - 1].indent; | |
423 | debug_println("paren_indent is now %d", paren_indent); | 407 | debug_println("paren_indent is now %d", paren_indent); | |
424 | } | 408 | } | |
425 | 409 | |||
426 | out.line_kind = lk_other; | 410 | out.line_kind = lk_other; | |
427 | } | 411 | } | |
428 | 412 | |||
429 | void | 413 | void | |
414 | output_line(void) | |||
415 | { | |||
416 | debug_blank_line(); | |||
417 | debug_printf("%s", __func__); | |||
418 | debug_buffers(); | |||
419 | ||||
420 | if (indent_enabled == indent_on) | |||
421 | output_indented_line(); | |||
422 | else if (indent_enabled == indent_last_off_line) { | |||
423 | indent_enabled = indent_on; | |||
424 | write_range(out.indent_off_text.s, out.indent_off_text.len); | |||
425 | buf_clear(&out.indent_off_text); | |||
426 | } | |||
427 | ||||
428 | buf_clear(&lab); | |||
429 | buf_clear(&code); | |||
430 | buf_clear(&com); | |||
431 | ||||
432 | prepare_next_line(); | |||
433 | } | |||
434 | ||||
435 | void | |||
430 | finish_output(void) | 436 | finish_output(void) | |
431 | { | 437 | { | |
432 | output_line(); | 438 | output_line(); | |
433 | if (indent_enabled != indent_on) { | 439 | if (indent_enabled != indent_on) { | |
434 | indent_enabled = indent_last_off_line; | 440 | indent_enabled = indent_last_off_line; | |
435 | output_line(); | 441 | output_line(); | |
436 | } | 442 | } | |
437 | fflush(output); | 443 | fflush(output); | |
438 | } | 444 | } |
--- src/usr.bin/indent/lexi.c 2023/06/16 23:51:32 1.230
+++ src/usr.bin/indent/lexi.c 2023/06/17 22:28:49 1.231
@@ -1,682 +1,682 @@ | @@ -1,682 +1,682 @@ | |||
1 | /* $NetBSD: lexi.c,v 1.230 2023/06/16 23:51:32 rillig Exp $ */ | 1 | /* $NetBSD: lexi.c,v 1.231 2023/06/17 22:28:49 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: lexi.c,v 1.230 2023/06/16 23:51:32 rillig Exp $"); | 41 | __RCSID("$NetBSD: lexi.c,v 1.231 2023/06/17 22:28:49 rillig Exp $"); | |
42 | 42 | |||
43 | #include <stdlib.h> | 43 | #include <stdlib.h> | |
44 | #include <string.h> | 44 | #include <string.h> | |
45 | 45 | |||
46 | #include "indent.h" | 46 | #include "indent.h" | |
47 | 47 | |||
48 | /* must be sorted alphabetically, is used in binary search */ | 48 | /* must be sorted alphabetically, is used in binary search */ | |
49 | static const struct keyword { | 49 | static const struct keyword { | |
50 | const char name[12]; | 50 | const char name[12]; | |
51 | lexer_symbol lsym; | 51 | lexer_symbol lsym; | |
52 | } keywords[] = { | 52 | } keywords[] = { | |
53 | {"_Bool", lsym_type}, | 53 | {"_Bool", lsym_type}, | |
54 | {"_Complex", lsym_type}, | 54 | {"_Complex", lsym_type}, | |
55 | {"_Imaginary", lsym_type}, | 55 | {"_Imaginary", lsym_type}, | |
56 | {"auto", lsym_modifier}, | 56 | {"auto", lsym_modifier}, | |
57 | {"bool", lsym_type}, | 57 | {"bool", lsym_type}, | |
58 | {"break", lsym_word}, | 58 | {"break", lsym_word}, | |
59 | {"case", lsym_case}, | 59 | {"case", lsym_case}, | |
60 | {"char", lsym_type}, | 60 | {"char", lsym_type}, | |
61 | {"complex", lsym_type}, | 61 | {"complex", lsym_type}, | |
62 | {"const", lsym_modifier}, | 62 | {"const", lsym_modifier}, | |
63 | {"continue", lsym_word}, | 63 | {"continue", lsym_word}, | |
64 | {"default", lsym_default}, | 64 | {"default", lsym_default}, | |
65 | {"do", lsym_do}, | 65 | {"do", lsym_do}, | |
66 | {"double", lsym_type}, | 66 | {"double", lsym_type}, | |
67 | {"else", lsym_else}, | 67 | {"else", lsym_else}, | |
68 | {"enum", lsym_tag}, | 68 | {"enum", lsym_tag}, | |
69 | {"extern", lsym_modifier}, | 69 | {"extern", lsym_modifier}, | |
70 | {"float", lsym_type}, | 70 | {"float", lsym_type}, | |
71 | {"for", lsym_for}, | 71 | {"for", lsym_for}, | |
72 | {"goto", lsym_word}, | 72 | {"goto", lsym_word}, | |
73 | {"if", lsym_if}, | 73 | {"if", lsym_if}, | |
74 | {"imaginary", lsym_type}, | 74 | {"imaginary", lsym_type}, | |
75 | {"inline", lsym_modifier}, | 75 | {"inline", lsym_modifier}, | |
76 | {"int", lsym_type}, | 76 | {"int", lsym_type}, | |
77 | {"long", lsym_type}, | 77 | {"long", lsym_type}, | |
78 | {"offsetof", lsym_offsetof}, | 78 | {"offsetof", lsym_offsetof}, | |
79 | {"register", lsym_modifier}, | 79 | {"register", lsym_modifier}, | |
80 | {"restrict", lsym_word}, | 80 | {"restrict", lsym_word}, | |
81 | {"return", lsym_return}, | 81 | {"return", lsym_return}, | |
82 | {"short", lsym_type}, | 82 | {"short", lsym_type}, | |
83 | {"signed", lsym_type}, | 83 | {"signed", lsym_type}, | |
84 | {"sizeof", lsym_sizeof}, | 84 | {"sizeof", lsym_sizeof}, | |
85 | {"static", lsym_modifier}, | 85 | {"static", lsym_modifier}, | |
86 | {"struct", lsym_tag}, | 86 | {"struct", lsym_tag}, | |
87 | {"switch", lsym_switch}, | 87 | {"switch", lsym_switch}, | |
88 | {"typedef", lsym_typedef}, | 88 | {"typedef", lsym_typedef}, | |
89 | {"union", lsym_tag}, | 89 | {"union", lsym_tag}, | |
90 | {"unsigned", lsym_type}, | 90 | {"unsigned", lsym_type}, | |
91 | {"void", lsym_type}, | 91 | {"void", lsym_type}, | |
92 | {"volatile", lsym_modifier}, | 92 | {"volatile", lsym_modifier}, | |
93 | {"while", lsym_while} | 93 | {"while", lsym_while} | |
94 | }; | 94 | }; | |
95 | 95 | |||
96 | static struct { | 96 | static struct { | |
97 | const char **items; | 97 | const char **items; | |
98 | unsigned int len; | 98 | unsigned int len; | |
99 | unsigned int cap; | 99 | unsigned int cap; | |
100 | } typenames; | 100 | } typenames; | |
101 | 101 | |||
102 | /*- | 102 | /*- | |
103 | * The transition table below was rewritten by hand from lx's output, given | 103 | * The transition table below was rewritten by hand from lx's output, given | |
104 | * the following definitions. lx is Katherine Flavel's lexer generator. | 104 | * the following definitions. lx is Katherine Flavel's lexer generator. | |
105 | * | 105 | * | |
106 | * O = /[0-7]/; D = /[0-9]/; NZ = /[1-9]/; | 106 | * O = /[0-7]/; D = /[0-9]/; NZ = /[1-9]/; | |
107 | * H = /[a-f0-9]/i; B = /[0-1]/; HP = /0x/i; | 107 | * H = /[a-f0-9]/i; B = /[0-1]/; HP = /0x/i; | |
108 | * BP = /0b/i; E = /e[+\-]?/i D+; P = /p[+\-]?/i D+; | 108 | * BP = /0b/i; E = /e[+\-]?/i D+; P = /p[+\-]?/i D+; | |
109 | * FS = /[fl]/i; IS = /u/i /(l|L|ll|LL)/? | /(l|L|ll|LL)/ /u/i?; | 109 | * FS = /[fl]/i; IS = /u/i /(l|L|ll|LL)/? | /(l|L|ll|LL)/ /u/i?; | |
110 | * | 110 | * | |
111 | * D+ E FS? -> $float; | 111 | * D+ E FS? -> $float; | |
112 | * D* "." D+ E? FS? -> $float; | 112 | * D* "." D+ E? FS? -> $float; | |
113 | * D+ "." E? FS? -> $float; HP H+ IS? -> $int; | 113 | * D+ "." E? FS? -> $float; HP H+ IS? -> $int; | |
114 | * HP H+ P FS? -> $float; NZ D* IS? -> $int; | 114 | * HP H+ P FS? -> $float; NZ D* IS? -> $int; | |
115 | * HP H* "." H+ P FS? -> $float; "0" O* IS? -> $int; | 115 | * HP H* "." H+ P FS? -> $float; "0" O* IS? -> $int; | |
116 | * HP H+ "." P FS -> $float; BP B+ IS? -> $int; | 116 | * HP H+ "." P FS -> $float; BP B+ IS? -> $int; | |
117 | */ | 117 | */ | |
118 | /* INDENT OFF */ | 118 | /* INDENT OFF */ | |
119 | static const unsigned char lex_number_state[][26] = { | 119 | static const unsigned char lex_number_state[][26] = { | |
120 | /* examples: | 120 | /* examples: | |
121 | 00 | 121 | 00 | |
122 | s 0xx | 122 | s 0xx | |
123 | t 00xaa | 123 | t 00xaa | |
124 | a 11 101100xxa.. | 124 | a 11 101100xxa.. | |
125 | r 11ee0001101lbuuxx.a.pp | 125 | r 11ee0001101lbuuxx.a.pp | |
126 | t.01.e+008bLuxll0Ll.aa.p+0 | 126 | t.01.e+008bLuxll0Ll.aa.p+0 | |
127 | states: ABCDEFGHIJKLMNOPQRSTUVWXYZ */ | 127 | states: ABCDEFGHIJKLMNOPQRSTUVWXYZ */ | |
128 | [0] = "uuiifuufiuuiiuiiiiiuiuuuuu", /* (other) */ | 128 | [0] = "uuiifuufiuuiiuiiiiiuiuuuuu", /* (other) */ | |
129 | [1] = "CEIDEHHHIJQ U Q VUVVZZZ", /* 0 */ | 129 | [1] = "CEIDEHHHIJQ U Q VUVVZZZ", /* 0 */ | |
130 | [2] = "DEIDEHHHIJQ U Q VUVVZZZ", /* 1 */ | 130 | [2] = "DEIDEHHHIJQ U Q VUVVZZZ", /* 1 */ | |
131 | [3] = "DEIDEHHHIJ U VUVVZZZ", /* 2 3 4 5 6 7 */ | 131 | [3] = "DEIDEHHHIJ U VUVVZZZ", /* 2 3 4 5 6 7 */ | |
132 | [4] = "DEJDEHHHJJ U VUVVZZZ", /* 8 9 */ | 132 | [4] = "DEJDEHHHJJ U VUVVZZZ", /* 8 9 */ | |
133 | [5] = " U VUVV ", /* A a C c D d */ | 133 | [5] = " U VUVV ", /* A a C c D d */ | |
134 | [6] = " K U VUVV ", /* B b */ | 134 | [6] = " K U VUVV ", /* B b */ | |
135 | [7] = " FFF FF U VUVV ", /* E e */ | 135 | [7] = " FFF FF U VUVV ", /* E e */ | |
136 | [8] = " f f U VUVV f", /* F f */ | 136 | [8] = " f f U VUVV f", /* F f */ | |
137 | [9] = " LLf fL PR Li L f", /* L */ | 137 | [9] = " LLf fL PR Li L f", /* L */ | |
138 | [10] = " OOf fO S P O i O f", /* l */ | 138 | [10] = " OOf fO S P O i O f", /* l */ | |
139 | [11] = " FFX ", /* P p */ | 139 | [11] = " FFX ", /* P p */ | |
140 | [12] = " MM M i iiM M ", /* U u */ | 140 | [12] = " MM M i iiM M ", /* U u */ | |
141 | [13] = " N ", /* X x */ | 141 | [13] = " N ", /* X x */ | |
142 | [14] = " G Y ", /* + - */ | 142 | [14] = " G Y ", /* + - */ | |
143 | [15] = "B EE EE T W ", /* . */ | 143 | [15] = "B EE EE T W ", /* . */ | |
144 | /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ | 144 | /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ | |
145 | }; | 145 | }; | |
146 | /* INDENT ON */ | 146 | /* INDENT ON */ | |
147 | 147 | |||
148 | static const unsigned char lex_number_row[] = { | 148 | static const unsigned char lex_number_row[] = { | |
149 | ['0'] = 1, | 149 | ['0'] = 1, | |
150 | ['1'] = 2, | 150 | ['1'] = 2, | |
151 | ['2'] = 3, ['3'] = 3, ['4'] = 3, ['5'] = 3, ['6'] = 3, ['7'] = 3, | 151 | ['2'] = 3, ['3'] = 3, ['4'] = 3, ['5'] = 3, ['6'] = 3, ['7'] = 3, | |
152 | ['8'] = 4, ['9'] = 4, | 152 | ['8'] = 4, ['9'] = 4, | |
153 | ['A'] = 5, ['a'] = 5, ['C'] = 5, ['c'] = 5, ['D'] = 5, ['d'] = 5, | 153 | ['A'] = 5, ['a'] = 5, ['C'] = 5, ['c'] = 5, ['D'] = 5, ['d'] = 5, | |
154 | ['B'] = 6, ['b'] = 6, | 154 | ['B'] = 6, ['b'] = 6, | |
155 | ['E'] = 7, ['e'] = 7, | 155 | ['E'] = 7, ['e'] = 7, | |
156 | ['F'] = 8, ['f'] = 8, | 156 | ['F'] = 8, ['f'] = 8, | |
157 | ['L'] = 9, | 157 | ['L'] = 9, | |
158 | ['l'] = 10, | 158 | ['l'] = 10, | |
159 | ['P'] = 11, ['p'] = 11, | 159 | ['P'] = 11, ['p'] = 11, | |
160 | ['U'] = 12, ['u'] = 12, | 160 | ['U'] = 12, ['u'] = 12, | |
161 | ['X'] = 13, ['x'] = 13, | 161 | ['X'] = 13, ['x'] = 13, | |
162 | ['+'] = 14, ['-'] = 14, | 162 | ['+'] = 14, ['-'] = 14, | |
163 | ['.'] = 15, | 163 | ['.'] = 15, | |
164 | }; | 164 | }; | |
165 | 165 | |||
166 | 166 | |||
167 | static bool | 167 | static bool | |
168 | is_identifier_start(char ch) | 168 | is_identifier_start(char ch) | |
169 | { | 169 | { | |
170 | return ch_isalpha(ch) || ch == '_' || ch == '$'; | 170 | return ch_isalpha(ch) || ch == '_' || ch == '$'; | |
171 | } | 171 | } | |
172 | 172 | |||
173 | static bool | 173 | static bool | |
174 | is_identifier_part(char ch) | 174 | is_identifier_part(char ch) | |
175 | { | 175 | { | |
176 | return ch_isalnum(ch) || ch == '_' || ch == '$'; | 176 | return ch_isalnum(ch) || ch == '_' || ch == '$'; | |
177 | } | 177 | } | |
178 | 178 | |||
179 | static void | 179 | static void | |
180 | token_add_char(char ch) | 180 | token_add_char(char ch) | |
181 | { | 181 | { | |
182 | buf_add_char(&token, ch); | 182 | buf_add_char(&token, ch); | |
183 | } | 183 | } | |
184 | 184 | |||
185 | static void | 185 | static void | |
186 | lex_number(void) | 186 | lex_number(void) | |
187 | { | 187 | { | |
188 | for (unsigned char s = 'A'; s != 'f' && s != 'i' && s != 'u';) { | 188 | for (unsigned char s = 'A'; s != 'f' && s != 'i' && s != 'u';) { | |
189 | unsigned char ch = (unsigned char)inp_p[0]; | 189 | unsigned char ch = (unsigned char)*inp_p; | |
190 | if (ch == '\\' && inp_p[1] == '\n') { | 190 | if (ch == '\\' && inp_p[1] == '\n') { | |
191 | inp_p++; | 191 | inp_p++; | |
192 | inp_skip(); | 192 | inp_skip(); | |
193 | line_no++; | 193 | line_no++; | |
194 | continue; | 194 | continue; | |
195 | } | 195 | } | |
196 | if (ch >= array_length(lex_number_row) | 196 | if (ch >= array_length(lex_number_row) | |
197 | || lex_number_row[ch] == 0) | 197 | || lex_number_row[ch] == 0) | |
198 | break; | 198 | break; | |
199 | 199 | |||
200 | unsigned char row = lex_number_row[ch]; | 200 | unsigned char row = lex_number_row[ch]; | |
201 | if (lex_number_state[row][s - 'A'] == ' ') { | 201 | if (lex_number_state[row][s - 'A'] == ' ') { | |
202 | /*- | 202 | // lex_number_state[0][s - 'A'] now indicates the type: | |
203 | * lex_number_state[0][s - 'A'] now indicates the type: | 203 | // f = floating, i = integer, u = unknown | |
204 | * f = floating, i = integer, u = unknown | |||
205 | */ | |||
206 | return; | 204 | return; | |
207 | } | 205 | } | |
208 | 206 | |||
209 | s = lex_number_state[row][s - 'A']; | 207 | s = lex_number_state[row][s - 'A']; | |
210 | token_add_char(inp_next()); | 208 | token_add_char(inp_next()); | |
211 | } | 209 | } | |
212 | } | 210 | } | |
213 | 211 | |||
214 | static void | 212 | static void | |
215 | lex_word(void) | 213 | lex_word(void) | |
216 | { | 214 | { | |
217 | for (;;) { | 215 | for (;;) { | |
218 | if (is_identifier_part(inp_p[0])) | 216 | if (is_identifier_part(inp_p[0])) | |
219 | token_add_char(*inp_p++); | 217 | token_add_char(*inp_p++); | |
220 | else if (inp_p[0] == '\\' && inp_p[1] == '\n') { | 218 | else if (inp_p[0] == '\\' && inp_p[1] == '\n') { | |
221 | inp_p++; | 219 | inp_p++; | |
222 | inp_skip(); | 220 | inp_skip(); | |
223 | line_no++; | 221 | line_no++; | |
224 | } else | 222 | } else | |
225 | return; | 223 | return; | |
226 | } | 224 | } | |
227 | } | 225 | } | |
228 | 226 | |||
229 | static void | 227 | static void | |
230 | lex_char_or_string(void) | 228 | lex_char_or_string(void) | |
231 | { | 229 | { | |
232 | for (char delim = token.s[token.len - 1];;) { | 230 | for (char delim = token.s[token.len - 1];;) { | |
233 | if (inp_p[0] == '\n') { | 231 | if (*inp_p == '\n') { | |
234 | diag(1, "Unterminated literal"); | 232 | diag(1, "Unterminated literal"); | |
235 | return; | 233 | return; | |
236 | } | 234 | } | |
237 | 235 | |||
238 | token_add_char(*inp_p++); | 236 | token_add_char(*inp_p++); | |
239 | if (token.s[token.len - 1] == delim) | 237 | if (token.s[token.len - 1] == delim) | |
240 | return; | 238 | return; | |
241 | 239 | |||
242 | if (token.s[token.len - 1] == '\\') { | 240 | if (token.s[token.len - 1] == '\\') { | |
243 | if (inp_p[0] == '\n') | 241 | if (*inp_p == '\n') | |
244 | ++line_no; | 242 | line_no++; | |
245 | token_add_char(inp_next()); | 243 | token_add_char(inp_next()); | |
246 | } | 244 | } | |
247 | } | 245 | } | |
248 | } | 246 | } | |
249 | 247 | |||
250 | /* Guess whether the current token is a declared type. */ | 248 | /* Guess whether the current token is a declared type. */ | |
251 | static bool | 249 | static bool | |
252 | probably_typename(void) | 250 | probably_typename(void) | |
253 | { | 251 | { | |
254 | if (ps.prev_lsym == lsym_modifier) | 252 | if (ps.prev_lsym == lsym_modifier) | |
255 | return true; | 253 | return true; | |
256 | if (ps.in_init) | 254 | if (ps.in_init) | |
257 | return false; | 255 | return false; | |
258 | if (ps.in_stmt_or_decl) /* XXX: this condition looks incorrect */ | 256 | if (ps.in_stmt_or_decl) /* XXX: this condition looks incorrect */ | |
259 | return false; | 257 | return false; | |
260 | if (ps.prev_lsym == lsym_semicolon | 258 | if (ps.prev_lsym == lsym_semicolon | |
261 | || ps.prev_lsym == lsym_lbrace | 259 | || ps.prev_lsym == lsym_lbrace | |
262 | || ps.prev_lsym == lsym_rbrace) { | 260 | || ps.prev_lsym == lsym_rbrace) { | |
263 | if (inp_p[0] == '*' && inp_p[1] != '=') | 261 | if (inp_p[0] == '*' && inp_p[1] != '=') | |
264 | return true; | 262 | return true; | |
265 | /* XXX: is_identifier_start */ | 263 | /* XXX: is_identifier_start */ | |
266 | if (ch_isalpha(inp_p[0])) | 264 | if (ch_isalpha(inp_p[0])) | |
267 | return true; | 265 | return true; | |
268 | } | 266 | } | |
269 | return false; | 267 | return false; | |
270 | } | 268 | } | |
271 | 269 | |||
272 | static int | 270 | static int | |
273 | bsearch_typenames(const char *key) | 271 | bsearch_typenames(const char *key) | |
274 | { | 272 | { | |
275 | const char **arr = typenames.items; | 273 | const char **arr = typenames.items; | |
276 | unsigned lo = 0; | 274 | unsigned lo = 0; | |
277 | unsigned hi = typenames.len; | 275 | unsigned hi = typenames.len; | |
278 | 276 | |||
279 | while (lo < hi) { | 277 | while (lo < hi) { | |
280 | unsigned mid = (lo + hi) / 2; | 278 | unsigned mid = (lo + hi) / 2; | |
281 | int cmp = strcmp(arr[mid], key); | 279 | int cmp = strcmp(arr[mid], key); | |
282 | if (cmp < 0) | 280 | if (cmp < 0) | |
283 | lo = mid + 1; | 281 | lo = mid + 1; | |
284 | else if (cmp > 0) | 282 | else if (cmp > 0) | |
285 | hi = mid; | 283 | hi = mid; | |
286 | else | 284 | else | |
287 | return (int)mid; | 285 | return (int)mid; | |
288 | } | 286 | } | |
289 | return -1 - (int)lo; | 287 | return -1 - (int)lo; | |
290 | } | 288 | } | |
291 | 289 | |||
292 | static bool | 290 | static bool | |
293 | is_typename(void) | 291 | is_typename(void) | |
294 | { | 292 | { | |
295 | if (opt.auto_typedefs && | 293 | if (opt.auto_typedefs && | |
296 | token.len >= 2 && memcmp(token.s + token.len - 2, "_t", 2) == 0) | 294 | token.len >= 2 && memcmp(token.s + token.len - 2, "_t", 2) == 0) | |
297 | return true; | 295 | return true; | |
298 | 296 | |||
299 | return bsearch_typenames(token.s) >= 0; | 297 | return bsearch_typenames(token.s) >= 0; | |
300 | } | 298 | } | |
301 | 299 | |||
302 | void | 300 | void | |
303 | register_typename(const char *name) | 301 | register_typename(const char *name) | |
304 | { | 302 | { | |
305 | if (typenames.len >= typenames.cap) { | 303 | if (typenames.len >= typenames.cap) { | |
306 | typenames.cap = 16 + 2 * typenames.cap; | 304 | typenames.cap = 16 + 2 * typenames.cap; | |
307 | typenames.items = nonnull(realloc(typenames.items, | 305 | typenames.items = nonnull(realloc(typenames.items, | |
308 | sizeof(typenames.items[0]) * typenames.cap)); | 306 | sizeof(typenames.items[0]) * typenames.cap)); | |
309 | } | 307 | } | |
310 | 308 | |||
311 | int pos = bsearch_typenames(name); | 309 | int pos = bsearch_typenames(name); | |
312 | if (pos >= 0) | 310 | if (pos >= 0) | |
313 | return; /* already in the list */ | 311 | return; /* already in the list */ | |
314 | 312 | |||
315 | pos = -1 - pos; | 313 | pos = -1 - pos; | |
316 | memmove(typenames.items + pos + 1, typenames.items + pos, | 314 | memmove(typenames.items + pos + 1, typenames.items + pos, | |
317 | sizeof(typenames.items[0]) * (typenames.len++ - (unsigned)pos)); | 315 | sizeof(typenames.items[0]) * (typenames.len++ - (unsigned)pos)); | |
318 | typenames.items[pos] = nonnull(strdup(name)); | 316 | typenames.items[pos] = nonnull(strdup(name)); | |
319 | } | 317 | } | |
320 | 318 | |||
321 | static int | 319 | static int | |
322 | cmp_keyword_by_name(const void *key, const void *elem) | 320 | cmp_keyword_by_name(const void *key, const void *elem) | |
323 | { | 321 | { | |
324 | return strcmp(key, ((const struct keyword *)elem)->name); | 322 | return strcmp(key, ((const struct keyword *)elem)->name); | |
325 | } | 323 | } | |
326 | 324 | |||
327 | /* | 325 | /* | |
328 | * Looking at something like 'function_name(...)' in a line, guess whether | 326 | * Looking at the '(', guess whether this starts a function definition or a | |
329 | * this starts a function definition or a declaration. | 327 | * function declaration. | |
330 | */ | 328 | */ | |
331 | static bool | 329 | static bool | |
332 | probably_function_definition(void) | 330 | probably_function_definition(void) | |
333 | { | 331 | { | |
334 | int paren_level = 0; | 332 | int paren_level = 0; | |
335 | for (const char *p = inp_p; *p != '\n'; p++) { | 333 | for (const char *p = inp_p; *p != '\n'; p++) { | |
336 | if (*p == '(') | 334 | if (*p == '(') | |
337 | paren_level++; | 335 | paren_level++; | |
338 | if (*p == ')' && --paren_level == 0) { | 336 | if (*p == ')' && --paren_level == 0) { | |
339 | p++; | 337 | p++; | |
340 | 338 | |||
341 | while (*p != '\n' | 339 | while (*p != '\n' | |
342 | && (ch_isspace(*p) || is_identifier_part(*p))) | 340 | && (ch_isspace(*p) || is_identifier_part(*p))) | |
343 | p++; /* '__dead' or '__unused' */ | 341 | p++; /* '__dead' or '__unused' */ | |
344 | 342 | |||
345 | if (*p == '\n') /* func(...) */ | 343 | if (*p == '\n') /* func(...) */ | |
346 | break; | 344 | break; | |
347 | if (*p == ';') /* func(...); */ | 345 | if (*p == ';') /* func(...); */ | |
348 | return false; | 346 | return false; | |
349 | if (*p == ',') /* double abs(), pi; */ | 347 | if (*p == ',') /* double abs(), pi; */ | |
350 | return false; | 348 | return false; | |
351 | if (*p == '(') /* func(...) __attribute__((...)) */ | 349 | if (*p == '(') /* func(...) __attribute__((...)) */ | |
352 | paren_level++; /* func(...) __printflike(...) | 350 | paren_level++; /* func(...) __printflike(...) | |
353 | */ | 351 | */ | |
354 | else | 352 | else | |
355 | break; /* func(...) { ... */ | 353 | break; /* func(...) { ... */ | |
356 | } | 354 | } | |
357 | 355 | |||
358 | if (paren_level == 1 && p[0] == '*' && p[1] == ',') | 356 | if (paren_level == 1 && p[0] == '*' && p[1] == ',') | |
359 | return false; | 357 | return false; | |
360 | } | 358 | } | |
361 | 359 | |||
362 | /* To further reduce the cases where indent wrongly treats an | 360 | /* | |
361 | * To further reduce the cases where indent wrongly treats an | |||
363 | * incomplete function declaration as a function definition, thus | 362 | * incomplete function declaration as a function definition, thus | |
364 | * adding a newline before the function name, it may be worth looking | 363 | * adding a newline before the function name, it may be worth looking | |
365 | * for parameter names, as these are often omitted in function | 364 | * for parameter names, as these are often omitted in function | |
366 | * declarations and only included in function definitions. Or just | 365 | * declarations and only included in function definitions. Or just | |
367 | * increase the lookahead to more than just the current line of input, | 366 | * increase the lookahead to more than just the current line of input, | |
368 | * until the next '{'. */ | 367 | * until the next '{'. | |
368 | */ | |||
369 | return true; | 369 | return true; | |
370 | } | 370 | } | |
371 | 371 | |||
372 | static lexer_symbol | 372 | static lexer_symbol | |
373 | lexi_alnum(void) | 373 | lexi_alnum(void) | |
374 | { | 374 | { | |
375 | if (ch_isdigit(inp_p[0]) || | 375 | if (ch_isdigit(inp_p[0]) || | |
376 | (inp_p[0] == '.' && ch_isdigit(inp_p[1]))) { | 376 | (inp_p[0] == '.' && ch_isdigit(inp_p[1]))) { | |
377 | lex_number(); | 377 | lex_number(); | |
378 | } else if (is_identifier_start(inp_p[0])) { | 378 | } else if (is_identifier_start(inp_p[0])) { | |
379 | lex_word(); | 379 | lex_word(); | |
380 | 380 | |||
381 | if (token.len == 1 && token.s[0] == 'L' && | 381 | if (token.len == 1 && token.s[0] == 'L' && | |
382 | (inp_p[0] == '"' || inp_p[0] == '\'')) { | 382 | (inp_p[0] == '"' || inp_p[0] == '\'')) { | |
383 | token_add_char(*inp_p++); | 383 | token_add_char(*inp_p++); | |
384 | lex_char_or_string(); | 384 | lex_char_or_string(); | |
385 | ps.next_unary = false; | 385 | ps.next_unary = false; | |
386 | return lsym_word; | 386 | return lsym_word; | |
387 | } | 387 | } | |
388 | } else | 388 | } else | |
389 | return lsym_eof; /* just as a placeholder */ | 389 | return lsym_eof; /* just as a placeholder */ | |
390 | 390 | |||
391 | while (ch_isblank(inp_p[0])) | 391 | while (ch_isblank(*inp_p)) | |
392 | inp_p++; | 392 | inp_p++; | |
393 | 393 | |||
394 | ps.next_unary = ps.prev_lsym == lsym_tag | 394 | ps.next_unary = ps.prev_lsym == lsym_tag | |
395 | || ps.prev_lsym == lsym_typedef; | 395 | || ps.prev_lsym == lsym_typedef; | |
396 | 396 | |||
397 | if (ps.prev_lsym == lsym_tag && ps.paren.len == 0) | 397 | if (ps.prev_lsym == lsym_tag && ps.paren.len == 0) | |
398 | return lsym_type; | 398 | return lsym_type; | |
399 | 399 | |||
400 | token_add_char('\0'); | 400 | token_add_char('\0'); // Terminate in non-debug mode as well. | |
401 | token.len--; | 401 | token.len--; | |
402 | const struct keyword *kw = bsearch(token.s, keywords, | 402 | const struct keyword *kw = bsearch(token.s, keywords, | |
403 | array_length(keywords), sizeof(keywords[0]), cmp_keyword_by_name); | 403 | array_length(keywords), sizeof(keywords[0]), cmp_keyword_by_name); | |
404 | lexer_symbol lsym = lsym_word; | 404 | lexer_symbol lsym = lsym_word; | |
405 | if (kw != NULL) { | 405 | if (kw != NULL) { | |
406 | if (kw->lsym == lsym_type) | 406 | if (kw->lsym == lsym_type) | |
407 | lsym = lsym_type; | 407 | lsym = lsym_type; | |
408 | ps.next_unary = true; | 408 | ps.next_unary = true; | |
409 | if (kw->lsym == lsym_tag || kw->lsym == lsym_type) | 409 | if (kw->lsym == lsym_tag || kw->lsym == lsym_type) | |
410 | goto found_typename; | 410 | goto found_typename; | |
411 | return kw->lsym; | 411 | return kw->lsym; | |
412 | } | 412 | } | |
413 | 413 | |||
414 | if (is_typename()) { | 414 | if (is_typename()) { | |
415 | lsym = lsym_type; | 415 | lsym = lsym_type; | |
416 | ps.next_unary = true; | 416 | ps.next_unary = true; | |
417 | found_typename: | 417 | found_typename: | |
418 | if (ps.paren.len > 0) { | 418 | if (ps.paren.len > 0) { | |
419 | /* inside parentheses: cast, param list, offsetof or | 419 | /* inside parentheses: cast, param list, offsetof or | |
420 | * sizeof */ | 420 | * sizeof */ | |
421 | struct paren_level *paren_level = | 421 | struct paren_level *paren_level = | |
422 | ps.paren.item + ps.paren.len - 1; | 422 | ps.paren.item + ps.paren.len - 1; | |
423 | if (paren_level->cast == cast_unknown) | 423 | if (paren_level->cast == cast_unknown) | |
424 | paren_level->cast = cast_maybe; | 424 | paren_level->cast = cast_maybe; | |
425 | } | 425 | } | |
426 | if (ps.prev_lsym != lsym_period | 426 | if (ps.prev_lsym != lsym_period | |
427 | && ps.prev_lsym != lsym_unary_op) { | 427 | && ps.prev_lsym != lsym_unary_op) { | |
428 | if (kw != NULL && kw->lsym == lsym_tag) | 428 | if (kw != NULL && kw->lsym == lsym_tag) | |
429 | return lsym_tag; | 429 | return lsym_tag; | |
430 | if (ps.paren.len == 0) | 430 | if (ps.paren.len == 0) | |
431 | return lsym_type; | 431 | return lsym_type; | |
432 | } | 432 | } | |
433 | } | 433 | } | |
434 | 434 | |||
435 | if (inp_p[0] == '(' && ps.psyms.len <= 2 && ps.ind_level == 0 && | 435 | if (*inp_p == '(' && ps.psyms.len < 3 && ps.ind_level == 0 && | |
436 | !ps.in_func_def_params && !ps.in_init) { | 436 | !ps.in_func_def_params && !ps.in_init) { | |
437 | 437 | |||
438 | if (ps.paren.len == 0 && probably_function_definition()) { | 438 | if (ps.paren.len == 0 && probably_function_definition()) { | |
439 | ps.line_has_func_def = true; | 439 | ps.line_has_func_def = true; | |
440 | if (ps.in_decl) | 440 | if (ps.in_decl) | |
441 | ps.in_func_def_params = true; | 441 | ps.in_func_def_params = true; | |
442 | return lsym_funcname; | 442 | return lsym_funcname; | |
443 | } | 443 | } | |
444 | 444 | |||
445 | } else if (ps.paren.len == 0 && probably_typename()) { | 445 | } else if (ps.paren.len == 0 && probably_typename()) { | |
446 | ps.next_unary = true; | 446 | ps.next_unary = true; | |
447 | return lsym_type; | 447 | return lsym_type; | |
448 | } | 448 | } | |
449 | 449 | |||
450 | return lsym; | 450 | return lsym; | |
451 | } | 451 | } | |
452 | 452 | |||
453 | static bool | 453 | static bool | |
454 | is_asterisk_pointer(void) | 454 | is_asterisk_pointer(void) | |
455 | { | 455 | { | |
456 | if (inp_p[strspn(inp_p, "* \t")] == ')') | 456 | if (inp_p[strspn(inp_p, "* \t")] == ')') | |
457 | return true; | 457 | return true; | |
458 | if (ps.next_unary || ps.in_func_def_params) | 458 | if (ps.next_unary || ps.in_func_def_params) | |
459 | return true; | 459 | return true; | |
460 | if (ps.prev_lsym == lsym_word || | 460 | if (ps.prev_lsym == lsym_word || | |
461 | ps.prev_lsym == lsym_rparen || | 461 | ps.prev_lsym == lsym_rparen || | |
462 | ps.prev_lsym == lsym_rbracket) | 462 | ps.prev_lsym == lsym_rbracket) | |
463 | return false; | 463 | return false; | |
464 | return ps.in_decl && ps.paren.len > 0; | 464 | return ps.in_decl && ps.paren.len > 0; | |
465 | } | 465 | } | |
466 | 466 | |||
467 | static bool | 467 | static bool | |
468 | probably_in_function_definition(void) | 468 | probably_in_function_definition(void) | |
469 | { | 469 | { | |
470 | for (const char *tp = inp_p; *tp != '\n';) { | 470 | for (const char *p = inp_p; *p != '\n';) { | |
471 | if (ch_isspace(*tp)) | 471 | if (ch_isspace(*p)) | |
472 | tp++; | 472 | p++; | |
473 | else if (is_identifier_start(*tp)) { | 473 | else if (is_identifier_start(*p)) { | |
474 | tp++; | 474 | p++; | |
475 | while (is_identifier_part(*tp)) | 475 | while (is_identifier_part(*p)) | |
476 | tp++; | 476 | p++; | |
477 | } else | 477 | } else | |
478 | return *tp == '('; | 478 | return *p == '('; | |
479 | } | 479 | } | |
480 | return false; | 480 | return false; | |
481 | } | 481 | } | |
482 | 482 | |||
483 | static void | 483 | static void | |
484 | lex_asterisk_pointer(void) | 484 | lex_asterisk_pointer(void) | |
485 | { | 485 | { | |
486 | while (inp_p[0] == '*' || ch_isspace(inp_p[0])) { | 486 | while (*inp_p == '*' || ch_isspace(*inp_p)) { | |
487 | if (inp_p[0] == '*') | 487 | if (*inp_p == '*') | |
488 | token_add_char('*'); | 488 | token_add_char('*'); | |
489 | inp_skip(); | 489 | inp_skip(); | |
490 | } | 490 | } | |
491 | 491 | |||
492 | if (ps.in_decl && probably_in_function_definition()) | 492 | if (ps.in_decl && probably_in_function_definition()) | |
493 | ps.line_has_func_def = true; | 493 | ps.line_has_func_def = true; | |
494 | } | 494 | } | |
495 | 495 | |||
496 | static bool | 496 | static bool | |
497 | skip(const char **pp, const char *s) | 497 | skip(const char **pp, const char *s) | |
498 | { | 498 | { | |
499 | size_t len = strlen(s); | 499 | size_t len = strlen(s); | |
500 | while (ch_isblank(**pp)) | 500 | while (ch_isblank(**pp)) | |
501 | (*pp)++; | 501 | (*pp)++; | |
502 | if (strncmp(*pp, s, len) == 0) { | 502 | if (strncmp(*pp, s, len) == 0) { | |
503 | *pp += len; | 503 | *pp += len; | |
504 | return true; | 504 | return true; | |
505 | } | 505 | } | |
506 | return false; | 506 | return false; | |
507 | } | 507 | } | |
508 | 508 | |||
509 | static void | 509 | static void | |
510 | lex_indent_comment(void) | 510 | lex_indent_comment(void) | |
511 | { | 511 | { | |
512 | const char *p = inp.s; | 512 | const char *p = inp.s; | |
513 | if (skip(&p, "/*") && skip(&p, "INDENT")) { | 513 | if (skip(&p, "/*") && skip(&p, "INDENT")) { | |
514 | enum indent_enabled enabled; | 514 | enum indent_enabled enabled; | |
515 | if (skip(&p, "ON") || *p == '*') | 515 | if (skip(&p, "ON") || *p == '*') | |
516 | enabled = indent_last_off_line; | 516 | enabled = indent_last_off_line; | |
517 | else if (skip(&p, "OFF")) | 517 | else if (skip(&p, "OFF")) | |
518 | enabled = indent_off; | 518 | enabled = indent_off; | |
519 | else | 519 | else | |
520 | return; | 520 | return; | |
521 | if (skip(&p, "*/\n")) { | 521 | if (skip(&p, "*/\n")) { | |
522 | if (lab.len > 0 || code.len > 0 || com.len > 0) | 522 | if (lab.len > 0 || code.len > 0 || com.len > 0) | |
523 | output_line(); | 523 | output_line(); | |
524 | indent_enabled = enabled; | 524 | indent_enabled = enabled; | |
525 | } | 525 | } | |
526 | } | 526 | } | |
527 | } | 527 | } | |
528 | 528 | |||
529 | /* Reads the next token, placing it in the global variable "token". */ | 529 | /* Reads the next token, placing it in the global variable "token". */ | |
530 | lexer_symbol | 530 | lexer_symbol | |
531 | lexi(void) | 531 | lexi(void) | |
532 | { | 532 | { | |
533 | buf_clear(&token); | 533 | buf_clear(&token); | |
534 | 534 | |||
535 | for (;;) { | 535 | for (;;) { | |
536 | if (ch_isblank(inp_p[0])) | 536 | if (ch_isblank(inp_p[0])) | |
537 | inp_p++; | 537 | inp_p++; | |
538 | else if (inp_p[0] == '\\' && inp_p[1] == '\n') { | 538 | else if (inp_p[0] == '\\' && inp_p[1] == '\n') { | |
539 | inp_p++; | 539 | inp_p++; | |
540 | inp_skip(); | 540 | inp_skip(); | |
541 | line_no++; | 541 | line_no++; | |
542 | } else | 542 | } else | |
543 | break; | 543 | break; | |
544 | } | 544 | } | |
545 | 545 | |||
546 | lexer_symbol alnum_lsym = lexi_alnum(); | 546 | lexer_symbol alnum_lsym = lexi_alnum(); | |
547 | if (alnum_lsym != lsym_eof) | 547 | if (alnum_lsym != lsym_eof) | |
548 | return alnum_lsym; | 548 | return alnum_lsym; | |
549 | 549 | |||
550 | /* Scan a non-alphanumeric token */ | 550 | /* Scan a non-alphanumeric token */ | |
551 | 551 | |||
552 | token_add_char(inp_next()); | 552 | token_add_char(inp_next()); | |
553 | 553 | |||
554 | lexer_symbol lsym; | 554 | lexer_symbol lsym; | |
555 | bool next_unary; | 555 | bool next_unary; | |
556 | 556 | |||
557 | switch (token.s[token.len - 1]) { | 557 | switch (token.s[token.len - 1]) { | |
558 | 558 | |||
559 | case '#': | 559 | case '#': | |
560 | lsym = lsym_preprocessing; | 560 | lsym = lsym_preprocessing; | |
561 | next_unary = ps.next_unary; | 561 | next_unary = ps.next_unary; | |
562 | break; | 562 | break; | |
563 | 563 | |||
564 | case '\n': | 564 | case '\n': | |
565 | /* if data has been exhausted, the '\n' is a dummy. */ | 565 | /* if data has been exhausted, the '\n' is a dummy. */ | |
566 | lsym = had_eof ? lsym_eof : lsym_newline; | 566 | lsym = had_eof ? lsym_eof : lsym_newline; | |
567 | next_unary = ps.next_unary; | 567 | next_unary = ps.next_unary; | |
568 | break; | 568 | break; | |
569 | 569 | |||
570 | /* INDENT OFF */ | 570 | /* INDENT OFF */ | |
571 | case '(': lsym = lsym_lparen; next_unary = true; break; | 571 | case '(': lsym = lsym_lparen; next_unary = true; break; | |
572 | case ')': lsym = lsym_rparen; next_unary = false; break; | 572 | case ')': lsym = lsym_rparen; next_unary = false; break; | |
573 | case '[': lsym = lsym_lbracket; next_unary = true; break; | 573 | case '[': lsym = lsym_lbracket; next_unary = true; break; | |
574 | case ']': lsym = lsym_rbracket; next_unary = false; break; | 574 | case ']': lsym = lsym_rbracket; next_unary = false; break; | |
575 | case '{': lsym = lsym_lbrace; next_unary = true; break; | 575 | case '{': lsym = lsym_lbrace; next_unary = true; break; | |
576 | case '}': lsym = lsym_rbrace; next_unary = true; break; | 576 | case '}': lsym = lsym_rbrace; next_unary = true; break; | |
577 | case '.': lsym = lsym_period; next_unary = false; break; | 577 | case '.': lsym = lsym_period; next_unary = false; break; | |
578 | case '?': lsym = lsym_question; next_unary = true; break; | 578 | case '?': lsym = lsym_question; next_unary = true; break; | |
579 | case ',': lsym = lsym_comma; next_unary = true; break; | 579 | case ',': lsym = lsym_comma; next_unary = true; break; | |
580 | case ';': lsym = lsym_semicolon; next_unary = true; break; | 580 | case ';': lsym = lsym_semicolon; next_unary = true; break; | |
581 | /* INDENT ON */ | 581 | /* INDENT ON */ | |
582 | 582 | |||
583 | case '-': | |||
584 | case '+': | 583 | case '+': | |
584 | case '-': | |||
585 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | 585 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | |
586 | next_unary = true; | 586 | next_unary = true; | |
587 | 587 | |||
588 | /* '++' or '--' */ | 588 | /* '++' or '--' */ | |
589 | if (inp_p[0] == token.s[token.len - 1]) { | 589 | if (*inp_p == token.s[token.len - 1]) { | |
590 | token_add_char(*inp_p++); | 590 | token_add_char(*inp_p++); | |
591 | if (ps.prev_lsym == lsym_word || | 591 | if (ps.prev_lsym == lsym_word || | |
592 | ps.prev_lsym == lsym_rparen || | 592 | ps.prev_lsym == lsym_rparen || | |
593 | ps.prev_lsym == lsym_rbracket) { | 593 | ps.prev_lsym == lsym_rbracket) { | |
594 | lsym = ps.next_unary | 594 | lsym = ps.next_unary | |
595 | ? lsym_unary_op : lsym_postfix_op; | 595 | ? lsym_unary_op : lsym_postfix_op; | |
596 | next_unary = false; | 596 | next_unary = false; | |
597 | } | 597 | } | |
598 | 598 | |||
599 | } else if (inp_p[0] == '=') { /* '+=' or '-=' */ | 599 | } else if (*inp_p == '=') { /* '+=' or '-=' */ | |
600 | token_add_char(*inp_p++); | 600 | token_add_char(*inp_p++); | |
601 | 601 | |||
602 | } else if (inp_p[0] == '>') { /* '->' */ | 602 | } else if (*inp_p == '>') { /* '->' */ | |
603 | token_add_char(*inp_p++); | 603 | token_add_char(*inp_p++); | |
604 | lsym = lsym_unary_op; | 604 | lsym = lsym_unary_op; | |
605 | next_unary = false; | 605 | next_unary = false; | |
606 | ps.want_blank = false; | 606 | ps.want_blank = false; | |
607 | } | 607 | } | |
608 | break; | 608 | break; | |
609 | 609 | |||
610 | case ':': | 610 | case ':': | |
611 | lsym = ps.quest_level > 0 | 611 | lsym = ps.quest_level > 0 | |
612 | ? (ps.quest_level--, lsym_question_colon) | 612 | ? (ps.quest_level--, lsym_question_colon) | |
613 | : ps.in_var_decl ? lsym_other_colon : lsym_label_colon; | 613 | : ps.in_var_decl ? lsym_other_colon : lsym_label_colon; | |
614 | next_unary = true; | 614 | next_unary = true; | |
615 | break; | 615 | break; | |
616 | 616 | |||
617 | case '*': | 617 | case '*': | |
618 | if (inp_p[0] == '=') { | 618 | if (*inp_p == '=') { | |
619 | token_add_char(*inp_p++); | 619 | token_add_char(*inp_p++); | |
620 | lsym = lsym_binary_op; | 620 | lsym = lsym_binary_op; | |
621 | } else if (is_asterisk_pointer()) { | 621 | } else if (is_asterisk_pointer()) { | |
622 | lex_asterisk_pointer(); | 622 | lex_asterisk_pointer(); | |
623 | lsym = lsym_unary_op; | 623 | lsym = lsym_unary_op; | |
624 | } else | 624 | } else | |
625 | lsym = lsym_binary_op; | 625 | lsym = lsym_binary_op; | |
626 | next_unary = true; | 626 | next_unary = true; | |
627 | break; | 627 | break; | |
628 | 628 | |||
629 | case '=': | 629 | case '=': | |
630 | if (ps.in_var_decl) | 630 | if (ps.in_var_decl) | |
631 | ps.in_init = true; | 631 | ps.in_init = true; | |
632 | if (inp_p[0] == '=') | 632 | if (*inp_p == '=') | |
633 | token_add_char(*inp_p++); | 633 | token_add_char(*inp_p++); | |
634 | lsym = lsym_binary_op; | 634 | lsym = lsym_binary_op; | |
635 | next_unary = true; | 635 | next_unary = true; | |
636 | break; | 636 | break; | |
637 | 637 | |||
638 | case '>': | 638 | case '>': | |
639 | case '<': | 639 | case '<': | |
640 | case '!': /* ops like <, <<, <=, !=, etc. */ | 640 | case '!': /* ops like <, <<, <=, !=, etc. */ | |
641 | if (inp_p[0] == '>' || inp_p[0] == '<' || inp_p[0] == '=') | 641 | if (*inp_p == '>' || *inp_p == '<' || *inp_p == '=') | |
642 | token_add_char(*inp_p++); | 642 | token_add_char(*inp_p++); | |
643 | if (inp_p[0] == '=') | 643 | if (*inp_p == '=') | |
644 | token_add_char(*inp_p++); | 644 | token_add_char(*inp_p++); | |
645 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | 645 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | |
646 | next_unary = true; | 646 | next_unary = true; | |
647 | break; | 647 | break; | |
648 | 648 | |||
649 | case '\'': | 649 | case '\'': | |
650 | case '"': | 650 | case '"': | |
651 | lex_char_or_string(); | 651 | lex_char_or_string(); | |
652 | lsym = lsym_word; | 652 | lsym = lsym_word; | |
653 | next_unary = false; | 653 | next_unary = false; | |
654 | break; | 654 | break; | |
655 | 655 | |||
656 | default: | 656 | default: | |
657 | if (token.s[token.len - 1] == '/' | 657 | if (token.s[token.len - 1] == '/' | |
658 | && (inp_p[0] == '*' || inp_p[0] == '/')) { | 658 | && (*inp_p == '*' || *inp_p == '/')) { | |
659 | enum indent_enabled prev = indent_enabled; | 659 | enum indent_enabled prev = indent_enabled; | |
660 | lex_indent_comment(); | 660 | lex_indent_comment(); | |
661 | if (prev == indent_on && indent_enabled == indent_off) | 661 | if (prev == indent_on && indent_enabled == indent_off) | |
662 | buf_clear(&out.indent_off_text); | 662 | buf_clear(&out.indent_off_text); | |
663 | token_add_char(*inp_p++); | 663 | token_add_char(*inp_p++); | |
664 | lsym = lsym_comment; | 664 | lsym = lsym_comment; | |
665 | next_unary = ps.next_unary; | 665 | next_unary = ps.next_unary; | |
666 | break; | 666 | break; | |
667 | } | 667 | } | |
668 | 668 | |||
669 | /* punctuation like '%', '&&', '/', '^', '||', '~' */ | 669 | /* punctuation like '%', '&&', '/', '^', '||', '~' */ | |
670 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | 670 | lsym = ps.next_unary ? lsym_unary_op : lsym_binary_op; | |
671 | if (inp_p[0] == token.s[token.len - 1]) | 671 | if (*inp_p == token.s[token.len - 1]) | |
672 | token_add_char(*inp_p++), lsym = lsym_binary_op; | 672 | token_add_char(*inp_p++), lsym = lsym_binary_op; | |
673 | if (inp_p[0] == '=') | 673 | if (*inp_p == '=') | |
674 | token_add_char(*inp_p++), lsym = lsym_binary_op; | 674 | token_add_char(*inp_p++), lsym = lsym_binary_op; | |
675 | 675 | |||
676 | next_unary = true; | 676 | next_unary = true; | |
677 | } | 677 | } | |
678 | 678 | |||
679 | ps.next_unary = next_unary; | 679 | ps.next_unary = next_unary; | |
680 | 680 | |||
681 | return lsym; | 681 | return lsym; | |
682 | } | 682 | } |
--- src/usr.bin/indent/parse.c 2023/06/14 20:46:08 1.77
+++ src/usr.bin/indent/parse.c 2023/06/17 22:28:49 1.78
@@ -1,263 +1,263 @@ | @@ -1,263 +1,263 @@ | |||
1 | /* $NetBSD: parse.c,v 1.77 2023/06/14 20:46:08 rillig Exp $ */ | 1 | /* $NetBSD: parse.c,v 1.78 2023/06/17 22:28:49 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: parse.c,v 1.77 2023/06/14 20:46:08 rillig Exp $"); | 41 | __RCSID("$NetBSD: parse.c,v 1.78 2023/06/17 22:28:49 rillig Exp $"); | |
42 | 42 | |||
43 | #include <stdlib.h> | 43 | #include <stdlib.h> | |
44 | 44 | |||
45 | #include "indent.h" | 45 | #include "indent.h" | |
46 | 46 | |||
47 | /* | 47 | /* | |
48 | * Try to combine the statement on the top of the parse stack with the symbol | 48 | * Try to combine the statement on the top of the parse stack with the symbol | |
49 | * directly below it, replacing these two symbols with a single symbol. | 49 | * directly below it, replacing these two symbols with a single symbol. | |
50 | */ | 50 | */ | |
51 | static bool | 51 | static bool | |
52 | psyms_reduce_stmt(void) | 52 | psyms_reduce_stmt(void) | |
53 | { | 53 | { | |
54 | struct psym_stack *psyms = &ps.psyms; | 54 | struct psym_stack *psyms = &ps.psyms; | |
55 | switch (psyms->sym[psyms->len - 2]) { | 55 | switch (psyms->sym[psyms->len - 2]) { | |
56 | 56 | |||
57 | case psym_stmt: | 57 | case psym_stmt: | |
58 | psyms->sym[psyms->len-- - 2] = psym_stmt; | 58 | psyms->sym[psyms->len-- - 2] = psym_stmt; | |
59 | return true; | 59 | return true; | |
60 | 60 | |||
61 | case psym_do: | 61 | case psym_do: | |
62 | psyms->sym[psyms->len-- - 2] = psym_do_stmt; | 62 | psyms->sym[psyms->len-- - 2] = psym_do_stmt; | |
63 | ps.ind_level_follow = psyms->ind_level[psyms->len - 1]; | 63 | ps.ind_level_follow = psyms->ind_level[psyms->len - 1]; | |
64 | return true; | 64 | return true; | |
65 | 65 | |||
66 | case psym_if_expr: | 66 | case psym_if_expr: | |
67 | psyms->sym[psyms->len-- - 2] = psym_if_expr_stmt; | 67 | psyms->sym[psyms->len-- - 2] = psym_if_expr_stmt; | |
68 | size_t i = psyms->len - 2; | 68 | size_t i = psyms->len - 2; | |
69 | while (psyms->sym[i] != psym_stmt && | 69 | while (psyms->sym[i] != psym_stmt && | |
70 | psyms->sym[i] != psym_lbrace_block) | 70 | psyms->sym[i] != psym_lbrace_block) | |
71 | --i; | 71 | i--; | |
72 | ps.ind_level_follow = psyms->ind_level[i]; | 72 | ps.ind_level_follow = psyms->ind_level[i]; | |
73 | /* For the time being, assume that there is no 'else' on this | 73 | /* For the time being, assume that there is no 'else' on this | |
74 | * 'if', and set the indentation level accordingly. If an | 74 | * 'if', and set the indentation level accordingly. If an | |
75 | * 'else' is scanned, it will be fixed up later. */ | 75 | * 'else' is scanned, it will be fixed up later. */ | |
76 | return true; | 76 | return true; | |
77 | 77 | |||
78 | case psym_switch_expr: | 78 | case psym_switch_expr: | |
79 | case psym_decl: | 79 | case psym_decl: | |
80 | case psym_if_expr_stmt_else: | 80 | case psym_if_expr_stmt_else: | |
81 | case psym_for_exprs: | 81 | case psym_for_exprs: | |
82 | case psym_while_expr: | 82 | case psym_while_expr: | |
83 | psyms->sym[psyms->len-- - 2] = psym_stmt; | 83 | psyms->sym[psyms->len-- - 2] = psym_stmt; | |
84 | ps.ind_level_follow = psyms->ind_level[psyms->len - 1]; | 84 | ps.ind_level_follow = psyms->ind_level[psyms->len - 1]; | |
85 | return true; | 85 | return true; | |
86 | 86 | |||
87 | default: | 87 | default: | |
88 | return false; | 88 | return false; | |
89 | } | 89 | } | |
90 | } | 90 | } | |
91 | 91 | |||
92 | static int | 92 | static int | |
93 | decl_level(void) | 93 | decl_level(void) | |
94 | { | 94 | { | |
95 | int level = 0; | 95 | int level = 0; | |
96 | for (size_t i = ps.psyms.len - 2; i > 0; i--) | 96 | for (size_t i = ps.psyms.len - 2; i > 0; i--) | |
97 | if (ps.psyms.sym[i] == psym_decl) | 97 | if (ps.psyms.sym[i] == psym_decl) | |
98 | level++; | 98 | level++; | |
99 | return level; | 99 | return level; | |
100 | } | 100 | } | |
101 | 101 | |||
102 | void | 102 | void | |
103 | ps_push(parser_symbol psym, bool follow) | 103 | ps_push(parser_symbol psym, bool follow) | |
104 | { | 104 | { | |
105 | if (ps.psyms.len == ps.psyms.cap) { | 105 | if (ps.psyms.len == ps.psyms.cap) { | |
106 | ps.psyms.cap += 16; | 106 | ps.psyms.cap += 16; | |
107 | ps.psyms.sym = nonnull(realloc(ps.psyms.sym, | 107 | ps.psyms.sym = nonnull(realloc(ps.psyms.sym, | |
108 | sizeof(ps.psyms.sym[0]) * ps.psyms.cap)); | 108 | sizeof(ps.psyms.sym[0]) * ps.psyms.cap)); | |
109 | ps.psyms.ind_level = nonnull(realloc(ps.psyms.ind_level, | 109 | ps.psyms.ind_level = nonnull(realloc(ps.psyms.ind_level, | |
110 | sizeof(ps.psyms.ind_level[0]) * ps.psyms.cap)); | 110 | sizeof(ps.psyms.ind_level[0]) * ps.psyms.cap)); | |
111 | } | 111 | } | |
112 | ps.psyms.len++; | 112 | ps.psyms.len++; | |
113 | ps.psyms.sym[ps.psyms.len - 1] = psym; | 113 | ps.psyms.sym[ps.psyms.len - 1] = psym; | |
114 | ps.psyms.ind_level[ps.psyms.len - 1] = | 114 | ps.psyms.ind_level[ps.psyms.len - 1] = | |
115 | follow ? ps.ind_level_follow : ps.ind_level; | 115 | follow ? ps.ind_level_follow : ps.ind_level; | |
116 | } | 116 | } | |
117 | 117 | |||
118 | /* | 118 | /* | |
119 | * Repeatedly try to reduce the top two symbols on the parse stack to a single | 119 | * Repeatedly try to reduce the top two symbols on the parse stack to a single | |
120 | * symbol, until no more reductions are possible. | 120 | * symbol, until no more reductions are possible. | |
121 | */ | 121 | */ | |
122 | static void | 122 | static void | |
123 | psyms_reduce(void) | 123 | psyms_reduce(void) | |
124 | { | 124 | { | |
125 | struct psym_stack *psyms = &ps.psyms; | 125 | struct psym_stack *psyms = &ps.psyms; | |
126 | again: | 126 | again: | |
127 | if (psyms->len >= 2 && psyms->sym[psyms->len - 1] == psym_stmt | 127 | if (psyms->len >= 2 && psyms->sym[psyms->len - 1] == psym_stmt | |
128 | && psyms_reduce_stmt()) | 128 | && psyms_reduce_stmt()) | |
129 | goto again; | 129 | goto again; | |
130 | if (psyms->sym[psyms->len - 1] == psym_while_expr && | 130 | if (psyms->sym[psyms->len - 1] == psym_while_expr && | |
131 | psyms->sym[psyms->len - 2] == psym_do_stmt) { | 131 | psyms->sym[psyms->len - 2] == psym_do_stmt) { | |
132 | psyms->len -= 2; | 132 | psyms->len -= 2; | |
133 | goto again; | 133 | goto again; | |
134 | } | 134 | } | |
135 | } | 135 | } | |
136 | 136 | |||
137 | static bool | 137 | static bool | |
138 | is_lbrace(parser_symbol psym) | 138 | is_lbrace(parser_symbol psym) | |
139 | { | 139 | { | |
140 | return psym == psym_lbrace_block | 140 | return psym == psym_lbrace_block | |
141 | || psym == psym_lbrace_struct | 141 | || psym == psym_lbrace_struct | |
142 | || psym == psym_lbrace_union | 142 | || psym == psym_lbrace_union | |
143 | || psym == psym_lbrace_enum; | 143 | || psym == psym_lbrace_enum; | |
144 | } | 144 | } | |
145 | 145 | |||
146 | /* | 146 | /* | |
147 | * Shift the token onto the parser stack, then try to reduce it by combining it with | 147 | * Shift the token onto the parser stack, then try to reduce it by combining it with | |
148 | * previous tokens. | 148 | * previous tokens. | |
149 | */ | 149 | */ | |
150 | void | 150 | void | |
151 | parse(parser_symbol psym) | 151 | parse(parser_symbol psym) | |
152 | { | 152 | { | |
153 | debug_blank_line(); | 153 | debug_blank_line(); | |
154 | debug_println("parse token: %s", psym_name[psym]); | 154 | debug_println("parse token: %s", psym_name[psym]); | |
155 | 155 | |||
156 | struct psym_stack *psyms = &ps.psyms; | 156 | struct psym_stack *psyms = &ps.psyms; | |
157 | if (psym != psym_else) { | 157 | if (psym != psym_else) { | |
158 | while (psyms->sym[psyms->len - 1] == psym_if_expr_stmt) { | 158 | while (psyms->sym[psyms->len - 1] == psym_if_expr_stmt) { | |
159 | psyms->sym[psyms->len - 1] = psym_stmt; | 159 | psyms->sym[psyms->len - 1] = psym_stmt; | |
160 | psyms_reduce(); | 160 | psyms_reduce(); | |
161 | } | 161 | } | |
162 | } | 162 | } | |
163 | 163 | |||
164 | switch (psym) { | 164 | switch (psym) { | |
165 | 165 | |||
166 | case psym_lbrace_block: | 166 | case psym_lbrace_block: | |
167 | case psym_lbrace_struct: | 167 | case psym_lbrace_struct: | |
168 | case psym_lbrace_union: | 168 | case psym_lbrace_union: | |
169 | case psym_lbrace_enum: | 169 | case psym_lbrace_enum: | |
170 | ps.break_after_comma = false; | 170 | ps.break_after_comma = false; | |
171 | if (psyms->sym[psyms->len - 1] == psym_decl | 171 | if (psyms->sym[psyms->len - 1] == psym_decl | |
172 | || psyms->sym[psyms->len - 1] == psym_stmt) | 172 | || psyms->sym[psyms->len - 1] == psym_stmt) | |
173 | ++ps.ind_level_follow; | 173 | ps.ind_level_follow++; | |
174 | else if (code.len == 0) { | 174 | else if (code.len == 0) { | |
175 | /* It is part of a while, for, etc. */ | 175 | /* It is part of a while, for, etc. */ | |
176 | --ps.ind_level; | 176 | ps.ind_level--; | |
177 | 177 | |||
178 | /* for a switch, brace should be two levels out from | 178 | /* for a switch, brace should be two levels out from | |
179 | * the code */ | 179 | * the code */ | |
180 | if (psyms->sym[psyms->len - 1] == psym_switch_expr | 180 | if (psyms->sym[psyms->len - 1] == psym_switch_expr | |
181 | && opt.case_indent >= 1.0F) | 181 | && opt.case_indent >= 1.0F) | |
182 | --ps.ind_level; | 182 | ps.ind_level--; | |
183 | } | 183 | } | |
184 | 184 | |||
185 | ps_push(psym, false); | 185 | ps_push(psym, false); | |
186 | ps_push(psym_stmt, true); | 186 | ps_push(psym_stmt, true); | |
187 | break; | 187 | break; | |
188 | 188 | |||
189 | case psym_rbrace: | 189 | case psym_rbrace: | |
190 | /* stack should have <lbrace> <stmt> or <lbrace> <decl> */ | 190 | /* stack should have <lbrace> <stmt> or <lbrace> <decl> */ | |
191 | if (!(psyms->len >= 2 | 191 | if (!(psyms->len >= 2 | |
192 | && is_lbrace(psyms->sym[psyms->len - 2]))) { | 192 | && is_lbrace(psyms->sym[psyms->len - 2]))) { | |
193 | diag(1, "Statement nesting error"); | 193 | diag(1, "Statement nesting error"); | |
194 | break; | 194 | break; | |
195 | } | 195 | } | |
196 | ps.ind_level = ps.ind_level_follow = | 196 | ps.ind_level = ps.ind_level_follow = | |
197 | psyms->ind_level[psyms->len-- - 2]; | 197 | psyms->ind_level[psyms->len-- - 2]; | |
198 | psyms->sym[psyms->len - 1] = psym_stmt; | 198 | psyms->sym[psyms->len - 1] = psym_stmt; | |
199 | break; | 199 | break; | |
200 | 200 | |||
201 | case psym_decl: | 201 | case psym_decl: | |
202 | if (psyms->sym[psyms->len - 1] == psym_decl) | 202 | if (psyms->sym[psyms->len - 1] == psym_decl) | |
203 | break; /* only put one declaration onto stack */ | 203 | break; /* only put one declaration onto stack */ | |
204 | 204 | |||
205 | ps.break_after_comma = true; | 205 | ps.break_after_comma = true; | |
206 | ps_push(psym_decl, true); | 206 | ps_push(psym_decl, true); | |
207 | 207 | |||
208 | if (opt.left_justify_decl) | 208 | if (opt.left_justify_decl) | |
209 | ps.ind_level_follow = ps.ind_level = decl_level(); | 209 | ps.ind_level_follow = ps.ind_level = decl_level(); | |
210 | break; | 210 | break; | |
211 | 211 | |||
212 | case psym_stmt: | 212 | case psym_stmt: | |
213 | ps.break_after_comma = false; | 213 | ps.break_after_comma = false; | |
214 | ps_push(psym_stmt, false); | 214 | ps_push(psym_stmt, false); | |
215 | break; | 215 | break; | |
216 | 216 | |||
217 | case psym_if_expr: | 217 | case psym_if_expr: | |
218 | if (psyms->sym[psyms->len - 1] == psym_if_expr_stmt_else | 218 | if (psyms->sym[psyms->len - 1] == psym_if_expr_stmt_else | |
219 | && opt.else_if_in_same_line) | 219 | && opt.else_if_in_same_line) | |
220 | ps.ind_level_follow = | 220 | ps.ind_level_follow = | |
221 | psyms->ind_level[psyms->len-- - 1]; | 221 | psyms->ind_level[psyms->len-- - 1]; | |
222 | /* FALLTHROUGH */ | 222 | /* FALLTHROUGH */ | |
223 | case psym_do: | 223 | case psym_do: | |
224 | case psym_for_exprs: | 224 | case psym_for_exprs: | |
225 | ps.ind_level = ps.ind_level_follow++; | 225 | ps.ind_level = ps.ind_level_follow++; | |
226 | ps_push(psym, false); | 226 | ps_push(psym, false); | |
227 | break; | 227 | break; | |
228 | 228 | |||
229 | case psym_else: | 229 | case psym_else: | |
230 | if (psyms->sym[psyms->len - 1] != psym_if_expr_stmt) { | 230 | if (psyms->sym[psyms->len - 1] != psym_if_expr_stmt) { | |
231 | diag(1, "Unmatched 'else'"); | 231 | diag(1, "Unmatched 'else'"); | |
232 | break; | 232 | break; | |
233 | } | 233 | } | |
234 | ps.ind_level = psyms->ind_level[psyms->len - 1]; | 234 | ps.ind_level = psyms->ind_level[psyms->len - 1]; | |
235 | ps.ind_level_follow = ps.ind_level + 1; | 235 | ps.ind_level_follow = ps.ind_level + 1; | |
236 | psyms->sym[psyms->len - 1] = psym_if_expr_stmt_else; | 236 | psyms->sym[psyms->len - 1] = psym_if_expr_stmt_else; | |
237 | break; | 237 | break; | |
238 | 238 | |||
239 | case psym_switch_expr: | 239 | case psym_switch_expr: | |
240 | ps_push(psym_switch_expr, true); | 240 | ps_push(psym_switch_expr, true); | |
241 | ps.ind_level_follow += (int)opt.case_indent + 1; | 241 | ps.ind_level_follow += (int)opt.case_indent + 1; | |
242 | break; | 242 | break; | |
243 | 243 | |||
244 | case psym_while_expr: | 244 | case psym_while_expr: | |
245 | if (psyms->sym[psyms->len - 1] == psym_do_stmt) { | 245 | if (psyms->sym[psyms->len - 1] == psym_do_stmt) { | |
246 | ps.ind_level = ps.ind_level_follow = | 246 | ps.ind_level = ps.ind_level_follow = | |
247 | psyms->ind_level[psyms->len - 1]; | 247 | psyms->ind_level[psyms->len - 1]; | |
248 | ps_push(psym_while_expr, false); | 248 | ps_push(psym_while_expr, false); | |
249 | } else { | 249 | } else { | |
250 | ps_push(psym_while_expr, true); | 250 | ps_push(psym_while_expr, true); | |
251 | ++ps.ind_level_follow; | 251 | ps.ind_level_follow++; | |
252 | } | 252 | } | |
253 | break; | 253 | break; | |
254 | 254 | |||
255 | default: | 255 | default: | |
256 | diag(1, "Unknown code to parser"); | 256 | diag(1, "Unknown code to parser"); | |
257 | return; | 257 | return; | |
258 | } | 258 | } | |
259 | 259 | |||
260 | debug_psyms_stack("before reduction"); | 260 | debug_psyms_stack("before reduction"); | |
261 | psyms_reduce(); | 261 | psyms_reduce(); | |
262 | debug_psyms_stack("after reduction"); | 262 | debug_psyms_stack("after reduction"); | |
263 | } | 263 | } |
--- src/usr.bin/indent/pr_comment.c 2023/06/16 11:27:49 1.166
+++ src/usr.bin/indent/pr_comment.c 2023/06/17 22:28:49 1.167
@@ -1,355 +1,349 @@ | @@ -1,355 +1,349 @@ | |||
1 | /* $NetBSD: pr_comment.c,v 1.166 2023/06/16 11:27:49 rillig Exp $ */ | 1 | /* $NetBSD: pr_comment.c,v 1.167 2023/06/17 22:28:49 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: pr_comment.c,v 1.166 2023/06/16 11:27:49 rillig Exp $"); | 41 | __RCSID("$NetBSD: pr_comment.c,v 1.167 2023/06/17 22:28:49 rillig Exp $"); | |
42 | 42 | |||
43 | #include <string.h> | 43 | #include <string.h> | |
44 | 44 | |||
45 | #include "indent.h" | 45 | #include "indent.h" | |
46 | 46 | |||
47 | static void | 47 | static void | |
48 | com_add_char(char ch) | 48 | com_add_char(char ch) | |
49 | { | 49 | { | |
50 | buf_add_char(&com, ch); | 50 | buf_add_char(&com, ch); | |
51 | } | 51 | } | |
52 | 52 | |||
53 | static void | 53 | static void | |
54 | com_add_delim(void) | 54 | com_add_star(void) | |
55 | { | 55 | { | |
56 | if (opt.star_comment_cont) | 56 | if (opt.star_comment_cont) | |
57 | buf_add_chars(&com, " * ", 3); | 57 | buf_add_chars(&com, " * ", 3); | |
58 | } | 58 | } | |
59 | 59 | |||
60 | static bool | 60 | static bool | |
61 | fits_in_one_line(int max_line_length) | 61 | fits_in_one_line(int max_line_length) | |
62 | { | 62 | { | |
63 | for (const char *start = inp_p, *p = start; *p != '\n'; p++) { | 63 | for (const char *start = inp_p, *p = start; *p != '\n'; p++) { | |
64 | if (p[0] == '*' && p[1] == '/') { | 64 | if (p[0] == '*' && p[1] == '/') { | |
65 | while (p - inp_p >= 2 | 65 | while (p - inp_p >= 2 | |
66 | && ch_isblank(p[-1]) | 66 | && ch_isblank(p[-1]) | |
67 | && ch_isblank(p[-2])) | 67 | && ch_isblank(p[-2])) | |
68 | p--; | 68 | p--; | |
69 | int ind = ind_add(ps.comment_ind + 3, | 69 | int ind = ind_add(ps.comment_ind + 3, | |
70 | start, (size_t)(p - start)); | 70 | start, (size_t)(p - start)); | |
71 | ind += p == start || ch_isblank(p[-1]) ? 2 : 3; | 71 | ind += p == start || ch_isblank(p[-1]) ? 2 : 3; | |
72 | return ind <= max_line_length; | 72 | return ind <= max_line_length; | |
73 | } | 73 | } | |
74 | } | 74 | } | |
75 | return false; | 75 | return false; | |
76 | } | 76 | } | |
77 | 77 | |||
78 | static void | 78 | static void | |
79 | analyze_comment(bool *p_may_wrap, bool *p_delim, int *p_line_length) | 79 | analyze_comment(bool *p_may_wrap, bool *p_delim, int *p_line_length) | |
80 | { | 80 | { | |
81 | bool may_wrap = true; | 81 | bool may_wrap = true; | |
82 | bool delim = false; | 82 | bool delim = false; // only relevant if may_wrap | |
83 | int ind; | 83 | int ind; | |
84 | int line_length = opt.max_line_length; | 84 | int line_length = opt.max_line_length; | |
85 | 85 | |||
86 | if (inp_p - inp.s == 2 && !opt.format_col1_comments) { | 86 | if (inp_p - inp.s == 2 && !opt.format_col1_comments) { | |
87 | may_wrap = false; | 87 | may_wrap = false; | |
88 | ind = 0; | 88 | ind = 0; | |
89 | } else { | 89 | } else { | |
90 | if (inp_p[0] == '-' || inp_p[0] == '*' || | 90 | if (inp_p[0] == '-' || inp_p[0] == '*' || | |
91 | token.s[token.len - 1] == '/' || | 91 | token.s[token.len - 1] == '/' || | |
92 | (inp_p[0] == '\n' && !opt.format_block_comments)) | 92 | (inp_p[0] == '\n' && !opt.format_block_comments)) | |
93 | may_wrap = false; | 93 | may_wrap = false; | |
94 | if (code.len == 0 && inp_p[strspn(inp_p, "*")] == '\n') | 94 | if (code.len == 0 && inp_p[strspn(inp_p, "*")] == '\n') | |
95 | out.line_kind = lk_block_comment; | 95 | out.line_kind = lk_block_comment; | |
96 | 96 | |||
97 | if (com.len > 0) | 97 | if (com.len > 0) | |
98 | output_line(); | 98 | output_line(); | |
99 | if (lab.len == 0 && code.len == 0) { | 99 | if (lab.len == 0 && code.len == 0) { | |
100 | ind = (ps.ind_level - opt.unindent_displace) | 100 | ind = (ps.ind_level - opt.unindent_displace) | |
101 | * opt.indent_size; | 101 | * opt.indent_size; | |
102 | if (ind <= 0) | 102 | if (ind <= 0) | |
103 | ind = opt.format_col1_comments ? 0 : 1; | 103 | ind = opt.format_col1_comments ? 0 : 1; | |
104 | line_length = opt.block_comment_max_line_length; | 104 | line_length = opt.block_comment_max_line_length; | |
105 | if (may_wrap && inp_p[0] == '\n') | 105 | if (may_wrap && inp_p[0] == '\n') | |
106 | delim = true; | 106 | delim = true; | |
107 | if (may_wrap && opt.comment_delimiter_on_blank_line) | 107 | if (may_wrap && opt.comment_delimiter_on_blank_line) | |
108 | delim = true; | 108 | delim = true; | |
109 | } else { | 109 | } else { | |
110 | int target_ind = code.len > 0 | 110 | int min_ind = code.len > 0 | |
111 | ? ind_add(compute_code_indent(), code.s, code.len) | 111 | ? ind_add(compute_code_indent(), code.s, code.len) | |
112 | : ind_add(compute_label_indent(), lab.s, lab.len); | 112 | : ind_add(compute_label_indent(), lab.s, lab.len); | |
113 | 113 | |||
114 | ind = ps.line_has_decl || ps.ind_level == 0 | 114 | ind = ps.line_has_decl || ps.ind_level == 0 | |
115 | ? opt.decl_comment_column - 1 | 115 | ? opt.decl_comment_column - 1 | |
116 | : opt.comment_column - 1; | 116 | : opt.comment_column - 1; | |
117 | if (ind <= target_ind) | 117 | if (ind <= min_ind) | |
118 | ind = next_tab(target_ind); | 118 | ind = next_tab(min_ind); | |
119 | if (ind + 25 > line_length) | 119 | if (ind + 25 > line_length) | |
120 | line_length = ind + 25; | 120 | line_length = ind + 25; | |
121 | } | 121 | } | |
122 | } | 122 | } | |
123 | 123 | |||
124 | if (!may_wrap) { | 124 | if (!may_wrap) { | |
125 | /* Find out how much indentation there was originally, because | 125 | /* Find out how much indentation there was originally, because | |
126 | * that much will have to be ignored by output_line. */ | 126 | * that much will have to be ignored by output_line. */ | |
127 | size_t len = (size_t)(inp_p - 2 - inp.s); | 127 | size_t len = (size_t)(inp_p - 2 - inp.s); | |
128 | ps.comment_shift = -ind_add(0, inp.s, len); | 128 | ps.comment_shift = -ind_add(0, inp.s, len); | |
129 | } else { | 129 | } else { | |
130 | ps.comment_shift = 0; | 130 | ps.comment_shift = 0; | |
131 | if (!(inp_p[0] == '\t' && !ch_isblank(inp_p[1]))) | 131 | if (!(inp_p[0] == '\t' && !ch_isblank(inp_p[1]))) | |
132 | while (ch_isblank(inp_p[0])) | 132 | while (ch_isblank(inp_p[0])) | |
133 | inp_p++; | 133 | inp_p++; | |
134 | } | 134 | } | |
135 | 135 | |||
136 | ps.comment_ind = ind; | 136 | ps.comment_ind = ind; | |
137 | *p_may_wrap = may_wrap; | 137 | *p_may_wrap = may_wrap; | |
138 | *p_delim = delim; | 138 | *p_delim = delim; | |
139 | *p_line_length = line_length; | 139 | *p_line_length = line_length; | |
140 | } | 140 | } | |
141 | 141 | |||
142 | static void | 142 | static void | |
143 | copy_comment_start(bool may_wrap, bool *delim, int line_length) | 143 | copy_comment_start(bool may_wrap, bool *delim, int line_length) | |
144 | { | 144 | { | |
145 | ps.comment_cont = false; | 145 | ps.comment_cont = false; | |
146 | com_add_char('/'); | 146 | com_add_char('/'); | |
147 | com_add_char(token.s[token.len - 1]); /* either '*' or '/' */ | 147 | com_add_char(token.s[token.len - 1]); /* either '*' or '/' */ | |
148 | 148 | |||
149 | if (may_wrap) { | 149 | if (may_wrap) { | |
150 | if (!ch_isblank(inp_p[0])) | 150 | if (!ch_isblank(inp_p[0])) | |
151 | com_add_char(' '); | 151 | com_add_char(' '); | |
152 | 152 | |||
153 | if (*delim && fits_in_one_line(line_length)) | 153 | if (*delim && fits_in_one_line(line_length)) | |
154 | *delim = false; | 154 | *delim = false; | |
155 | if (*delim) { | 155 | if (*delim) { | |
156 | output_line(); | 156 | output_line(); | |
157 | com_add_delim(); | 157 | com_add_star(); | |
158 | } | 158 | } | |
159 | } | 159 | } | |
160 | } | 160 | } | |
161 | 161 | |||
162 | static void | 162 | static void | |
163 | copy_comment_wrap_text(int line_length, ssize_t *last_blank) | 163 | copy_comment_wrap_text(int line_length, ssize_t *last_blank) | |
164 | { | 164 | { | |
165 | int now_len = ind_add(ps.comment_ind, com.s, com.len); | 165 | int ind = ind_add(ps.comment_ind, com.s, com.len); | |
166 | for (;;) { | 166 | for (;;) { | |
167 | char ch = inp_next(); | 167 | char ch = inp_next(); | |
168 | if (ch_isblank(ch)) | 168 | if (ch_isblank(ch)) | |
169 | *last_blank = (ssize_t)com.len; | 169 | *last_blank = (ssize_t)com.len; | |
170 | com_add_char(ch); | 170 | com_add_char(ch); | |
171 | now_len++; | 171 | ind++; | |
172 | if (memchr("*\n\r\b\t", inp_p[0], 6) != NULL) | 172 | if (memchr("*\n\r\b\t", inp_p[0], 6) != NULL) | |
173 | break; | 173 | break; | |
174 | if (now_len >= line_length && *last_blank != -1) | 174 | if (ind >= line_length && *last_blank != -1) | |
175 | break; | 175 | break; | |
176 | } | 176 | } | |
177 | 177 | |||
178 | if (now_len <= line_length) | 178 | if (ind <= line_length) | |
179 | return; | 179 | return; | |
180 | if (ch_isspace(com.s[com.len - 1])) | 180 | if (ch_isspace(com.s[com.len - 1])) | |
181 | return; | 181 | return; | |
182 | 182 | |||
183 | if (*last_blank == -1) { | 183 | if (*last_blank == -1) { | |
184 | /* only a single word in this line */ | 184 | /* only a single word in this line */ | |
185 | output_line(); | 185 | output_line(); | |
186 | com_add_delim(); | 186 | com_add_star(); | |
187 | return; | 187 | return; | |
188 | } | 188 | } | |
189 | 189 | |||
190 | const char *last_word_s = com.s + *last_blank + 1; | 190 | // Move the overlong word to the next line. | |
191 | const char *last_word = com.s + *last_blank + 1; | |||
191 | size_t last_word_len = com.len - (size_t)(*last_blank + 1); | 192 | size_t last_word_len = com.len - (size_t)(*last_blank + 1); | |
192 | com.len = (size_t)*last_blank; | 193 | com.len = (size_t)*last_blank; | |
194 | buf_terminate(&com); | |||
193 | output_line(); | 195 | output_line(); | |
194 | com_add_delim(); | 196 | com_add_star(); | |
195 | 197 | |||
196 | /* Assume that output_line and com_add_delim don't invalidate the | 198 | /* Assume that output_line and com_add_delim left the "unused" part of | |
197 | * "unused" part of the buffer beyond com.s + com.len. */ | 199 | * the now truncated buffer beyond com.s + com.len as-is. */ | |
198 | memmove(com.s + com.len, last_word_s, last_word_len); | 200 | memmove(com.s + com.len, last_word, last_word_len); | |
199 | com.len += last_word_len; | 201 | com.len += last_word_len; | |
202 | buf_terminate(&com); | |||
200 | *last_blank = -1; | 203 | *last_blank = -1; | |
201 | } | 204 | } | |
202 | 205 | |||
206 | /* In a comment that is re-wrapped, handle a single newline character. */ | |||
203 | static bool | 207 | static bool | |
204 | copy_comment_wrap_newline(ssize_t *last_blank, bool seen_newline) | 208 | copy_comment_wrap_newline(ssize_t *last_blank, bool seen_newline) | |
205 | { | 209 | { | |
206 | *last_blank = -1; | 210 | *last_blank = -1; | |
207 | if (seen_newline) { | 211 | if (seen_newline) { | |
208 | if (com.len == 0) | 212 | if (com.len == 0) | |
209 | com_add_char(' '); /* force empty output line */ | 213 | com_add_char(' '); /* force empty output line */ | |
210 | if (com.len > 3) { | 214 | if (com.len > 3) { | |
211 | output_line(); | 215 | output_line(); | |
212 | com_add_delim(); | 216 | com_add_star(); | |
213 | } | 217 | } | |
214 | output_line(); | 218 | output_line(); | |
215 | com_add_delim(); | 219 | com_add_star(); | |
216 | } else { | 220 | } else { | |
217 | if (!(com.len > 0 && ch_isblank(com.s[com.len - 1]))) | 221 | if (!(com.len > 0 && ch_isblank(com.s[com.len - 1]))) | |
218 | com_add_char(' '); | 222 | com_add_char(' '); | |
219 | *last_blank = (int)com.len - 1; | 223 | *last_blank = (int)com.len - 1; | |
220 | } | 224 | } | |
221 | ++line_no; | 225 | line_no++; | |
222 | 226 | |||
223 | /* flush any blanks and/or tabs at start of next line */ | 227 | /* flush any blanks and/or tabs at start of next line */ | |
224 | inp_skip(); /* '\n' */ | 228 | inp_skip(); /* '\n' */ | |
225 | while (ch_isblank(inp_p[0])) | 229 | while (ch_isblank(inp_p[0])) | |
226 | inp_p++; | 230 | inp_p++; | |
227 | if (inp_p[0] == '*' && inp_p[1] == '/') | 231 | if (inp_p[0] == '*' && inp_p[1] == '/') | |
228 | return false; | 232 | return false; | |
229 | if (inp_p[0] == '*') { | 233 | if (inp_p[0] == '*') { | |
230 | inp_p++; | 234 | inp_p++; | |
231 | while (ch_isblank(inp_p[0])) | 235 | while (ch_isblank(inp_p[0])) | |
232 | inp_p++; | 236 | inp_p++; | |
233 | } | 237 | } | |
234 | 238 | |||
235 | return true; | 239 | return true; | |
236 | } | 240 | } | |
237 | 241 | |||
238 | static void | 242 | static void | |
239 | copy_comment_wrap_finish(int line_length, bool delim) | 243 | copy_comment_wrap_finish(int line_length, bool delim) | |
240 | { | 244 | { | |
241 | if (delim) { | 245 | if (delim) { | |
242 | if (com.len > 3) | 246 | if (com.len > 3) | |
243 | output_line(); | 247 | output_line(); | |
244 | else | 248 | else | |
245 | buf_clear(&com); | 249 | buf_clear(&com); | |
246 | com_add_char(' '); | 250 | com_add_char(' '); | |
247 | } else { | 251 | } else { | |
248 | size_t len = com.len; | 252 | size_t len = com.len; | |
253 | // XXX: This loop differs from the one below. | |||
249 | while (ch_isblank(com.s[len - 1])) | 254 | while (ch_isblank(com.s[len - 1])) | |
250 | len--; | 255 | len--; | |
251 | int end_ind = ind_add(ps.comment_ind, com.s, len); | 256 | if (ind_add(ps.comment_ind, com.s, len) + 3 > line_length) | |
252 | if (end_ind + 3 > line_length) | |||
253 | output_line(); | 257 | output_line(); | |
254 | } | 258 | } | |
255 | 259 | |||
256 | while (com.len >= 2 | 260 | while (com.len >= 2 | |
257 | && ch_isblank(com.s[com.len - 1]) | 261 | && ch_isblank(com.s[com.len - 1]) | |
258 | && ch_isblank(com.s[com.len - 2])) | 262 | && ch_isblank(com.s[com.len - 2])) | |
259 | com.len--; | 263 | com.len--; | |
260 | buf_terminate(&com); | 264 | buf_terminate(&com); | |
261 | 265 | |||
262 | inp_p += 2; | 266 | inp_p += 2; | |
263 | if (com.len > 0 && ch_isblank(com.s[com.len - 1])) | 267 | if (com.len > 0 && ch_isblank(com.s[com.len - 1])) | |
264 | buf_add_chars(&com, "*/", 2); | 268 | buf_add_chars(&com, "*/", 2); | |
265 | else | 269 | else | |
266 | buf_add_chars(&com, " */", 3); | 270 | buf_add_chars(&com, " */", 3); | |
267 | } | 271 | } | |
268 | 272 | |||
269 | /* | |||
270 | * Copy characters from 'inp' to 'com'. Try to keep comments from going over | |||
271 | * the maximum line length. To do that, remember where the last blank, tab, or | |||
272 | * newline was. When a line is filled, print up to the last blank and continue | |||
273 | * copying. | |||
274 | */ | |||
275 | static void | 273 | static void | |
276 | copy_comment_wrap(int line_length, bool delim) | 274 | copy_comment_wrap(int line_length, bool delim) | |
277 | { | 275 | { | |
278 | ssize_t last_blank = -1; /* index of the last blank in 'com' */ | 276 | ssize_t last_blank = -1; /* index of the last blank in 'com' */ | |
279 | bool seen_newline = false; | 277 | bool seen_newline = false; | |
280 | 278 | |||
281 | for (;;) { | 279 | for (;;) { | |
282 | if (inp_p[0] == '\n') { | 280 | if (inp_p[0] == '\n') { | |
283 | if (had_eof) | 281 | if (had_eof) | |
284 | goto unterminated_comment; | 282 | goto unterminated_comment; | |
285 | if (!copy_comment_wrap_newline(&last_blank, | 283 | if (!copy_comment_wrap_newline(&last_blank, | |
286 | seen_newline)) | 284 | seen_newline)) | |
287 | break; | 285 | break; | |
288 | seen_newline = true; | 286 | seen_newline = true; | |
289 | } else if (inp_p[0] == '*' && inp_p[1] == '/') | 287 | } else if (inp_p[0] == '*' && inp_p[1] == '/') | |
290 | break; | 288 | break; | |
291 | else { | 289 | else { | |
292 | copy_comment_wrap_text(line_length, &last_blank); | 290 | copy_comment_wrap_text(line_length, &last_blank); | |
293 | seen_newline = false; | 291 | seen_newline = false; | |
294 | } | 292 | } | |
295 | } | 293 | } | |
296 | 294 | |||
297 | copy_comment_wrap_finish(line_length, delim); | 295 | copy_comment_wrap_finish(line_length, delim); | |
298 | return; | 296 | return; | |
299 | 297 | |||
300 | unterminated_comment: | 298 | unterminated_comment: | |
301 | diag(1, "Unterminated comment"); | 299 | diag(1, "Unterminated comment"); | |
302 | output_line(); | 300 | output_line(); | |
303 | } | 301 | } | |
304 | 302 | |||
305 | static void | 303 | static void | |
306 | copy_comment_nowrap(void) | 304 | copy_comment_nowrap(void) | |
307 | { | 305 | { | |
308 | char kind = token.s[token.len - 1]; | 306 | char kind = token.s[token.len - 1]; | |
309 | 307 | |||
310 | for (;;) { | 308 | for (;;) { | |
311 | if (inp_p[0] == '\n') { | 309 | if (inp_p[0] == '\n') { | |
312 | if (kind == '/') | 310 | if (kind == '/') | |
313 | return; | 311 | return; | |
314 | 312 | |||
315 | if (had_eof) { | 313 | if (had_eof) { | |
316 | diag(1, "Unterminated comment"); | 314 | diag(1, "Unterminated comment"); | |
317 | output_line(); | 315 | output_line(); | |
318 | return; | 316 | return; | |
319 | } | 317 | } | |
320 | 318 | |||
321 | if (com.len == 0) | 319 | if (com.len == 0) | |
322 | com_add_char(' '); /* force output of an | 320 | com_add_char(' '); /* force output of an | |
323 | * empty line */ | 321 | * empty line */ | |
324 | output_line(); | 322 | output_line(); | |
325 | ++line_no; | 323 | line_no++; | |
326 | inp_skip(); | 324 | inp_skip(); | |
327 | continue; | 325 | continue; | |
328 | } | 326 | } | |
329 | 327 | |||
330 | com_add_char(*inp_p++); | 328 | com_add_char(*inp_p++); | |
331 | if (com.len >= 2 | 329 | if (com.len >= 2 | |
332 | && com.s[com.len - 2] == '*' | 330 | && com.s[com.len - 2] == '*' | |
333 | && com.s[com.len - 1] == '/' | 331 | && com.s[com.len - 1] == '/' | |
334 | && kind == '*') | 332 | && kind == '*') | |
335 | return; | 333 | return; | |
336 | } | 334 | } | |
337 | } | 335 | } | |
338 | 336 | |||
339 | /* | |||
340 | * Scan, reformat and output a single comment, which is either a block comment | |||
341 | * starting with '/' '*' or an end-of-line comment starting with '//'. | |||
342 | */ | |||
343 | void | 337 | void | |
344 | process_comment(void) | 338 | process_comment(void) | |
345 | { | 339 | { | |
346 | bool may_wrap, delim; | 340 | bool may_wrap, delim; | |
347 | int line_length; | 341 | int line_length; | |
348 | 342 | |||
349 | analyze_comment(&may_wrap, &delim, &line_length); | 343 | analyze_comment(&may_wrap, &delim, &line_length); | |
350 | copy_comment_start(may_wrap, &delim, line_length); | 344 | copy_comment_start(may_wrap, &delim, line_length); | |
351 | if (may_wrap) | 345 | if (may_wrap) | |
352 | copy_comment_wrap(line_length, delim); | 346 | copy_comment_wrap(line_length, delim); | |
353 | else | 347 | else | |
354 | copy_comment_nowrap(); | 348 | copy_comment_nowrap(); | |
355 | } | 349 | } |