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