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