Annotation of 43BSDReno/pgrm/lex/nfa.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.