1 /*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 1985 Sun Microsystems, Inc.
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 #include <err.h>
40 #include <stdio.h>
41 #include "indent_globs.h"
42 #include "indent_codes.h"
43 #include "indent.h"
44
45 /* Globals */
46 int break_comma;
47 float case_ind;
48
49 static void reduce(void);
50
51 void
parse(int tk)52 parse(int tk) /* tk: the code for the construct scanned */
53 {
54 int i;
55
56 #ifdef debug
57 printf("%2d - %s\n", tk, token);
58 #endif
59
60 while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
61 /* true if we have an if without an else */
62 ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt
63 * reduction */
64 reduce(); /* see if this allows any reduction */
65 }
66
67
68 switch (tk) { /* go on and figure out what to do with the
69 * input */
70
71 case decl: /* scanned a declaration word */
72 ps.search_brace = opt.btype_2;
73 /* indicate that following brace should be on same line */
74 if (ps.p_stack[ps.tos] != decl) { /* only put one declaration
75 * onto stack */
76 break_comma = true; /* while in declaration, newline should be
77 * forced after comma */
78 ps.p_stack[++ps.tos] = decl;
79 ps.il[ps.tos] = ps.i_l_follow;
80
81 if (opt.ljust_decl) {/* only do if we want left justified
82 * declarations */
83 ps.ind_level = 0;
84 for (i = ps.tos - 1; i > 0; --i)
85 if (ps.p_stack[i] == decl)
86 ++ps.ind_level; /* indentation is number of
87 * declaration levels deep we are */
88 ps.i_l_follow = ps.ind_level;
89 }
90 }
91 break;
92
93 case ifstmt: /* scanned if (...) */
94 if (ps.p_stack[ps.tos] == elsehead && opt.else_if) /* "else if ..." */
95 /*
96 * Note that the stack pointer here is decremented, effectively
97 * reducing "else if" to "if". This saves a lot of stack space
98 * in case of a long "if-else-if ... else-if" sequence.
99 */
100 ps.i_l_follow = ps.il[ps.tos--];
101 /* the rest is the same as for dolit and forstmt */
102 /* FALLTHROUGH */
103 case dolit: /* 'do' */
104 case forstmt: /* for (...) */
105 ps.p_stack[++ps.tos] = tk;
106 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
107 ++ps.i_l_follow; /* subsequent statements should be indented 1 */
108 ps.search_brace = opt.btype_2;
109 break;
110
111 case lbrace: /* scanned { */
112 break_comma = false; /* don't break comma in an initial list */
113 if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
114 || ps.p_stack[ps.tos] == stmtl)
115 ++ps.i_l_follow; /* it is a random, isolated stmt group or a
116 * declaration */
117 else {
118 if (s_code == e_code) {
119 /*
120 * only do this if there is nothing on the line
121 */
122 --ps.ind_level;
123 /*
124 * it is a group as part of a while, for, etc.
125 */
126 if (ps.p_stack[ps.tos] == swstmt && opt.case_indent >= 1)
127 --ps.ind_level;
128 /*
129 * for a switch, brace should be two levels out from the code
130 */
131 }
132 }
133
134 ps.p_stack[++ps.tos] = lbrace;
135 ps.il[ps.tos] = ps.ind_level;
136 ps.p_stack[++ps.tos] = stmt;
137 /* allow null stmt between braces */
138 ps.il[ps.tos] = ps.i_l_follow;
139 break;
140
141 case whilestmt: /* scanned while (...) */
142 if (ps.p_stack[ps.tos] == dohead) {
143 /* it is matched with do stmt */
144 ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
145 ps.p_stack[++ps.tos] = whilestmt;
146 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
147 }
148 else { /* it is a while loop */
149 ps.p_stack[++ps.tos] = whilestmt;
150 ps.il[ps.tos] = ps.i_l_follow;
151 ++ps.i_l_follow;
152 ps.search_brace = opt.btype_2;
153 }
154
155 break;
156
157 case elselit: /* scanned an else */
158
159 if (ps.p_stack[ps.tos] != ifhead)
160 diag2(1, "Unmatched 'else'");
161 else {
162 ps.ind_level = ps.il[ps.tos]; /* indentation for else should
163 * be same as for if */
164 ps.i_l_follow = ps.ind_level + 1; /* everything following should
165 * be in 1 level */
166 ps.p_stack[ps.tos] = elsehead;
167 /* remember if with else */
168 ps.search_brace = opt.btype_2 | opt.else_if;
169 }
170 break;
171
172 case rbrace: /* scanned a } */
173 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
174 if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) {
175 ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
176 ps.p_stack[ps.tos] = stmt;
177 }
178 else
179 diag2(1, "Statement nesting error");
180 break;
181
182 case swstmt: /* had switch (...) */
183 ps.p_stack[++ps.tos] = swstmt;
184 ps.cstk[ps.tos] = case_ind;
185 /* save current case indent level */
186 ps.il[ps.tos] = ps.i_l_follow;
187 case_ind = ps.i_l_follow + opt.case_indent; /* cases should be one
188 * level down from
189 * switch */
190 ps.i_l_follow += opt.case_indent + 1; /* statements should be two
191 * levels in */
192 ps.search_brace = opt.btype_2;
193 break;
194
195 case semicolon: /* this indicates a simple stmt */
196 break_comma = false; /* turn off flag to break after commas in a
197 * declaration */
198 ps.p_stack[++ps.tos] = stmt;
199 ps.il[ps.tos] = ps.ind_level;
200 break;
201
202 default: /* this is an error */
203 diag2(1, "Unknown code to parser");
204 return;
205
206
207 } /* end of switch */
208
209 if (ps.tos >= STACKSIZE - 1)
210 errx(1, "Parser stack overflow");
211
212 reduce(); /* see if any reduction can be done */
213
214 #ifdef debug
215 for (i = 1; i <= ps.tos; ++i)
216 printf("(%d %d)", ps.p_stack[i], ps.il[i]);
217 printf("\n");
218 #endif
219
220 return;
221 }
222
223 /*
224 * NAME: reduce
225 *
226 * FUNCTION: Implements the reduce part of the parsing algorithm
227 *
228 * ALGORITHM: The following reductions are done. Reductions are repeated
229 * until no more are possible.
230 *
231 * Old TOS New TOS
232 * <stmt> <stmt> <stmtl>
233 * <stmtl> <stmt> <stmtl>
234 * do <stmt> "dostmt"
235 * if <stmt> "ifstmt"
236 * switch <stmt> <stmt>
237 * decl <stmt> <stmt>
238 * "ifelse" <stmt> <stmt>
239 * for <stmt> <stmt>
240 * while <stmt> <stmt>
241 * "dostmt" while <stmt>
242 *
243 * On each reduction, ps.i_l_follow (the indentation for the following line)
244 * is set to the indentation level associated with the old TOS.
245 *
246 * PARAMETERS: None
247 *
248 * RETURNS: Nothing
249 *
250 * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
251 *
252 * CALLS: None
253 *
254 * CALLED BY: parse
255 *
256 * HISTORY: initial coding November 1976 D A Willcox of CAC
257 *
258 */
259 /*----------------------------------------------*\
260 | REDUCTION PHASE |
261 \*----------------------------------------------*/
262 static void
reduce(void)263 reduce(void)
264 {
265 int i;
266
267 for (;;) { /* keep looping until there is nothing left to
268 * reduce */
269
270 switch (ps.p_stack[ps.tos]) {
271
272 case stmt:
273 switch (ps.p_stack[ps.tos - 1]) {
274
275 case stmt:
276 case stmtl:
277 /* stmtl stmt or stmt stmt */
278 ps.p_stack[--ps.tos] = stmtl;
279 break;
280
281 case dolit: /* <do> <stmt> */
282 ps.p_stack[--ps.tos] = dohead;
283 ps.i_l_follow = ps.il[ps.tos];
284 break;
285
286 case ifstmt:
287 /* <if> <stmt> */
288 ps.p_stack[--ps.tos] = ifhead;
289 for (i = ps.tos - 1;
290 (
291 ps.p_stack[i] != stmt
292 &&
293 ps.p_stack[i] != stmtl
294 &&
295 ps.p_stack[i] != lbrace
296 );
297 --i);
298 ps.i_l_follow = ps.il[i];
299 /*
300 * for the time being, we will assume that there is no else on
301 * this if, and set the indentation level accordingly. If an
302 * else is scanned, it will be fixed up later
303 */
304 break;
305
306 case swstmt:
307 /* <switch> <stmt> */
308 case_ind = ps.cstk[ps.tos - 1];
309 /* FALLTHROUGH */
310 case decl: /* finish of a declaration */
311 case elsehead:
312 /* <<if> <stmt> else> <stmt> */
313 case forstmt:
314 /* <for> <stmt> */
315 case whilestmt:
316 /* <while> <stmt> */
317 ps.p_stack[--ps.tos] = stmt;
318 ps.i_l_follow = ps.il[ps.tos];
319 break;
320
321 default: /* <anything else> <stmt> */
322 return;
323
324 } /* end of section for <stmt> on top of stack */
325 break;
326
327 case whilestmt: /* while (...) on top */
328 if (ps.p_stack[ps.tos - 1] == dohead) {
329 /* it is termination of a do while */
330 ps.tos -= 2;
331 break;
332 }
333 else
334 return;
335
336 default: /* anything else on top */
337 return;
338
339 }
340 }
341 }
342