[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / indent

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