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