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 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 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