Annotation of src/usr.bin/indent/parse.c, Revision 1.7
1.7 ! deraadt 1: /* $OpenBSD: parse.c,v 1.6 2003/06/12 01:07:27 deraadt Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /*
1.4 pjanzen 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.
1.1 deraadt 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.
1.6 deraadt 18: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 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: #ifndef lint
1.4 pjanzen 36: /*static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93";*/
1.7 ! deraadt 37: static char rcsid[] = "$OpenBSD: parse.c,v 1.6 2003/06/12 01:07:27 deraadt Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
40: #include <stdio.h>
41: #include "indent_globs.h"
42: #include "indent_codes.h"
43:
1.7 ! deraadt 44: void reduce(void);
1.3 mickey 45:
46: void
1.1 deraadt 47: parse(tk)
48: int tk; /* the code for the construct scanned */
49: {
50: int i;
51:
52: #ifdef debug
53: printf("%2d - %s\n", tk, token);
54: #endif
55:
56: while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
57: /* true if we have an if without an else */
58: ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt
59: * reduction */
60: reduce(); /* see if this allows any reduction */
61: }
62:
63:
64: switch (tk) { /* go on and figure out what to do with the
65: * input */
66:
67: case decl: /* scanned a declaration word */
68: ps.search_brace = btype_2;
69: /* indicate that following brace should be on same line */
70: if (ps.p_stack[ps.tos] != decl) { /* only put one declaration
71: * onto stack */
72: break_comma = true; /* while in declaration, newline should be
73: * forced after comma */
74: ps.p_stack[++ps.tos] = decl;
75: ps.il[ps.tos] = ps.i_l_follow;
76:
77: if (ps.ljust_decl) {/* only do if we want left justified
78: * declarations */
79: ps.ind_level = 0;
80: for (i = ps.tos - 1; i > 0; --i)
81: if (ps.p_stack[i] == decl)
82: ++ps.ind_level; /* indentation is number of
83: * declaration levels deep we are */
84: ps.i_l_follow = ps.ind_level;
85: }
86: }
87: break;
88:
89: case ifstmt: /* scanned if (...) */
90: if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */
91: ps.i_l_follow = ps.il[ps.tos];
92: case dolit: /* 'do' */
93: case forstmt: /* for (...) */
94: ps.p_stack[++ps.tos] = tk;
95: ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
96: ++ps.i_l_follow; /* subsequent statements should be indented 1 */
97: ps.search_brace = btype_2;
98: break;
99:
100: case lbrace: /* scanned { */
101: break_comma = false; /* don't break comma in an initial list */
102: if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
103: || ps.p_stack[ps.tos] == stmtl)
104: ++ps.i_l_follow; /* it is a random, isolated stmt group or a
105: * declaration */
106: else {
107: if (s_code == e_code) {
108: /*
109: * only do this if there is nothing on the line
110: */
111: --ps.ind_level;
112: /*
113: * it is a group as part of a while, for, etc.
114: */
115: if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
116: --ps.ind_level;
117: /*
118: * for a switch, brace should be two levels out from the code
119: */
120: }
121: }
122:
123: ps.p_stack[++ps.tos] = lbrace;
124: ps.il[ps.tos] = ps.ind_level;
125: ps.p_stack[++ps.tos] = stmt;
126: /* allow null stmt between braces */
127: ps.il[ps.tos] = ps.i_l_follow;
128: break;
129:
130: case whilestmt: /* scanned while (...) */
131: if (ps.p_stack[ps.tos] == dohead) {
132: /* it is matched with do stmt */
133: ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
134: ps.p_stack[++ps.tos] = whilestmt;
135: ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
136: }
137: else { /* it is a while loop */
138: ps.p_stack[++ps.tos] = whilestmt;
139: ps.il[ps.tos] = ps.i_l_follow;
140: ++ps.i_l_follow;
141: ps.search_brace = btype_2;
142: }
143:
144: break;
145:
146: case elselit: /* scanned an else */
147:
148: if (ps.p_stack[ps.tos] != ifhead)
149: diag(1, "Unmatched 'else'");
150: else {
151: ps.ind_level = ps.il[ps.tos]; /* indentation for else should
152: * be same as for if */
153: ps.i_l_follow = ps.ind_level + 1; /* everything following should
154: * be in 1 level */
155: ps.p_stack[ps.tos] = elsehead;
156: /* remember if with else */
157: ps.search_brace = btype_2 | ps.else_if;
158: }
159: break;
160:
161: case rbrace: /* scanned a } */
162: /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
163: if (ps.p_stack[ps.tos - 1] == lbrace) {
164: ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
165: ps.p_stack[ps.tos] = stmt;
166: }
167: else
168: diag(1, "Stmt nesting error.");
169: break;
170:
171: case swstmt: /* had switch (...) */
172: ps.p_stack[++ps.tos] = swstmt;
173: ps.cstk[ps.tos] = case_ind;
174: /* save current case indent level */
175: ps.il[ps.tos] = ps.i_l_follow;
176: case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one
177: * level down from
178: * switch */
179: ps.i_l_follow += ps.case_indent + 1; /* statements should be two
180: * levels in */
181: ps.search_brace = btype_2;
182: break;
183:
184: case semicolon: /* this indicates a simple stmt */
185: break_comma = false; /* turn off flag to break after commas in a
186: * declaration */
187: ps.p_stack[++ps.tos] = stmt;
188: ps.il[ps.tos] = ps.ind_level;
189: break;
190:
191: default: /* this is an error */
192: diag(1, "Unknown code to parser");
193: return;
194:
195:
196: } /* end of switch */
197:
198: reduce(); /* see if any reduction can be done */
199:
200: #ifdef debug
201: for (i = 1; i <= ps.tos; ++i)
202: printf("(%d %d)", ps.p_stack[i], ps.il[i]);
203: printf("\n");
204: #endif
205:
206: return;
207: }
208:
209: /*
210: * NAME: reduce
1.4 pjanzen 211: *
1.1 deraadt 212: * FUNCTION: Implements the reduce part of the parsing algorithm
1.4 pjanzen 213: *
1.1 deraadt 214: * ALGORITHM: The following reductions are done. Reductions are repeated
215: * until no more are possible.
1.4 pjanzen 216: *
1.1 deraadt 217: * Old TOS New TOS
218: * <stmt> <stmt> <stmtl>
219: * <stmtl> <stmt> <stmtl>
220: * do <stmt> "dostmt"
221: * if <stmt> "ifstmt"
222: * switch <stmt> <stmt>
223: * decl <stmt> <stmt>
224: * "ifelse" <stmt> <stmt>
225: * for <stmt> <stmt>
226: * while <stmt> <stmt>
227: * "dostmt" while <stmt>
1.4 pjanzen 228: *
1.1 deraadt 229: * On each reduction, ps.i_l_follow (the indentation for the following line)
230: * is set to the indentation level associated with the old TOS.
1.4 pjanzen 231: *
1.1 deraadt 232: * PARAMETERS: None
1.4 pjanzen 233: *
1.1 deraadt 234: * RETURNS: Nothing
1.4 pjanzen 235: *
1.1 deraadt 236: * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
1.4 pjanzen 237: *
1.1 deraadt 238: * CALLS: None
1.4 pjanzen 239: *
1.1 deraadt 240: * CALLED BY: parse
1.4 pjanzen 241: *
1.1 deraadt 242: * HISTORY: initial coding November 1976 D A Willcox of CAC
1.4 pjanzen 243: *
1.1 deraadt 244: */
245: /*----------------------------------------------*\
246: | REDUCTION PHASE |
247: \*----------------------------------------------*/
1.3 mickey 248: void
1.7 ! deraadt 249: reduce(void)
1.1 deraadt 250: {
251:
1.5 mpech 252: int i;
1.1 deraadt 253:
254: for (;;) { /* keep looping until there is nothing left to
255: * reduce */
256:
257: switch (ps.p_stack[ps.tos]) {
258:
259: case stmt:
260: switch (ps.p_stack[ps.tos - 1]) {
261:
262: case stmt:
263: case stmtl:
264: /* stmtl stmt or stmt stmt */
265: ps.p_stack[--ps.tos] = stmtl;
266: break;
267:
268: case dolit: /* <do> <stmt> */
269: ps.p_stack[--ps.tos] = dohead;
270: ps.i_l_follow = ps.il[ps.tos];
271: break;
272:
273: case ifstmt:
274: /* <if> <stmt> */
275: ps.p_stack[--ps.tos] = ifhead;
276: for (i = ps.tos - 1;
277: (
278: ps.p_stack[i] != stmt
279: &&
280: ps.p_stack[i] != stmtl
281: &&
282: ps.p_stack[i] != lbrace
283: );
284: --i);
285: ps.i_l_follow = ps.il[i];
286: /*
287: * for the time being, we will assume that there is no else on
288: * this if, and set the indentation level accordingly. If an
289: * else is scanned, it will be fixed up later
290: */
291: break;
292:
293: case swstmt:
294: /* <switch> <stmt> */
295: case_ind = ps.cstk[ps.tos - 1];
296:
297: case decl: /* finish of a declaration */
298: case elsehead:
299: /* <<if> <stmt> else> <stmt> */
300: case forstmt:
301: /* <for> <stmt> */
302: case whilestmt:
303: /* <while> <stmt> */
304: ps.p_stack[--ps.tos] = stmt;
305: ps.i_l_follow = ps.il[ps.tos];
306: break;
307:
308: default: /* <anything else> <stmt> */
309: return;
310:
311: } /* end of section for <stmt> on top of stack */
312: break;
313:
314: case whilestmt: /* while (...) on top */
315: if (ps.p_stack[ps.tos - 1] == dohead) {
316: /* it is termination of a do while */
317: ps.p_stack[--ps.tos] = stmt;
318: break;
319: }
320: else
321: return;
322:
323: default: /* anything else on top */
324: return;
325:
326: }
327: }
328: }