Wed Jun 14 20:46:08 2023 UTC ()
indent: clean up the code, add a few tests


(rillig)
diff -r1.7 -r1.8 src/tests/usr.bin/indent/fmt_block.c
diff -r1.7 -r1.8 src/tests/usr.bin/indent/ps_ind_level.c
diff -r1.54 -r1.55 src/tests/usr.bin/indent/fmt_decl.c
diff -r1.13 -r1.14 src/tests/usr.bin/indent/lsym_preprocessing.c
diff -r1.11 -r1.12 src/tests/usr.bin/indent/opt_bc.c
diff -r1.3 -r1.4 src/tests/usr.bin/indent/psym_rbrace.c
diff -r1.60 -r1.61 src/usr.bin/indent/debug.c
diff -r1.366 -r1.367 src/usr.bin/indent/indent.c
diff -r1.196 -r1.197 src/usr.bin/indent/indent.h
diff -r1.76 -r1.77 src/usr.bin/indent/parse.c

cvs diff -r1.7 -r1.8 src/tests/usr.bin/indent/fmt_block.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/fmt_block.c 2023/05/22 23:03:16 1.7
+++ src/tests/usr.bin/indent/fmt_block.c 2023/06/14 20:46:08 1.8
@@ -1,22 +1,21 @@ @@ -1,22 +1,21 @@
1/* $NetBSD: fmt_block.c,v 1.7 2023/05/22 23:03:16 rillig Exp $ */ 1/* $NetBSD: fmt_block.c,v 1.8 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for formatting blocks of statements and declarations. 4 * Tests for formatting blocks of statements and declarations.
5 * 5 *
6 * See also: 6 * See also:
7 * lsym_lbrace.c 7 * lsym_lbrace.c
8 * psym_stmt.c 8 * psym_stmt.c
9 * psym_stmt_list.c 
10 */ 9 */
11 10
12//indent input 11//indent input
13void 12void
14function(void) 13function(void)
15{ 14{
16 if (true) { 15 if (true) {
17 16
18 } 17 }
19 18
20 { 19 {
21 print("block"); 20 print("block");
22 } 21 }

cvs diff -r1.7 -r1.8 src/tests/usr.bin/indent/ps_ind_level.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/ps_ind_level.c 2023/05/15 14:55:47 1.7
+++ src/tests/usr.bin/indent/ps_ind_level.c 2023/06/14 20:46:08 1.8
@@ -1,41 +1,50 @@ @@ -1,41 +1,50 @@
1/* $NetBSD: ps_ind_level.c,v 1.7 2023/05/15 14:55:47 rillig Exp $ */ 1/* $NetBSD: ps_ind_level.c,v 1.8 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * The indentation of the very first line of a file determines the 4 * The indentation of the very first line of a file determines the
5 * indentation of the remaining code. Even if later code has a smaller 5 * indentation of the remaining code. This mode is meant for code snippets from
6 * indentation, it is nevertheless indented to the level given by the first 6 * function bodies. At this level, function definitions are not recognized
7 * line of code. 7 * properly.
 8 *
 9 * Even if later code has a smaller indentation, it is nevertheless indented to
 10 * the level given by the first line of code.
8 * 11 *
9 * In this particular test, the indentation is set to 5 and the tabulator 12 * In this particular test, the indentation is set to 5 and the tabulator
10 * width is set to 8, to demonstrate an off-by-one error in 13 * width is set to 8, to demonstrate an off-by-one error in
11 * main_prepare_parsing that has been fixed in indent.c 1.107 from 2021-10-05. 14 * main_prepare_parsing that has been fixed in indent.c 1.107 from 2021-10-05.
12 * 15 *
13 * The declaration in the first line is indented by 3 tabs, amounting to 24 16 * The declaration in the first line is indented by 3 tabs, amounting to 24
14 * spaces. The initial indentation of the code is intended to be rounded down, 17 * spaces. The initial indentation of the code is intended to be rounded down,
15 * to 4 levels of indentation, amounting to 20 spaces. 18 * to 4 levels of indentation, amounting to 20 spaces.
16 */ 19 */
17//indent input 20//indent input
18 int indented_by_24; 21 int indented_by_24;
19 22
20void function_in_column_1(void){} 23void function_in_column_1(void){}
 24
 25 #if indented
 26#endif
21//indent end 27//indent end
22 28
23/* 5 spaces indentation, 8 spaces per tabulator */ 29/* 5 spaces indentation, 8 spaces per tabulator */
24//indent run -i5 -ts8 30//indent run -i5 -ts8
25 int indented_by_24; 31 int indented_by_24;
26 32
27 void function_in_column_1(void) { 33 void function_in_column_1(void) {
28 } 34 }
 35
 36#if indented
 37#endif
29//indent end 38//indent end
30 39
31 40
32/* 41/*
33 * Labels are always indented 2 levels left of the code. The first line starts 42 * Labels are always indented 2 levels left of the code. The first line starts
34 * at indentation level 3, the code in the function is therefore at level 4, 43 * at indentation level 3, the code in the function is therefore at level 4,
35 * and the label is at level 2, sticking out of the code. 44 * and the label is at level 2, sticking out of the code.
36 */ 45 */
37//indent input 46//indent input
38 int indent_by_24; 47 int indent_by_24;
39 48
40void function(void) { 49void function(void) {
41label:; 50label:;

cvs diff -r1.54 -r1.55 src/tests/usr.bin/indent/fmt_decl.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/fmt_decl.c 2023/06/10 17:56:29 1.54
+++ src/tests/usr.bin/indent/fmt_decl.c 2023/06/14 20:46:08 1.55
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fmt_decl.c,v 1.54 2023/06/10 17:56:29 rillig Exp $ */ 1/* $NetBSD: fmt_decl.c,v 1.55 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for declarations of global variables, external functions, and local 4 * Tests for declarations of global variables, external functions, and local
5 * variables. 5 * variables.
6 * 6 *
7 * See also: 7 * See also:
8 * opt_di.c 8 * opt_di.c
9 */ 9 */
10 10
11/* See FreeBSD r303570 */ 11/* See FreeBSD r303570 */
12 12
13/* 13/*
14 * A type definition usually declares a single type, so there is no need to 14 * A type definition usually declares a single type, so there is no need to
@@ -1075,13 +1075,114 @@ b[] = {1, 2}; @@ -1075,13 +1075,114 @@ b[] = {1, 2};
1075 * When a type occurs at the top level, it forces a line break before. 1075 * When a type occurs at the top level, it forces a line break before.
1076 */ 1076 */
1077//indent input 1077//indent input
1078__attribute__((__dead__)) void die(void) {} 1078__attribute__((__dead__)) void die(void) {}
1079//indent end 1079//indent end
1080 1080
1081//indent run 1081//indent run
1082__attribute__((__dead__)) 1082__attribute__((__dead__))
1083void 1083void
1084die(void) 1084die(void)
1085{ 1085{
1086} 1086}
1087//indent end 1087//indent end
 1088
 1089
 1090/*
 1091 * In very rare cases, the type of a declarator might include literal tab
 1092 * characters. This tab might affect the indentation of the declarator, but
 1093 * only if it occurs before the declarator, and that is hard to achieve.
 1094 */
 1095//indent input
 1096int arr[sizeof " "];
 1097//indent end
 1098
 1099//indent run-equals-input
 1100
 1101
 1102/*
 1103 * The '}' of an initializer is not supposed to end the statement, it only ends
 1104 * the brace level of the initializer expression.
 1105 */
 1106//indent input
 1107int multi_line[1][1][1] = {
 1108{
 1109{
 11101
 1111},
 1112},
 1113};
 1114int single_line[2][1][1] = {{{1},},{{2}}};
 1115//indent end
 1116
 1117//indent run -di0
 1118int multi_line[1][1][1] = {
 1119 {
 1120 {
 1121 1
 1122 },
 1123 },
 1124};
 1125int single_line[2][1][1] = {{{1},}, {{2}}};
 1126//indent end
 1127
 1128
 1129/*
 1130 * The '}' of an initializer is not supposed to end the statement, it only ends
 1131 * the brace level of the initializer expression.
 1132 */
 1133//indent input
 1134{
 1135int multi_line = {
 1136{
 1137{
 1138b
 1139},
 1140},
 1141};
 1142int single_line = {{{b},},{}};
 1143}
 1144//indent end
 1145
 1146//indent run -di0
 1147{
 1148 int multi_line = {
 1149 {
 1150 {
 1151 b
 1152 },
 1153 },
 1154 };
 1155 int single_line = {{{b},}, {}};
 1156}
 1157//indent end
 1158
 1159
 1160/*
 1161 * In initializers, multi-line expressions don't have their second line
 1162 * indented, even though they should.
 1163 */
 1164//indent input
 1165{
 1166multi_line = (int[]){
 1167{1
 1168+1},
 1169{1
 1170+1},
 1171{1
 1172+1},
 1173};
 1174}
 1175//indent end
 1176
 1177//indent run
 1178{
 1179 multi_line = (int[]){
 1180 {1
 1181 + 1},
 1182 {1
 1183 + 1},
 1184 {1
 1185 + 1},
 1186 };
 1187}
 1188//indent end

cvs diff -r1.13 -r1.14 src/tests/usr.bin/indent/lsym_preprocessing.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/lsym_preprocessing.c 2023/06/14 17:07:32 1.13
+++ src/tests/usr.bin/indent/lsym_preprocessing.c 2023/06/14 20:46:08 1.14
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: lsym_preprocessing.c,v 1.13 2023/06/14 17:07:32 rillig Exp $ */ 1/* $NetBSD: lsym_preprocessing.c,v 1.14 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the token lsym_preprocessing, which represents a '#' that starts 4 * Tests for the token lsym_preprocessing, which represents a '#' that starts
5 * a preprocessing line. 5 * a preprocessing line.
6 * 6 *
7 * #define 7 * #define
8 * #ifdef 8 * #ifdef
9 * #include 9 * #include
10 * #line 10 * #line
11 * #pragma 11 * #pragma
12 * 12 *
13 * The whole preprocessing line is processed separately from the main source 13 * The whole preprocessing line is processed separately from the main source
14 * code, without much tokenizing or parsing. 14 * code, without much tokenizing or parsing.
@@ -297,13 +297,48 @@ int before; @@ -297,13 +297,48 @@ int before;
297#else 297#else
298#elif 0 298#elif 0
299#elifdef var 299#elifdef var
300#endif 300#endif
301 301
302#unknown 302#unknown
303# 3 "file.c" 303# 3 "file.c"
304exit 1 304exit 1
305error: Standard Input:1: Unmatched #else 305error: Standard Input:1: Unmatched #else
306error: Standard Input:2: Unmatched #elif 306error: Standard Input:2: Unmatched #elif
307error: Standard Input:3: Unmatched #elifdef 307error: Standard Input:3: Unmatched #elifdef
308error: Standard Input:4: Unmatched #endif 308error: Standard Input:4: Unmatched #endif
309//indent end 309//indent end
 310
 311
 312/*
 313 * The '#' can only occur at the beginning of a line, therefore indent does not
 314 * care when it occurs in the middle of a line.
 315 */
 316//indent input
 317int no = #;
 318//indent end
 319
 320//indent run -di0
 321int no =
 322#;
 323//indent end
 324
 325
 326/*
 327 * Preprocessing directives may be indented; indent moves them to the beginning
 328 * of a line.
 329 */
 330//indent input
 331#if 0
 332 #if 1 \
 333 || 2
 334 #endif
 335#endif
 336//indent end
 337
 338//indent run
 339#if 0
 340#if 1 \
 341 || 2
 342#endif
 343#endif
 344//indent end

cvs diff -r1.11 -r1.12 src/tests/usr.bin/indent/opt_bc.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/opt_bc.c 2023/06/14 14:11:28 1.11
+++ src/tests/usr.bin/indent/opt_bc.c 2023/06/14 20:46:08 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: opt_bc.c,v 1.11 2023/06/14 14:11:28 rillig Exp $ */ 1/* $NetBSD: opt_bc.c,v 1.12 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the options '-bc' and '-nbc'. 4 * Tests for the options '-bc' and '-nbc'.
5 * 5 *
6 * The option '-bc' forces a newline after each comma in a declaration. 6 * The option '-bc' forces a newline after each comma in a declaration.
7 * 7 *
8 * The option '-nbc' removes line breaks between declarators. In most other 8 * The option '-nbc' removes line breaks between declarators. In most other
9 * places, indent preserves line breaks. 9 * places, indent preserves line breaks.
10 */ 10 */
11 11
12//indent input 12//indent input
13int a,b,c; 13int a,b,c;
14void function_declaration(int a,int b,int c); 14void function_declaration(int a,int b,int c);
@@ -111,26 +111,37 @@ int d; @@ -111,26 +111,37 @@ int d;
111//indent input 111//indent input
112int a = 1, b = 2; 112int a = 1, b = 2;
113int a = (1), b = 2; 113int a = (1), b = 2;
114//indent end 114//indent end
115 115
116//indent run -bc 116//indent run -bc
117int a = 1, 117int a = 1,
118 b = 2; 118 b = 2;
119int a = (1), 119int a = (1),
120 b = 2; 120 b = 2;
121//indent end 121//indent end
122 122
123 123
 124//indent input
 125int a,
 126b,
 127c;
 128//indent end
 129
 130//indent run -nbc -di0
 131int a, b, c;
 132//indent end
 133
 134
124/* 135/*
125 * When declarations are too long to fit in a single line, they should not be 136 * When declarations are too long to fit in a single line, they should not be
126 * joined. 137 * joined.
127 */ 138 */
128//indent input 139//indent input
129{ 140{
130 const struct paren_level *prev = state.prev_ps.paren.item, 141 const struct paren_level *prev = state.prev_ps.paren.item,
131 *curr = ps.paren.item; 142 *curr = ps.paren.item;
132} 143}
133//indent end 144//indent end
134 145
135//indent run 146//indent run
136// $ FIXME: The line becomes too long. 147// $ FIXME: The line becomes too long.

cvs diff -r1.3 -r1.4 src/tests/usr.bin/indent/psym_rbrace.c (expand / switch to unified diff)

--- src/tests/usr.bin/indent/psym_rbrace.c 2022/04/24 09:04:12 1.3
+++ src/tests/usr.bin/indent/psym_rbrace.c 2023/06/14 20:46:08 1.4
@@ -1,15 +1,88 @@ @@ -1,15 +1,88 @@
1/* $NetBSD: psym_rbrace.c,v 1.3 2022/04/24 09:04:12 rillig Exp $ */ 1/* $NetBSD: psym_rbrace.c,v 1.4 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/* 3/*
4 * Tests for the parser symbol psym_rbrace, which represents '}' and finishes 4 * Tests for the parser symbol psym_rbrace, which represents '}' and finishes
5 * the previous '{'. 5 * the previous '{'.
6 * 6 *
7 * See also: 7 * See also:
8 * psym_lbrace.c 8 * psym_lbrace.c
9 */ 9 */
10 10
 11
 12/*
 13 * While it is a syntax error to have an unfinished declaration between braces,
 14 * indent is forgiving enough to accept this input.
 15 */
 16//indent input
 17{
 18 int
 19}
 20//indent end
 21
 22//indent run
 23{
 24 int
 25 }
 26exit 1
 27error: Standard Input:3: Statement nesting error
 28error: Standard Input:3: Stuff missing from end of file
 29//indent end
 30
 31
11//indent input 32//indent input
12// TODO: add input 33{
 34 do {
 35 } while (cond)
 36}
13//indent end 37//indent end
14 38
 39// XXX: Why doesn't indent complain about the missing semicolon?
15//indent run-equals-input 40//indent run-equals-input
 41
 42
 43//indent input
 44{
 45 if (cond)
 46}
 47//indent end
 48
 49//indent run
 50{
 51 if (cond)
 52 }
 53exit 1
 54error: Standard Input:3: Statement nesting error
 55error: Standard Input:3: Stuff missing from end of file
 56//indent end
 57
 58
 59//indent input
 60{
 61 switch (expr)
 62}
 63//indent end
 64
 65//indent run
 66{
 67 switch (expr)
 68 }
 69exit 1
 70error: Standard Input:3: Statement nesting error
 71error: Standard Input:3: Stuff missing from end of file
 72//indent end
 73
 74
 75//indent input
 76{
 77 while (cond)
 78}
 79//indent end
 80
 81//indent run
 82{
 83 while (cond)
 84 }
 85exit 1
 86error: Standard Input:3: Statement nesting error
 87error: Standard Input:3: Stuff missing from end of file
 88//indent end

cvs diff -r1.60 -r1.61 src/usr.bin/indent/debug.c (expand / switch to unified diff)

--- src/usr.bin/indent/debug.c 2023/06/14 16:14:30 1.60
+++ src/usr.bin/indent/debug.c 2023/06/14 20:46:08 1.61
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: debug.c,v 1.60 2023/06/14 16:14:30 rillig Exp $ */ 1/* $NetBSD: debug.c,v 1.61 2023/06/14 20:46:08 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.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
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.60 2023/06/14 16:14:30 rillig Exp $"); 33__RCSID("$NetBSD: debug.c,v 1.61 2023/06/14 20:46:08 rillig Exp $");
34 34
35#include <stdarg.h> 35#include <stdarg.h>
36#include <string.h> 36#include <string.h>
37 37
38#include "indent.h" 38#include "indent.h"
39 39
40#ifdef debug 40#ifdef debug
41 41
42static struct { 42static struct {
43 // 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 = {
@@ -357,27 +357,27 @@ debug_parser_state(void) @@ -357,27 +357,27 @@ debug_parser_state(void)
357 state.heading = "spacing inside a statement or declaration"; 357 state.heading = "spacing inside a statement or declaration";
358 debug_ps_bool(next_unary); 358 debug_ps_bool(next_unary);
359 debug_ps_bool(want_blank); 359 debug_ps_bool(want_blank);
360 debug_ps_int(ind_paren_level); 360 debug_ps_int(ind_paren_level);
361 debug_ps_paren(); 361 debug_ps_paren();
362 362
363 state.heading = "indentation of comments"; 363 state.heading = "indentation of comments";
364 debug_ps_int(comment_ind); 364 debug_ps_int(comment_ind);
365 debug_ps_int(comment_shift); 365 debug_ps_int(comment_shift);
366 debug_ps_bool(comment_in_first_line); 366 debug_ps_bool(comment_in_first_line);
367 367
368 state.heading = "vertical spacing"; 368 state.heading = "vertical spacing";
369 debug_ps_bool(break_after_comma); 369 debug_ps_bool(break_after_comma);
370 debug_ps_bool(force_nl); 370 debug_ps_bool(want_newline);
371 debug_ps_enum(declaration, declaration_name); 371 debug_ps_enum(declaration, declaration_name);
372 debug_ps_bool(blank_line_after_decl); 372 debug_ps_bool(blank_line_after_decl);
373 373
374 state.heading = NULL; 374 state.heading = NULL;
375 debug_blank_line(); 375 debug_blank_line();
376 376
377 state.prev_ps = ps; 377 state.prev_ps = ps;
378 state.ps_first = false; 378 state.ps_first = false;
379} 379}
380 380
381void 381void
382debug_psyms_stack(const char *situation) 382debug_psyms_stack(const char *situation)
383{ 383{

cvs diff -r1.366 -r1.367 src/usr.bin/indent/indent.c (expand / switch to unified diff)

--- src/usr.bin/indent/indent.c 2023/06/14 19:05:40 1.366
+++ src/usr.bin/indent/indent.c 2023/06/14 20:46:08 1.367
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: indent.c,v 1.366 2023/06/14 19:05:40 rillig Exp $ */ 1/* $NetBSD: indent.c,v 1.367 2023/06/14 20:46:08 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
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
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.366 2023/06/14 19:05:40 rillig Exp $"); 41__RCSID("$NetBSD: indent.c,v 1.367 2023/06/14 20:46:08 rillig Exp $");
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <err.h> 44#include <err.h>
45#include <stdarg.h> 45#include <stdarg.h>
46#include <stdio.h> 46#include <stdio.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "indent.h" 50#include "indent.h"
51 51
52struct options opt = { 52struct options opt = {
53 .brace_same_line = true, 53 .brace_same_line = true,
54 .comment_delimiter_on_blank_line = true, 54 .comment_delimiter_on_blank_line = true,
@@ -177,27 +177,27 @@ ind_add(int ind, const char *s, size_t l @@ -177,27 +177,27 @@ ind_add(int ind, const char *s, size_t l
177 else if (*p == '\t') 177 else if (*p == '\t')
178 ind = next_tab(ind); 178 ind = next_tab(ind);
179 else if (*p == '\b') 179 else if (*p == '\b')
180 --ind; 180 --ind;
181 else 181 else
182 ++ind; 182 ++ind;
183 } 183 }
184 return ind; 184 return ind;
185} 185}
186 186
187static void 187static void
188init_globals(void) 188init_globals(void)
189{ 189{
190 ps_push(psym_stmt, false); 190 ps_push(psym_stmt, false); /* as a stop symbol */
191 ps.prev_lsym = lsym_semicolon; 191 ps.prev_lsym = lsym_semicolon;
192 ps.lbrace_kind = psym_lbrace_block; 192 ps.lbrace_kind = psym_lbrace_block;
193 193
194 const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX"); 194 const char *suffix = getenv("SIMPLE_BACKUP_SUFFIX");
195 if (suffix != NULL) 195 if (suffix != NULL)
196 backup_suffix = suffix; 196 backup_suffix = suffix;
197} 197}
198 198
199static void 199static void
200load_profiles(int argc, char **argv) 200load_profiles(int argc, char **argv)
201{ 201{
202 const char *profile_name = NULL; 202 const char *profile_name = NULL;
203 203
@@ -335,51 +335,51 @@ move_com_to_code(lexer_symbol lsym) @@ -335,51 +335,51 @@ move_com_to_code(lexer_symbol lsym)
335 buf_add_char(&code, ' '); 335 buf_add_char(&code, ' ');
336 buf_add_buf(&code, &com); 336 buf_add_buf(&code, &com);
337 buf_clear(&com); 337 buf_clear(&com);
338 ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket; 338 ps.want_blank = lsym != lsym_rparen && lsym != lsym_rbracket;
339} 339}
340 340
341static void 341static void
342update_ps_lbrace_kind(lexer_symbol lsym) 342update_ps_lbrace_kind(lexer_symbol lsym)
343{ 343{
344 if (lsym == lsym_tag) { 344 if (lsym == lsym_tag) {
345 ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct : 345 ps.lbrace_kind = token.s[0] == 's' ? psym_lbrace_struct :
346 token.s[0] == 'u' ? psym_lbrace_union : 346 token.s[0] == 'u' ? psym_lbrace_union :
347 psym_lbrace_enum; 347 psym_lbrace_enum;
348 } else if (lsym != lsym_type_outside_parentheses 348 } else if (lsym == lsym_type_outside_parentheses
349 && lsym != lsym_word 349 || lsym == lsym_word
350 && lsym != lsym_lbrace) 350 || lsym == lsym_lbrace) {
 351 /* Keep the current '{' kind. */
 352 } else
351 ps.lbrace_kind = psym_lbrace_block; 353 ps.lbrace_kind = psym_lbrace_block;
352} 354}
353 355
354static void 356static void
355indent_declarator(int decl_ind, bool tabs_to_var) 357indent_declarator(int decl_ind, bool tabs_to_var)
356{ 358{
357 int base = ps.ind_level * opt.indent_size; 359 int base = ps.ind_level * opt.indent_size;
358 int ind = base + (int)code.len; 360 int ind = ind_add(base, code.s, code.len);
359 int target = base + decl_ind; 361 int target = base + decl_ind;
360 size_t orig_code_len = code.len; 362 size_t orig_code_len = code.len;
361 363
362 if (tabs_to_var) 364 if (tabs_to_var)
363 for (int next; (next = next_tab(ind)) <= target; ind = next) 365 for (int next; (next = next_tab(ind)) <= target; ind = next)
364 buf_add_char(&code, '\t'); 366 buf_add_char(&code, '\t');
365 
366 for (; ind < target; ind++) 367 for (; ind < target; ind++)
367 buf_add_char(&code, ' '); 368 buf_add_char(&code, ' ');
368 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 ps.want_blank = false; 371
372 } 372 ps.want_blank = false;
373 ps.decl_indent_done = true; 373 ps.decl_indent_done = true;
374} 374}
375 375
376static bool 376static bool
377is_function_pointer_declaration(void) 377is_function_pointer_declaration(void)
378{ 378{
379 return ps.in_decl 379 return ps.in_decl
380 && !ps.in_init 380 && !ps.in_init
381 && !ps.decl_indent_done 381 && !ps.decl_indent_done
382 && !ps.line_has_func_def 382 && !ps.line_has_func_def
383 && ps.ind_paren_level == 0; 383 && ps.ind_paren_level == 0;
384} 384}
385 385
@@ -546,27 +546,27 @@ process_preprocessing(void) @@ -546,27 +546,27 @@ process_preprocessing(void)
546 546
547static void 547static void
548process_newline(void) 548process_newline(void)
549{ 549{
550 if (ps.prev_lsym == lsym_comma 550 if (ps.prev_lsym == lsym_comma
551 && ps.paren.len == 0 && !ps.in_init 551 && ps.paren.len == 0 && !ps.in_init
552 && !opt.break_after_comma && ps.break_after_comma 552 && !opt.break_after_comma && ps.break_after_comma
553 && lab.len == 0 /* for preprocessing lines */ 553 && lab.len == 0 /* for preprocessing lines */
554 && com.len == 0) 554 && com.len == 0)
555 goto stay_in_line; 555 goto stay_in_line;
556 if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr 556 if (ps.psyms.sym[ps.psyms.len - 1] == psym_switch_expr
557 && opt.brace_same_line 557 && opt.brace_same_line
558 && com.len == 0) { 558 && com.len == 0) {
559 ps.force_nl = true; 559 ps.want_newline = true;
560 goto stay_in_line; 560 goto stay_in_line;
561 } 561 }
562 562
563 output_line(); 563 output_line();
564 564
565stay_in_line: 565stay_in_line:
566 ++line_no; 566 ++line_no;
567} 567}
568 568
569static bool 569static bool
570want_blank_before_lparen(void) 570want_blank_before_lparen(void)
571{ 571{
572 if (opt.proc_calls_space) 572 if (opt.proc_calls_space)
@@ -581,133 +581,128 @@ want_blank_before_lparen(void) @@ -581,133 +581,128 @@ want_blank_before_lparen(void)
581 return false; 581 return false;
582 return true; 582 return true;
583} 583}
584 584
585static void 585static void
586process_lparen(void) 586process_lparen(void)
587{ 587{
588 588
589 if (is_function_pointer_declaration()) 589 if (is_function_pointer_declaration())
590 indent_declarator(ps.decl_ind, ps.tabs_to_var); 590 indent_declarator(ps.decl_ind, ps.tabs_to_var);
591 else if (ps.want_blank && want_blank_before_lparen()) 591 else if (ps.want_blank && want_blank_before_lparen())
592 buf_add_char(&code, ' '); 592 buf_add_char(&code, ' ');
593 ps.want_blank = false; 593 ps.want_blank = false;
594 buf_add_char(&code, token.s[0]); 594 buf_add_buf(&code, &token);
595 595
596 if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0) 596 if (opt.extra_expr_indent && ps.spaced_expr_psym != psym_0)
597 ps.extra_expr_indent = eei_maybe; 597 ps.extra_expr_indent = eei_maybe;
598 598
599 if (ps.in_var_decl && ps.psyms.len <= 3 && !ps.in_init) { 599 if (ps.in_var_decl && ps.psyms.len <= 3 && !ps.in_init) {
600 parse(psym_stmt); /* prepare for function definition */ 600 parse(psym_stmt); /* prepare for function definition */
601 ps.in_var_decl = false; 601 ps.in_var_decl = false;
602 } 602 }
603 603
604 enum paren_level_cast cast = cast_unknown; 604 enum paren_level_cast cast = cast_unknown;
605 if (ps.prev_lsym == lsym_offsetof 605 if (ps.prev_lsym == lsym_offsetof
606 || ps.prev_lsym == lsym_sizeof 606 || ps.prev_lsym == lsym_sizeof
607 || ps.prev_lsym == lsym_for 607 || ps.prev_lsym == lsym_for
608 || ps.prev_lsym == lsym_if 608 || ps.prev_lsym == lsym_if
609 || ps.prev_lsym == lsym_switch 609 || ps.prev_lsym == lsym_switch
610 || ps.prev_lsym == lsym_while 610 || ps.prev_lsym == lsym_while
611 || ps.line_has_func_def) 611 || ps.line_has_func_def)
612 cast = cast_no; 612 cast = cast_no;
613 613
614 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast); 614 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast);
615} 615}
616 616
617static void 617static void
618process_rparen(void) 618process_rparen(void)
619{ 619{
620 if (ps.paren.len == 0) { 620 if (ps.paren.len == 0)
621 diag(0, "Extra '%c'", *token.s); 621 diag(0, "Extra '%c'", *token.s);
622 goto unbalanced; 
623 } 
624 622
625 enum paren_level_cast cast = ps.paren.item[--ps.paren.len].cast; 623 ps.prev_paren_was_cast = ps.paren.len > 0
626 if (ps.in_func_def_params || (ps.line_has_decl && !ps.in_init)) 624 && ps.paren.item[--ps.paren.len].cast == cast_maybe
627 cast = cast_no; 625 && !ps.in_func_def_params
628 626 && !(ps.line_has_decl && !ps.in_init);
629 ps.prev_paren_was_cast = cast == cast_maybe; 627 if (ps.prev_paren_was_cast) {
630 if (cast == cast_maybe) { 
631 ps.next_unary = true; 628 ps.next_unary = true;
632 ps.want_blank = opt.space_after_cast; 629 ps.want_blank = opt.space_after_cast;
633 } else 630 } else
634 ps.want_blank = true; 631 ps.want_blank = true;
635 632
636 if (code.len == 0) 633 if (code.len == 0)
637 ps.ind_paren_level = (int)ps.paren.len; 634 ps.ind_paren_level = (int)ps.paren.len;
638 635
639unbalanced: 636 buf_add_buf(&code, &token);
640 buf_add_char(&code, token.s[0]); 
641 637
642 if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { 638 if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) {
643 if (ps.extra_expr_indent == eei_maybe) 
644 ps.extra_expr_indent = eei_last; 
645 ps.force_nl = true; 
646 ps.next_unary = true; 
647 ps.in_stmt_or_decl = false; 
648 parse(ps.spaced_expr_psym); 639 parse(ps.spaced_expr_psym);
649 ps.spaced_expr_psym = psym_0; 640 ps.spaced_expr_psym = psym_0;
 641
 642 ps.want_newline = true;
 643 ps.next_unary = true;
 644 ps.in_stmt_or_decl = false;
650 ps.want_blank = true; 645 ps.want_blank = true;
651 out.line_kind = lk_stmt_head; 646 out.line_kind = lk_stmt_head;
 647 if (ps.extra_expr_indent == eei_maybe)
 648 ps.extra_expr_indent = eei_last;
652 } 649 }
653} 650}
654 651
655static void 652static void
656process_lbracket(void) 653process_lbracket(void)
657{ 654{
658 if (code.len > 0 655 if (code.len > 0
659 && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op)) 656 && (ps.prev_lsym == lsym_comma || ps.prev_lsym == lsym_binary_op))
660 buf_add_char(&code, ' '); 657 buf_add_char(&code, ' ');
 658 buf_add_buf(&code, &token);
661 ps.want_blank = false; 659 ps.want_blank = false;
662 buf_add_char(&code, token.s[0]); 
663 660
664 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast_no); 661 paren_stack_push(&ps.paren, ind_add(0, code.s, code.len), cast_no);
665} 662}
666 663
667static void 664static void
668process_rbracket(void) 665process_rbracket(void)
669{ 666{
670 if (ps.paren.len == 0) { 667 if (ps.paren.len == 0)
671 diag(0, "Extra '%c'", *token.s); 668 diag(0, "Extra '%c'", *token.s);
672 goto unbalanced; 669 if (ps.paren.len > 0)
673 } 670 ps.paren.len--;
674 ps.paren.len--; 
675 671
676 ps.want_blank = true; 
677 if (code.len == 0) 672 if (code.len == 0)
678 ps.ind_paren_level = (int)ps.paren.len; 673 ps.ind_paren_level = (int)ps.paren.len;
679 674
680unbalanced: 675 buf_add_buf(&code, &token);
681 buf_add_char(&code, token.s[0]); 676 ps.want_blank = true;
682} 677}
683 678
684static void 679static void
685process_lbrace(void) 680process_lbrace(void)
686{ 681{
687 if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) { 682 if (ps.prev_lsym == lsym_rparen && ps.prev_paren_was_cast) {
688 ps.in_var_decl = true; // XXX: not really 683 ps.in_var_decl = true; // XXX: not really
689 ps.in_init = true; 684 ps.in_init = true;
690 } 685 }
691 686
692 if (out.line_kind == lk_stmt_head) 687 if (out.line_kind == lk_stmt_head)
693 out.line_kind = lk_other; 688 out.line_kind = lk_other;
694 689
695 ps.in_stmt_or_decl = false; /* don't indent the {} */ 690 ps.in_stmt_or_decl = false; /* don't indent the {} */
696 691
697 if (ps.in_init) 692 if (ps.in_init)
698 ps.init_level++; 693 ps.init_level++;
699 else 694 else
700 ps.force_nl = true; 695 ps.want_newline = true;
701 696
702 if (code.len > 0 && !ps.in_init) { 697 if (code.len > 0 && !ps.in_init) {
703 if (!opt.brace_same_line || 698 if (!opt.brace_same_line ||
704 (code.len > 0 && code.s[code.len - 1] == '}')) 699 (code.len > 0 && code.s[code.len - 1] == '}'))
705 output_line(); 700 output_line();
706 else if (ps.in_func_def_params && !ps.in_var_decl) { 701 else if (ps.in_func_def_params && !ps.in_var_decl) {
707 ps.ind_level_follow = 0; 702 ps.ind_level_follow = 0;
708 if (opt.function_brace_split) 703 if (opt.function_brace_split)
709 output_line(); 704 output_line();
710 else 705 else
711 ps.want_blank = true; 706 ps.want_blank = true;
712 } 707 }
713 } 708 }
@@ -779,27 +774,27 @@ process_rbrace(void) @@ -779,27 +774,27 @@ process_rbrace(void)
779 ? opt.decl_indent : opt.local_decl_indent; 774 ? opt.decl_indent : opt.local_decl_indent;
780 } 775 }
781 ps.in_decl = true; 776 ps.in_decl = true;
782 } 777 }
783 778
784 if (ps.psyms.len == 3) 779 if (ps.psyms.len == 3)
785 out.line_kind = lk_func_end; 780 out.line_kind = lk_func_end;
786 781
787 parse(psym_rbrace); 782 parse(psym_rbrace);
788 783
789 if (!ps.in_var_decl 784 if (!ps.in_var_decl
790 && ps.psyms.sym[ps.psyms.len - 1] != psym_do_stmt 785 && ps.psyms.sym[ps.psyms.len - 1] != psym_do_stmt
791 && ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt) 786 && ps.psyms.sym[ps.psyms.len - 1] != psym_if_expr_stmt)
792 ps.force_nl = true; 787 ps.want_newline = true;
793} 788}
794 789
795static void 790static void
796process_period(void) 791process_period(void)
797{ 792{
798 if (code.len > 0 && code.s[code.len - 1] == ',') 793 if (code.len > 0 && code.s[code.len - 1] == ',')
799 buf_add_char(&code, ' '); 794 buf_add_char(&code, ' ');
800 buf_add_char(&code, '.'); 795 buf_add_char(&code, '.');
801 ps.want_blank = false; 796 ps.want_blank = false;
802} 797}
803 798
804static void 799static void
805process_unary_op(void) 800process_unary_op(void)
@@ -836,41 +831,41 @@ process_comma(void) @@ -836,41 +831,41 @@ process_comma(void)
836 /* indent leading commas and not the actual identifiers */ 831 /* indent leading commas and not the actual identifiers */
837 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var); 832 indent_declarator(ps.decl_ind - 1, ps.tabs_to_var);
838 } 833 }
839 834
840 buf_add_char(&code, ','); 835 buf_add_char(&code, ',');
841 836
842 if (ps.paren.len == 0) { 837 if (ps.paren.len == 0) {
843 if (ps.init_level == 0) 838 if (ps.init_level == 0)
844 ps.in_init = false; 839 ps.in_init = false;
845 int typical_varname_length = 8; 840 int typical_varname_length = 8;
846 if (ps.break_after_comma && (opt.break_after_comma || 841 if (ps.break_after_comma && (opt.break_after_comma ||
847 ind_add(compute_code_indent(), code.s, code.len) 842 ind_add(compute_code_indent(), code.s, code.len)
848 >= opt.max_line_length - typical_varname_length)) 843 >= opt.max_line_length - typical_varname_length))
849 ps.force_nl = true; 844 ps.want_newline = true;
850 } 845 }
851} 846}
852 847
853static void 848static void
854process_label_colon(void) 849process_label_colon(void)
855{ 850{
856 buf_add_buf(&lab, &code); 851 buf_add_buf(&lab, &code);
857 buf_add_char(&lab, ':'); 852 buf_add_char(&lab, ':');
858 buf_clear(&code); 853 buf_clear(&code);
859 854
860 if (ps.seen_case) 855 if (ps.seen_case)
861 out.line_kind = lk_case_or_default; 856 out.line_kind = lk_case_or_default;
862 ps.in_stmt_or_decl = false; 857 ps.in_stmt_or_decl = false;
863 ps.force_nl = ps.seen_case; 858 ps.want_newline = ps.seen_case;
864 ps.seen_case = false; 859 ps.seen_case = false;
865 ps.want_blank = false; 860 ps.want_blank = false;
866} 861}
867 862
868static void 863static void
869process_other_colon(void) 864process_other_colon(void)
870{ 865{
871 buf_add_char(&code, ':'); 866 buf_add_char(&code, ':');
872 ps.want_blank = ps.decl_level == 0; 867 ps.want_blank = ps.decl_level == 0;
873} 868}
874 869
875static void 870static void
876process_semicolon(void) 871process_semicolon(void)
@@ -905,27 +900,27 @@ process_semicolon(void) @@ -905,27 +900,27 @@ process_semicolon(void)
905 ps.paren.len = 0; 900 ps.paren.len = 0;
906 if (ps.spaced_expr_psym != psym_0) { 901 if (ps.spaced_expr_psym != psym_0) {
907 parse(ps.spaced_expr_psym); 902 parse(ps.spaced_expr_psym);
908 ps.spaced_expr_psym = psym_0; 903 ps.spaced_expr_psym = psym_0;
909 } 904 }
910 } 905 }
911 buf_add_char(&code, ';'); 906 buf_add_char(&code, ';');
912 ps.want_blank = true; 907 ps.want_blank = true;
913 ps.in_stmt_or_decl = ps.paren.len > 0; 908 ps.in_stmt_or_decl = ps.paren.len > 0;
914 ps.decl_ind = 0; 909 ps.decl_ind = 0;
915 910
916 if (ps.spaced_expr_psym == psym_0) { 911 if (ps.spaced_expr_psym == psym_0) {
917 parse(psym_stmt); 912 parse(psym_stmt);
918 ps.force_nl = true; 913 ps.want_newline = true;
919 } 914 }
920} 915}
921 916
922static void 917static void
923process_type_outside_parentheses(void) 918process_type_outside_parentheses(void)
924{ 919{
925 parse(psym_decl); /* let the parser worry about indentation */ 920 parse(psym_decl); /* let the parser worry about indentation */
926 921
927 if (ps.prev_lsym == lsym_rparen && ps.psyms.len <= 2 && code.len > 0) 922 if (ps.prev_lsym == lsym_rparen && ps.psyms.len <= 2 && code.len > 0)
928 output_line(); 923 output_line();
929 924
930 if (ps.in_func_def_params && opt.indent_parameters && 925 if (ps.in_func_def_params && opt.indent_parameters &&
931 ps.decl_level == 0) { 926 ps.decl_level == 0) {
@@ -958,57 +953,57 @@ process_word(lexer_symbol lsym) @@ -958,57 +953,57 @@ process_word(lexer_symbol lsym)
958 buf_add_char(&code, ' '); 953 buf_add_char(&code, ' ');
959 ps.want_blank = false; 954 ps.want_blank = false;
960 955
961 } else if (!ps.in_init && !ps.decl_indent_done && 956 } else if (!ps.in_init && !ps.decl_indent_done &&
962 ps.ind_paren_level == 0) { 957 ps.ind_paren_level == 0) {
963 if (opt.decl_indent == 0 958 if (opt.decl_indent == 0
964 && code.len > 0 && code.s[code.len - 1] == '}') 959 && code.len > 0 && code.s[code.len - 1] == '}')
965 ps.decl_ind = ind_add(0, code.s, code.len) + 1; 960 ps.decl_ind = ind_add(0, code.s, code.len) + 1;
966 indent_declarator(ps.decl_ind, ps.tabs_to_var); 961 indent_declarator(ps.decl_ind, ps.tabs_to_var);
967 ps.want_blank = false; 962 ps.want_blank = false;
968 } 963 }
969 964
970 } else if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) { 965 } else if (ps.spaced_expr_psym != psym_0 && ps.paren.len == 0) {
971 ps.force_nl = true; 966 ps.want_newline = true;
972 ps.in_stmt_or_decl = false; 967 ps.in_stmt_or_decl = false;
973 ps.next_unary = true; 968 ps.next_unary = true;
974 parse(ps.spaced_expr_psym); 969 parse(ps.spaced_expr_psym);
975 ps.spaced_expr_psym = psym_0; 970 ps.spaced_expr_psym = psym_0;
976 } 971 }
977} 972}
978 973
979static void 974static void
980process_do(void) 975process_do(void)
981{ 976{
982 ps.in_stmt_or_decl = false; 977 ps.in_stmt_or_decl = false;
983 ps.in_decl = false; 978 ps.in_decl = false;
984 979
985 if (code.len > 0) 980 if (code.len > 0)
986 output_line(); 981 output_line();
987 982
988 ps.force_nl = true; 983 ps.want_newline = true;
989 parse(psym_do); 984 parse(psym_do);
990} 985}
991 986
992static void 987static void
993process_else(void) 988process_else(void)
994{ 989{
995 ps.in_stmt_or_decl = false; 990 ps.in_stmt_or_decl = false;
996 991
997 if (code.len > 0 992 if (code.len > 0
998 && !(opt.cuddle_else && code.s[code.len - 1] == '}')) 993 && !(opt.cuddle_else && code.s[code.len - 1] == '}'))
999 output_line(); 994 output_line();
1000 995
1001 ps.force_nl = true; 996 ps.want_newline = true;
1002 parse(psym_else); 997 parse(psym_else);
1003} 998}
1004 999
1005static void 1000static void
1006process_lsym(lexer_symbol lsym) 1001process_lsym(lexer_symbol lsym)
1007{ 1002{
1008 switch (lsym) { 1003 switch (lsym) {
1009 /* INDENT OFF */ 1004 /* INDENT OFF */
1010 case lsym_preprocessing: process_preprocessing(); break; 1005 case lsym_preprocessing: process_preprocessing(); break;
1011 case lsym_newline: process_newline(); break; 1006 case lsym_newline: process_newline(); break;
1012 case lsym_comment: process_comment(); break; 1007 case lsym_comment: process_comment(); break;
1013 case lsym_lparen: process_lparen(); break; 1008 case lsym_lparen: process_lparen(); break;
1014 case lsym_lbracket: process_lbracket(); break; 1009 case lsym_lbracket: process_lbracket(); break;
@@ -1075,35 +1070,35 @@ indent(void) @@ -1075,35 +1070,35 @@ indent(void)
1075 lexer_symbol lsym = lexi(); 1070 lexer_symbol lsym = lexi();
1076 1071
1077 debug_blank_line(); 1072 debug_blank_line();
1078 debug_printf("line %d: %s", line_no, lsym_name[lsym]); 1073 debug_printf("line %d: %s", line_no, lsym_name[lsym]);
1079 debug_print_buf("token", &token); 1074 debug_print_buf("token", &token);
1080 debug_buffers(); 1075 debug_buffers();
1081 debug_blank_line(); 1076 debug_blank_line();
1082 1077
1083 if (lsym == lsym_eof) 1078 if (lsym == lsym_eof)
1084 return process_eof(); 1079 return process_eof();
1085 1080
1086 if (lsym == lsym_if && ps.prev_lsym == lsym_else 1081 if (lsym == lsym_if && ps.prev_lsym == lsym_else
1087 && opt.else_if_in_same_line) 1082 && opt.else_if_in_same_line)
1088 ps.force_nl = false; 1083 ps.want_newline = false;
1089 1084
1090 if (lsym == lsym_preprocessing || lsym == lsym_newline) 1085 if (lsym == lsym_preprocessing || lsym == lsym_newline)
1091 ps.force_nl = false; 1086 ps.want_newline = false;
1092 else if (lsym == lsym_comment) { 1087 else if (lsym == lsym_comment) {
1093 /* no special processing */ 1088 /* no special processing */
1094 } else { 1089 } else {
1095 if (ps.force_nl && should_break_line(lsym)) { 1090 if (ps.want_newline && should_break_line(lsym)) {
1096 ps.force_nl = false; 1091 ps.want_newline = false;
1097 output_line(); 1092 output_line();
1098 } 1093 }
1099 ps.in_stmt_or_decl = true; 1094 ps.in_stmt_or_decl = true;
1100 if (com.len > 0) 1095 if (com.len > 0)
1101 move_com_to_code(lsym); 1096 move_com_to_code(lsym);
1102 update_ps_lbrace_kind(lsym); 1097 update_ps_lbrace_kind(lsym);
1103 } 1098 }
1104 1099
1105 process_lsym(lsym); 1100 process_lsym(lsym);
1106 1101
1107 if (lsym != lsym_preprocessing 1102 if (lsym != lsym_preprocessing
1108 && lsym != lsym_newline 1103 && lsym != lsym_newline
1109 && lsym != lsym_comment) 1104 && lsym != lsym_comment)

cvs diff -r1.196 -r1.197 src/usr.bin/indent/indent.h (expand / switch to unified diff)

--- src/usr.bin/indent/indent.h 2023/06/14 19:05:40 1.196
+++ src/usr.bin/indent/indent.h 2023/06/14 20:46:08 1.197
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: indent.h,v 1.196 2023/06/14 19:05:40 rillig Exp $ */ 1/* $NetBSD: indent.h,v 1.197 2023/06/14 20:46:08 rillig Exp $ */
2 2
3/*- 3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * 5 *
6 * Copyright (c) 2001 Jens Schweikhardt 6 * Copyright (c) 2001 Jens Schweikhardt
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -262,30 +262,30 @@ struct paren_level { @@ -262,30 +262,30 @@ struct paren_level {
262 int indent; /* indentation of the operand/argument, 262 int indent; /* indentation of the operand/argument,
263 * relative to the enclosing statement; if 263 * relative to the enclosing statement; if
264 * negative, reflected at -1 */ 264 * negative, reflected at -1 */
265 enum paren_level_cast { 265 enum paren_level_cast {
266 cast_unknown, 266 cast_unknown,
267 cast_maybe, 267 cast_maybe,
268 cast_no, 268 cast_no,
269 } cast; /* whether the parentheses form a type cast */ 269 } cast; /* whether the parentheses form a type cast */
270}; 270};
271 271
272struct psym_stack { 272struct psym_stack {
273 parser_symbol *sym; 273 parser_symbol *sym;
274 int *ind_level; 274 int *ind_level;
275 size_t len; /* points to one behind the top of the stack; 275 size_t len; /* points to one behind the top of the stack; 1
276 * 1 at the top level of the file outside a 276 * at the top level of the file outside a
277 * declaration or statement; 2 at the top 277 * declaration or statement; 2 at the top level
278 * level */ 278 */
279 size_t cap; 279 size_t cap;
280}; 280};
281 281
282/* 282/*
283 * The parser state determines the layout of the formatted text. 283 * The parser state determines the layout of the formatted text.
284 * 284 *
285 * At each '#if', the parser state is copied so that the corresponding '#else' 285 * At each '#if', the parser state is copied so that the corresponding '#else'
286 * lines start in the same state. 286 * lines start in the same state.
287 * 287 *
288 * In a function body, the number of block braces determines the indentation 288 * In a function body, the number of block braces determines the indentation
289 * of statements and declarations. 289 * of statements and declarations.
290 * 290 *
291 * In a statement, the number of parentheses or brackets determines the 291 * In a statement, the number of parentheses or brackets determines the
@@ -383,29 +383,29 @@ extern struct parser_state { @@ -383,29 +383,29 @@ extern struct parser_state {
383 383
384 /* Indentation of comments */ 384 /* Indentation of comments */
385 385
386 int comment_ind; /* indentation of the current comment */ 386 int comment_ind; /* indentation of the current comment */
387 int comment_shift; /* all but the first line of a boxed comment 387 int comment_shift; /* all but the first line of a boxed comment
388 * are shifted this much to the right */ 388 * are shifted this much to the right */
389 bool comment_in_first_line; 389 bool comment_in_first_line;
390 390
391 /* Vertical spacing */ 391 /* Vertical spacing */
392 392
393 bool break_after_comma; /* whether to add a newline after the next 393 bool break_after_comma; /* whether to add a newline after the next
394 * comma; used in declarations but not in 394 * comma; used in declarations but not in
395 * initializer lists */ 395 * initializer lists */
396 bool force_nl; /* whether the next token is forced to go to a 396 bool want_newline; /* whether the next token should go to a new
397 * new line; used after 'if (expr)' and in 397 * line; used after 'if (expr)' and in similar
398 * similar situations; tokens like '{' may 398 * situations; tokens like '{' or ';' may
399 * ignore this */ 399 * ignore this */
400 400
401 enum declaration { 401 enum declaration {
402 decl_no, /* no declaration anywhere nearby */ 402 decl_no, /* no declaration anywhere nearby */
403 decl_begin, /* collecting tokens of a declaration */ 403 decl_begin, /* collecting tokens of a declaration */
404 decl_end, /* finished a declaration */ 404 decl_end, /* finished a declaration */
405 } declaration; 405 } declaration;
406 bool blank_line_after_decl; 406 bool blank_line_after_decl;
407} ps; 407} ps;
408 408
409extern struct output_state { 409extern struct output_state {
410 enum line_kind { 410 enum line_kind {
411 lk_other, 411 lk_other,

cvs diff -r1.76 -r1.77 src/usr.bin/indent/parse.c (expand / switch to unified diff)

--- src/usr.bin/indent/parse.c 2023/06/14 19:05:40 1.76
+++ src/usr.bin/indent/parse.c 2023/06/14 20:46:08 1.77
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parse.c,v 1.76 2023/06/14 19:05:40 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.77 2023/06/14 20:46:08 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
@@ -28,40 +28,40 @@ @@ -28,40 +28,40 @@
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.76 2023/06/14 19:05:40 rillig Exp $"); 41__RCSID("$NetBSD: parse.c,v 1.77 2023/06/14 20:46:08 rillig Exp $");
42 42
43#include <err.h> 
44#include <stdlib.h> 43#include <stdlib.h>
45 44
46#include "indent.h" 45#include "indent.h"
47 46
48/* 47/*
49 * 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
50 * directly below it, replacing these two symbols with a single symbol. 49 * directly below it, replacing these two symbols with a single symbol.
51 */ 50 */
52static bool 51static bool
53psyms_reduce_stmt(struct psym_stack *psyms) 52psyms_reduce_stmt(void)
54{ 53{
 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;
@@ -95,46 +95,47 @@ decl_level(void) @@ -95,46 +95,47 @@ decl_level(void)
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
102void 102void
103ps_push(parser_symbol psym, bool follow) 103ps_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 */
122static void 122static void
123psyms_reduce(struct psym_stack *psyms) 123psyms_reduce(void)
124{ 124{
 125 struct psym_stack *psyms = &ps.psyms;
125again: 126again:
126 if (psyms->len >= 2 && psyms->sym[psyms->len - 1] == psym_stmt 127 if (psyms->len >= 2 && psyms->sym[psyms->len - 1] == psym_stmt
127 && psyms_reduce_stmt(psyms)) 128 && psyms_reduce_stmt())
128 goto again; 129 goto again;
129 if (psyms->sym[psyms->len - 1] == psym_while_expr && 130 if (psyms->sym[psyms->len - 1] == psym_while_expr &&
130 psyms->sym[psyms->len - 2] == psym_do_stmt) { 131 psyms->sym[psyms->len - 2] == psym_do_stmt) {
131 psyms->len -= 2; 132 psyms->len -= 2;
132 goto again; 133 goto again;
133 } 134 }
134} 135}
135 136
136static bool 137static bool
137is_lbrace(parser_symbol psym) 138is_lbrace(parser_symbol psym)
138{ 139{
139 return psym == psym_lbrace_block 140 return psym == psym_lbrace_block
140 || psym == psym_lbrace_struct 141 || psym == psym_lbrace_struct
@@ -146,27 +147,27 @@ is_lbrace(parser_symbol psym) @@ -146,27 +147,27 @@ is_lbrace(parser_symbol psym)
146 * 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
147 * previous tokens. 148 * previous tokens.
148 */ 149 */
149void 150void
150parse(parser_symbol psym) 151parse(parser_symbol psym)
151{ 152{
152 debug_blank_line(); 153 debug_blank_line();
153 debug_println("parse token: %s", psym_name[psym]); 154 debug_println("parse token: %s", psym_name[psym]);
154 155
155 struct psym_stack *psyms = &ps.psyms; 156 struct psym_stack *psyms = &ps.psyms;
156 if (psym != psym_else) { 157 if (psym != psym_else) {
157 while (psyms->sym[psyms->len - 1] == psym_if_expr_stmt) { 158 while (psyms->sym[psyms->len - 1] == psym_if_expr_stmt) {
158 psyms->sym[psyms->len - 1] = psym_stmt; 159 psyms->sym[psyms->len - 1] = psym_stmt;
159 psyms_reduce(&ps.psyms); 160 psyms_reduce();
160 } 161 }
161 } 162 }
162 163
163 switch (psym) { 164 switch (psym) {
164 165
165 case psym_lbrace_block: 166 case psym_lbrace_block:
166 case psym_lbrace_struct: 167 case psym_lbrace_struct:
167 case psym_lbrace_union: 168 case psym_lbrace_union:
168 case psym_lbrace_enum: 169 case psym_lbrace_enum:
169 ps.break_after_comma = false; 170 ps.break_after_comma = false;
170 if (psyms->sym[psyms->len - 1] == psym_decl 171 if (psyms->sym[psyms->len - 1] == psym_decl
171 || psyms->sym[psyms->len - 1] == psym_stmt) 172 || psyms->sym[psyms->len - 1] == psym_stmt)
172 ++ps.ind_level_follow; 173 ++ps.ind_level_follow;
@@ -176,27 +177,27 @@ parse(parser_symbol psym) @@ -176,27 +177,27 @@ parse(parser_symbol psym)
176 177
177 /* for a switch, brace should be two levels out from 178 /* for a switch, brace should be two levels out from
178 * the code */ 179 * the code */
179 if (psyms->sym[psyms->len - 1] == psym_switch_expr 180 if (psyms->sym[psyms->len - 1] == psym_switch_expr
180 && opt.case_indent >= 1.0F) 181 && opt.case_indent >= 1.0F)
181 --ps.ind_level; 182 --ps.ind_level;
182 } 183 }
183 184
184 ps_push(psym, false); 185 ps_push(psym, false);
185 ps_push(psym_stmt, true); 186 ps_push(psym_stmt, true);
186 break; 187 break;
187 188
188 case psym_rbrace: 189 case psym_rbrace:
189 /* stack should have <lbrace> <stmt> or <lbrace> <stmt_list> */ 190 /* stack should have <lbrace> <stmt> or <lbrace> <decl> */
190 if (!(psyms->len >= 2 191 if (!(psyms->len >= 2
191 && is_lbrace(psyms->sym[psyms->len - 2]))) { 192 && is_lbrace(psyms->sym[psyms->len - 2]))) {
192 diag(1, "Statement nesting error"); 193 diag(1, "Statement nesting error");
193 break; 194 break;
194 } 195 }
195 ps.ind_level = ps.ind_level_follow = 196 ps.ind_level = ps.ind_level_follow =
196 psyms->ind_level[psyms->len-- - 2]; 197 psyms->ind_level[psyms->len-- - 2];
197 psyms->sym[psyms->len - 1] = psym_stmt; 198 psyms->sym[psyms->len - 1] = psym_stmt;
198 break; 199 break;
199 200
200 case psym_decl: 201 case psym_decl:
201 if (psyms->sym[psyms->len - 1] == psym_decl) 202 if (psyms->sym[psyms->len - 1] == psym_decl)
202 break; /* only put one declaration onto stack */ 203 break; /* only put one declaration onto stack */
@@ -247,16 +248,16 @@ parse(parser_symbol psym) @@ -247,16 +248,16 @@ parse(parser_symbol psym)
247 ps_push(psym_while_expr, false); 248 ps_push(psym_while_expr, false);
248 } else { 249 } else {
249 ps_push(psym_while_expr, true); 250 ps_push(psym_while_expr, true);
250 ++ps.ind_level_follow; 251 ++ps.ind_level_follow;
251 } 252 }
252 break; 253 break;
253 254
254 default: 255 default:
255 diag(1, "Unknown code to parser"); 256 diag(1, "Unknown code to parser");
256 return; 257 return;
257 } 258 }
258 259
259 debug_psyms_stack("before reduction"); 260 debug_psyms_stack("before reduction");
260 psyms_reduce(&ps.psyms); 261 psyms_reduce();
261 debug_psyms_stack("after reduction"); 262 debug_psyms_stack("after reduction");
262} 263}