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

Annotation of src/usr.bin/lex/nfa.c, Revision 1.1.1.1

1.1       deraadt     1: /* nfa - NFA construction routines */
                      2:
                      3: /*-
                      4:  * Copyright (c) 1990 The Regents of the University of California.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Vern Paxson.
                      9:  *
                     10:  * The United States Government has rights in this work pursuant
                     11:  * to contract no. DE-AC03-76SF00098 between the United States
                     12:  * Department of Energy and the University of California.
                     13:  *
                     14:  * Redistribution and use in source and binary forms are permitted provided
                     15:  * that: (1) source distributions retain this entire copyright notice and
                     16:  * comment, and (2) distributions including binaries display the following
                     17:  * acknowledgement:  ``This product includes software developed by the
                     18:  * University of California, Berkeley and its contributors'' in the
                     19:  * documentation or other materials provided with the distribution and in
                     20:  * all advertising materials mentioning features or use of this software.
                     21:  * Neither the name of the University nor the names of its contributors may
                     22:  * be used to endorse or promote products derived from this software without
                     23:  * specific prior written permission.
                     24:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     25:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     26:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     27:  */
                     28:
                     29: /* $Header: /a/cvsroot/src/usr.bin/lex/nfa.c,v 1.8 1995/05/05 05:35:38 jtc Exp $ */
                     30:
                     31: #include "flexdef.h"
                     32:
                     33:
                     34: /* declare functions that have forward references */
                     35:
                     36: int dupmachine PROTO((int));
                     37: void mkxtion PROTO((int, int));
                     38:
                     39:
                     40: /* add_accept - add an accepting state to a machine
                     41:  *
                     42:  * accepting_number becomes mach's accepting number.
                     43:  */
                     44:
                     45: void add_accept( mach, accepting_number )
                     46: int mach, accepting_number;
                     47:        {
                     48:        /* Hang the accepting number off an epsilon state.  if it is associated
                     49:         * with a state that has a non-epsilon out-transition, then the state
                     50:         * will accept BEFORE it makes that transition, i.e., one character
                     51:         * too soon.
                     52:         */
                     53:
                     54:        if ( transchar[finalst[mach]] == SYM_EPSILON )
                     55:                accptnum[finalst[mach]] = accepting_number;
                     56:
                     57:        else
                     58:                {
                     59:                int astate = mkstate( SYM_EPSILON );
                     60:                accptnum[astate] = accepting_number;
                     61:                (void) link_machines( mach, astate );
                     62:                }
                     63:        }
                     64:
                     65:
                     66: /* copysingl - make a given number of copies of a singleton machine
                     67:  *
                     68:  * synopsis
                     69:  *
                     70:  *   newsng = copysingl( singl, num );
                     71:  *
                     72:  *     newsng - a new singleton composed of num copies of singl
                     73:  *     singl  - a singleton machine
                     74:  *     num    - the number of copies of singl to be present in newsng
                     75:  */
                     76:
                     77: int copysingl( singl, num )
                     78: int singl, num;
                     79:        {
                     80:        int copy, i;
                     81:
                     82:        copy = mkstate( SYM_EPSILON );
                     83:
                     84:        for ( i = 1; i <= num; ++i )
                     85:                copy = link_machines( copy, dupmachine( singl ) );
                     86:
                     87:        return copy;
                     88:        }
                     89:
                     90:
                     91: /* dumpnfa - debugging routine to write out an nfa */
                     92:
                     93: void dumpnfa( state1 )
                     94: int state1;
                     95:
                     96:        {
                     97:        int sym, tsp1, tsp2, anum, ns;
                     98:
                     99:        fprintf( stderr,
                    100:        _( "\n\n********** beginning dump of nfa with start state %d\n" ),
                    101:                state1 );
                    102:
                    103:        /* We probably should loop starting at firstst[state1] and going to
                    104:         * lastst[state1], but they're not maintained properly when we "or"
                    105:         * all of the rules together.  So we use our knowledge that the machine
                    106:         * starts at state 1 and ends at lastnfa.
                    107:         */
                    108:
                    109:        /* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */
                    110:        for ( ns = 1; ns <= lastnfa; ++ns )
                    111:                {
                    112:                fprintf( stderr, _( "state # %4d\t" ), ns );
                    113:
                    114:                sym = transchar[ns];
                    115:                tsp1 = trans1[ns];
                    116:                tsp2 = trans2[ns];
                    117:                anum = accptnum[ns];
                    118:
                    119:                fprintf( stderr, "%3d:  %4d, %4d", sym, tsp1, tsp2 );
                    120:
                    121:                if ( anum != NIL )
                    122:                        fprintf( stderr, "  [%d]", anum );
                    123:
                    124:                fprintf( stderr, "\n" );
                    125:                }
                    126:
                    127:        fprintf( stderr, _( "********** end of dump\n" ) );
                    128:        }
                    129:
                    130:
                    131: /* dupmachine - make a duplicate of a given machine
                    132:  *
                    133:  * synopsis
                    134:  *
                    135:  *   copy = dupmachine( mach );
                    136:  *
                    137:  *     copy - holds duplicate of mach
                    138:  *     mach - machine to be duplicated
                    139:  *
                    140:  * note that the copy of mach is NOT an exact duplicate; rather, all the
                    141:  * transition states values are adjusted so that the copy is self-contained,
                    142:  * as the original should have been.
                    143:  *
                    144:  * also note that the original MUST be contiguous, with its low and high
                    145:  * states accessible by the arrays firstst and lastst
                    146:  */
                    147:
                    148: int dupmachine( mach )
                    149: int mach;
                    150:        {
                    151:        int i, init, state_offset;
                    152:        int state = 0;
                    153:        int last = lastst[mach];
                    154:
                    155:        for ( i = firstst[mach]; i <= last; ++i )
                    156:                {
                    157:                state = mkstate( transchar[i] );
                    158:
                    159:                if ( trans1[i] != NO_TRANSITION )
                    160:                        {
                    161:                        mkxtion( finalst[state], trans1[i] + state - i );
                    162:
                    163:                        if ( transchar[i] == SYM_EPSILON &&
                    164:                             trans2[i] != NO_TRANSITION )
                    165:                                mkxtion( finalst[state],
                    166:                                        trans2[i] + state - i );
                    167:                        }
                    168:
                    169:                accptnum[state] = accptnum[i];
                    170:                }
                    171:
                    172:        if ( state == 0 )
                    173:                flexfatal( _( "empty machine in dupmachine()" ) );
                    174:
                    175:        state_offset = state - i + 1;
                    176:
                    177:        init = mach + state_offset;
                    178:        firstst[init] = firstst[mach] + state_offset;
                    179:        finalst[init] = finalst[mach] + state_offset;
                    180:        lastst[init] = lastst[mach] + state_offset;
                    181:
                    182:        return init;
                    183:        }
                    184:
                    185:
                    186: /* finish_rule - finish up the processing for a rule
                    187:  *
                    188:  * An accepting number is added to the given machine.  If variable_trail_rule
                    189:  * is true then the rule has trailing context and both the head and trail
                    190:  * are variable size.  Otherwise if headcnt or trailcnt is non-zero then
                    191:  * the machine recognizes a pattern with trailing context and headcnt is
                    192:  * the number of characters in the matched part of the pattern, or zero
                    193:  * if the matched part has variable length.  trailcnt is the number of
                    194:  * trailing context characters in the pattern, or zero if the trailing
                    195:  * context has variable length.
                    196:  */
                    197:
                    198: void finish_rule( mach, variable_trail_rule, headcnt, trailcnt )
                    199: int mach, variable_trail_rule, headcnt, trailcnt;
                    200:        {
                    201:        char action_text[MAXLINE];
                    202:
                    203:        add_accept( mach, num_rules );
                    204:
                    205:        /* We did this in new_rule(), but it often gets the wrong
                    206:         * number because we do it before we start parsing the current rule.
                    207:         */
                    208:        rule_linenum[num_rules] = linenum;
                    209:
                    210:        /* If this is a continued action, then the line-number has already
                    211:         * been updated, giving us the wrong number.
                    212:         */
                    213:        if ( continued_action )
                    214:                --rule_linenum[num_rules];
                    215:
                    216:        sprintf( action_text, "case %d:\n", num_rules );
                    217:        add_action( action_text );
                    218:
                    219:        if ( variable_trail_rule )
                    220:                {
                    221:                rule_type[num_rules] = RULE_VARIABLE;
                    222:
                    223:                if ( performance_report > 0 )
                    224:                        fprintf( stderr,
                    225:                        _( "Variable trailing context rule at line %d\n" ),
                    226:                                rule_linenum[num_rules] );
                    227:
                    228:                variable_trailing_context_rules = true;
                    229:                }
                    230:
                    231:        else
                    232:                {
                    233:                rule_type[num_rules] = RULE_NORMAL;
                    234:
                    235:                if ( headcnt > 0 || trailcnt > 0 )
                    236:                        {
                    237:                        /* Do trailing context magic to not match the trailing
                    238:                         * characters.
                    239:                         */
                    240:                        char *scanner_cp = "yy_c_buf_p = yy_cp";
                    241:                        char *scanner_bp = "yy_bp";
                    242:
                    243:                        add_action(
                    244:        "*yy_cp = yy_hold_char; /* undo effects of setting up yytext */\n" );
                    245:
                    246:                        if ( headcnt > 0 )
                    247:                                {
                    248:                                sprintf( action_text, "%s = %s + %d;\n",
                    249:                                scanner_cp, scanner_bp, headcnt );
                    250:                                add_action( action_text );
                    251:                                }
                    252:
                    253:                        else
                    254:                                {
                    255:                                sprintf( action_text, "%s -= %d;\n",
                    256:                                        scanner_cp, trailcnt );
                    257:                                add_action( action_text );
                    258:                                }
                    259:
                    260:                        add_action(
                    261:                        "YY_DO_BEFORE_ACTION; /* set up yytext again */\n" );
                    262:                        }
                    263:                }
                    264:
                    265:        /* Okay, in the action code at this point yytext and yyleng have
                    266:         * their proper final values for this rule, so here's the point
                    267:         * to do any user action.  But don't do it for continued actions,
                    268:         * as that'll result in multiple YY_RULE_SETUP's.
                    269:         */
                    270:        if ( ! continued_action )
                    271:                add_action( "YY_RULE_SETUP\n" );
                    272:
                    273:        line_directive_out( (FILE *) 0, 1 );
                    274:        }
                    275:
                    276:
                    277: /* link_machines - connect two machines together
                    278:  *
                    279:  * synopsis
                    280:  *
                    281:  *   new = link_machines( first, last );
                    282:  *
                    283:  *     new    - a machine constructed by connecting first to last
                    284:  *     first  - the machine whose successor is to be last
                    285:  *     last   - the machine whose predecessor is to be first
                    286:  *
                    287:  * note: this routine concatenates the machine first with the machine
                    288:  *  last to produce a machine new which will pattern-match first first
                    289:  *  and then last, and will fail if either of the sub-patterns fails.
                    290:  *  FIRST is set to new by the operation.  last is unmolested.
                    291:  */
                    292:
                    293: int link_machines( first, last )
                    294: int first, last;
                    295:        {
                    296:        if ( first == NIL )
                    297:                return last;
                    298:
                    299:        else if ( last == NIL )
                    300:                return first;
                    301:
                    302:        else
                    303:                {
                    304:                mkxtion( finalst[first], last );
                    305:                finalst[first] = finalst[last];
                    306:                lastst[first] = MAX( lastst[first], lastst[last] );
                    307:                firstst[first] = MIN( firstst[first], firstst[last] );
                    308:
                    309:                return first;
                    310:                }
                    311:        }
                    312:
                    313:
                    314: /* mark_beginning_as_normal - mark each "beginning" state in a machine
                    315:  *                            as being a "normal" (i.e., not trailing context-
                    316:  *                            associated) states
                    317:  *
                    318:  * The "beginning" states are the epsilon closure of the first state
                    319:  */
                    320:
                    321: void mark_beginning_as_normal( mach )
                    322: register int mach;
                    323:        {
                    324:        switch ( state_type[mach] )
                    325:                {
                    326:                case STATE_NORMAL:
                    327:                        /* Oh, we've already visited here. */
                    328:                        return;
                    329:
                    330:                case STATE_TRAILING_CONTEXT:
                    331:                        state_type[mach] = STATE_NORMAL;
                    332:
                    333:                        if ( transchar[mach] == SYM_EPSILON )
                    334:                                {
                    335:                                if ( trans1[mach] != NO_TRANSITION )
                    336:                                        mark_beginning_as_normal(
                    337:                                                trans1[mach] );
                    338:
                    339:                                if ( trans2[mach] != NO_TRANSITION )
                    340:                                        mark_beginning_as_normal(
                    341:                                                trans2[mach] );
                    342:                                }
                    343:                        break;
                    344:
                    345:                default:
                    346:                        flexerror(
                    347:                        _( "bad state type in mark_beginning_as_normal()" ) );
                    348:                        break;
                    349:                }
                    350:        }
                    351:
                    352:
                    353: /* mkbranch - make a machine that branches to two machines
                    354:  *
                    355:  * synopsis
                    356:  *
                    357:  *   branch = mkbranch( first, second );
                    358:  *
                    359:  *     branch - a machine which matches either first's pattern or second's
                    360:  *     first, second - machines whose patterns are to be or'ed (the | operator)
                    361:  *
                    362:  * Note that first and second are NEITHER destroyed by the operation.  Also,
                    363:  * the resulting machine CANNOT be used with any other "mk" operation except
                    364:  * more mkbranch's.  Compare with mkor()
                    365:  */
                    366:
                    367: int mkbranch( first, second )
                    368: int first, second;
                    369:        {
                    370:        int eps;
                    371:
                    372:        if ( first == NO_TRANSITION )
                    373:                return second;
                    374:
                    375:        else if ( second == NO_TRANSITION )
                    376:                return first;
                    377:
                    378:        eps = mkstate( SYM_EPSILON );
                    379:
                    380:        mkxtion( eps, first );
                    381:        mkxtion( eps, second );
                    382:
                    383:        return eps;
                    384:        }
                    385:
                    386:
                    387: /* mkclos - convert a machine into a closure
                    388:  *
                    389:  * synopsis
                    390:  *   new = mkclos( state );
                    391:  *
                    392:  * new - a new state which matches the closure of "state"
                    393:  */
                    394:
                    395: int mkclos( state )
                    396: int state;
                    397:        {
                    398:        return mkopt( mkposcl( state ) );
                    399:        }
                    400:
                    401:
                    402: /* mkopt - make a machine optional
                    403:  *
                    404:  * synopsis
                    405:  *
                    406:  *   new = mkopt( mach );
                    407:  *
                    408:  *     new  - a machine which optionally matches whatever mach matched
                    409:  *     mach - the machine to make optional
                    410:  *
                    411:  * notes:
                    412:  *     1. mach must be the last machine created
                    413:  *     2. mach is destroyed by the call
                    414:  */
                    415:
                    416: int mkopt( mach )
                    417: int mach;
                    418:        {
                    419:        int eps;
                    420:
                    421:        if ( ! SUPER_FREE_EPSILON(finalst[mach]) )
                    422:                {
                    423:                eps = mkstate( SYM_EPSILON );
                    424:                mach = link_machines( mach, eps );
                    425:                }
                    426:
                    427:        /* Can't skimp on the following if FREE_EPSILON(mach) is true because
                    428:         * some state interior to "mach" might point back to the beginning
                    429:         * for a closure.
                    430:         */
                    431:        eps = mkstate( SYM_EPSILON );
                    432:        mach = link_machines( eps, mach );
                    433:
                    434:        mkxtion( mach, finalst[mach] );
                    435:
                    436:        return mach;
                    437:        }
                    438:
                    439:
                    440: /* mkor - make a machine that matches either one of two machines
                    441:  *
                    442:  * synopsis
                    443:  *
                    444:  *   new = mkor( first, second );
                    445:  *
                    446:  *     new - a machine which matches either first's pattern or second's
                    447:  *     first, second - machines whose patterns are to be or'ed (the | operator)
                    448:  *
                    449:  * note that first and second are both destroyed by the operation
                    450:  * the code is rather convoluted because an attempt is made to minimize
                    451:  * the number of epsilon states needed
                    452:  */
                    453:
                    454: int mkor( first, second )
                    455: int first, second;
                    456:        {
                    457:        int eps, orend;
                    458:
                    459:        if ( first == NIL )
                    460:                return second;
                    461:
                    462:        else if ( second == NIL )
                    463:                return first;
                    464:
                    465:        else
                    466:                {
                    467:                /* See comment in mkopt() about why we can't use the first
                    468:                 * state of "first" or "second" if they satisfy "FREE_EPSILON".
                    469:                 */
                    470:                eps = mkstate( SYM_EPSILON );
                    471:
                    472:                first = link_machines( eps, first );
                    473:
                    474:                mkxtion( first, second );
                    475:
                    476:                if ( SUPER_FREE_EPSILON(finalst[first]) &&
                    477:                     accptnum[finalst[first]] == NIL )
                    478:                        {
                    479:                        orend = finalst[first];
                    480:                        mkxtion( finalst[second], orend );
                    481:                        }
                    482:
                    483:                else if ( SUPER_FREE_EPSILON(finalst[second]) &&
                    484:                          accptnum[finalst[second]] == NIL )
                    485:                        {
                    486:                        orend = finalst[second];
                    487:                        mkxtion( finalst[first], orend );
                    488:                        }
                    489:
                    490:                else
                    491:                        {
                    492:                        eps = mkstate( SYM_EPSILON );
                    493:
                    494:                        first = link_machines( first, eps );
                    495:                        orend = finalst[first];
                    496:
                    497:                        mkxtion( finalst[second], orend );
                    498:                        }
                    499:                }
                    500:
                    501:        finalst[first] = orend;
                    502:        return first;
                    503:        }
                    504:
                    505:
                    506: /* mkposcl - convert a machine into a positive closure
                    507:  *
                    508:  * synopsis
                    509:  *   new = mkposcl( state );
                    510:  *
                    511:  *    new - a machine matching the positive closure of "state"
                    512:  */
                    513:
                    514: int mkposcl( state )
                    515: int state;
                    516:        {
                    517:        int eps;
                    518:
                    519:        if ( SUPER_FREE_EPSILON(finalst[state]) )
                    520:                {
                    521:                mkxtion( finalst[state], state );
                    522:                return state;
                    523:                }
                    524:
                    525:        else
                    526:                {
                    527:                eps = mkstate( SYM_EPSILON );
                    528:                mkxtion( eps, state );
                    529:                return link_machines( state, eps );
                    530:                }
                    531:        }
                    532:
                    533:
                    534: /* mkrep - make a replicated machine
                    535:  *
                    536:  * synopsis
                    537:  *   new = mkrep( mach, lb, ub );
                    538:  *
                    539:  *    new - a machine that matches whatever "mach" matched from "lb"
                    540:  *          number of times to "ub" number of times
                    541:  *
                    542:  * note
                    543:  *   if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach"
                    544:  */
                    545:
                    546: int mkrep( mach, lb, ub )
                    547: int mach, lb, ub;
                    548:        {
                    549:        int base_mach, tail, copy, i;
                    550:
                    551:        base_mach = copysingl( mach, lb - 1 );
                    552:
                    553:        if ( ub == INFINITY )
                    554:                {
                    555:                copy = dupmachine( mach );
                    556:                mach = link_machines( mach,
                    557:                link_machines( base_mach, mkclos( copy ) ) );
                    558:                }
                    559:
                    560:        else
                    561:                {
                    562:                tail = mkstate( SYM_EPSILON );
                    563:
                    564:                for ( i = lb; i < ub; ++i )
                    565:                        {
                    566:                        copy = dupmachine( mach );
                    567:                        tail = mkopt( link_machines( copy, tail ) );
                    568:                        }
                    569:
                    570:                mach = link_machines( mach, link_machines( base_mach, tail ) );
                    571:                }
                    572:
                    573:        return mach;
                    574:        }
                    575:
                    576:
                    577: /* mkstate - create a state with a transition on a given symbol
                    578:  *
                    579:  * synopsis
                    580:  *
                    581:  *   state = mkstate( sym );
                    582:  *
                    583:  *     state - a new state matching sym
                    584:  *     sym   - the symbol the new state is to have an out-transition on
                    585:  *
                    586:  * note that this routine makes new states in ascending order through the
                    587:  * state array (and increments LASTNFA accordingly).  The routine DUPMACHINE
                    588:  * relies on machines being made in ascending order and that they are
                    589:  * CONTIGUOUS.  Change it and you will have to rewrite DUPMACHINE (kludge
                    590:  * that it admittedly is)
                    591:  */
                    592:
                    593: int mkstate( sym )
                    594: int sym;
                    595:        {
                    596:        if ( ++lastnfa >= current_mns )
                    597:                {
                    598:                if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS )
                    599:                        lerrif(
                    600:                _( "input rules are too complicated (>= %d NFA states)" ),
                    601:                                current_mns );
                    602:
                    603:                ++num_reallocs;
                    604:
                    605:                firstst = reallocate_integer_array( firstst, current_mns );
                    606:                lastst = reallocate_integer_array( lastst, current_mns );
                    607:                finalst = reallocate_integer_array( finalst, current_mns );
                    608:                transchar = reallocate_integer_array( transchar, current_mns );
                    609:                trans1 = reallocate_integer_array( trans1, current_mns );
                    610:                trans2 = reallocate_integer_array( trans2, current_mns );
                    611:                accptnum = reallocate_integer_array( accptnum, current_mns );
                    612:                assoc_rule =
                    613:                        reallocate_integer_array( assoc_rule, current_mns );
                    614:                state_type =
                    615:                        reallocate_integer_array( state_type, current_mns );
                    616:                }
                    617:
                    618:        firstst[lastnfa] = lastnfa;
                    619:        finalst[lastnfa] = lastnfa;
                    620:        lastst[lastnfa] = lastnfa;
                    621:        transchar[lastnfa] = sym;
                    622:        trans1[lastnfa] = NO_TRANSITION;
                    623:        trans2[lastnfa] = NO_TRANSITION;
                    624:        accptnum[lastnfa] = NIL;
                    625:        assoc_rule[lastnfa] = num_rules;
                    626:        state_type[lastnfa] = current_state_type;
                    627:
                    628:        /* Fix up equivalence classes base on this transition.  Note that any
                    629:         * character which has its own transition gets its own equivalence
                    630:         * class.  Thus only characters which are only in character classes
                    631:         * have a chance at being in the same equivalence class.  E.g. "a|b"
                    632:         * puts 'a' and 'b' into two different equivalence classes.  "[ab]"
                    633:         * puts them in the same equivalence class (barring other differences
                    634:         * elsewhere in the input).
                    635:         */
                    636:
                    637:        if ( sym < 0 )
                    638:                {
                    639:                /* We don't have to update the equivalence classes since
                    640:                 * that was already done when the ccl was created for the
                    641:                 * first time.
                    642:                 */
                    643:                }
                    644:
                    645:        else if ( sym == SYM_EPSILON )
                    646:                ++numeps;
                    647:
                    648:        else
                    649:                {
                    650:                check_char( sym );
                    651:
                    652:                if ( useecs )
                    653:                        /* Map NUL's to csize. */
                    654:                        mkechar( sym ? sym : csize, nextecm, ecgroup );
                    655:                }
                    656:
                    657:        return lastnfa;
                    658:        }
                    659:
                    660:
                    661: /* mkxtion - make a transition from one state to another
                    662:  *
                    663:  * synopsis
                    664:  *
                    665:  *   mkxtion( statefrom, stateto );
                    666:  *
                    667:  *     statefrom - the state from which the transition is to be made
                    668:  *     stateto   - the state to which the transition is to be made
                    669:  */
                    670:
                    671: void mkxtion( statefrom, stateto )
                    672: int statefrom, stateto;
                    673:        {
                    674:        if ( trans1[statefrom] == NO_TRANSITION )
                    675:                trans1[statefrom] = stateto;
                    676:
                    677:        else if ( (transchar[statefrom] != SYM_EPSILON) ||
                    678:                  (trans2[statefrom] != NO_TRANSITION) )
                    679:                flexfatal( _( "found too many transitions in mkxtion()" ) );
                    680:
                    681:        else
                    682:                { /* second out-transition for an epsilon state */
                    683:                ++eps2;
                    684:                trans2[statefrom] = stateto;
                    685:                }
                    686:        }
                    687:
                    688: /* new_rule - initialize for a new rule */
                    689:
                    690: void new_rule()
                    691:        {
                    692:        if ( ++num_rules >= current_max_rules )
                    693:                {
                    694:                ++num_reallocs;
                    695:                current_max_rules += MAX_RULES_INCREMENT;
                    696:                rule_type = reallocate_integer_array( rule_type,
                    697:                                                        current_max_rules );
                    698:                rule_linenum = reallocate_integer_array( rule_linenum,
                    699:                                                        current_max_rules );
                    700:                rule_useful = reallocate_integer_array( rule_useful,
                    701:                                                        current_max_rules );
                    702:                }
                    703:
                    704:        if ( num_rules > MAX_RULE )
                    705:                lerrif( _( "too many rules (> %d)!" ), MAX_RULE );
                    706:
                    707:        rule_linenum[num_rules] = linenum;
                    708:        rule_useful[num_rules] = false;
                    709:        }