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

Annotation of src/usr.bin/lex/parse.y, Revision 1.7

1.7     ! deraadt     1: /*     $OpenBSD: parse.y,v 1.5 2002/05/30 10:53:45 deraadt Exp $       */
1.2       deraadt     2:
1.1       deraadt     3: /* parse.y - parser for flex input */
                      4:
                      5: %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
                      6: %token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
                      7:
                      8: %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
                      9: %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
                     10:
                     11: %{
                     12: /*-
                     13:  * Copyright (c) 1990 The Regents of the University of California.
                     14:  * All rights reserved.
                     15:  *
                     16:  * This code is derived from software contributed to Berkeley by
                     17:  * Vern Paxson.
                     18:  *
                     19:  * The United States Government has rights in this work pursuant
                     20:  * to contract no. DE-AC03-76SF00098 between the United States
                     21:  * Department of Energy and the University of California.
                     22:  *
1.4       deraadt    23:  * Redistribution and use in source and binary forms, with or without
                     24:  * modification, are permitted provided that: (1) source distributions
                     25:  * retain this entire copyright notice and comment, and (2) distributions
                     26:  * including binaries display the following acknowledgement:  ``This product
                     27:  * includes software developed by the University of California, Berkeley
                     28:  * and its contributors'' in the documentation or other materials provided
                     29:  * with the distribution and in all advertising materials mentioning
                     30:  * features or use of this software. Neither the name of the University nor
                     31:  * the names of its contributors may be used to endorse or promote products
                     32:  * derived from this software without specific prior written permission.
1.1       deraadt    33:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     34:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     35:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     36:  */
                     37:
1.7     ! deraadt    38: /* $Header: /cvs/src/usr.bin/lex/parse.y,v 1.5 2002/05/30 10:53:45 deraadt Exp $ */
1.1       deraadt    39:
                     40:
                     41: /* Some versions of bison are broken in that they use alloca() but don't
                     42:  * declare it properly.  The following is the patented (just kidding!)
                     43:  * #ifdef chud to fix the problem, courtesy of Francois Pinard.
                     44:  */
                     45: #ifdef YYBISON
                     46: /* AIX requires this to be the first thing in the file.  What a piece.  */
                     47: # ifdef _AIX
                     48:  #pragma alloca
                     49: # endif
                     50: #endif
                     51:
                     52: #include "flexdef.h"
                     53:
                     54: /* The remainder of the alloca() cruft has to come after including flexdef.h,
                     55:  * so HAVE_ALLOCA_H is (possibly) defined.
                     56:  */
                     57: #ifdef YYBISON
                     58: # ifdef __GNUC__
                     59: #  ifndef alloca
                     60: #   define alloca __builtin_alloca
                     61: #  endif
                     62: # else
                     63: #  if HAVE_ALLOCA_H
                     64: #   include <alloca.h>
                     65: #  else
                     66: #   ifdef __hpux
                     67: void *alloca ();
                     68: #   else
                     69: #    ifdef __TURBOC__
                     70: #     include <malloc.h>
                     71: #    else
                     72: char *alloca ();
                     73: #    endif
                     74: #   endif
                     75: #  endif
                     76: # endif
                     77: #endif
                     78:
                     79: /* Bletch, ^^^^ that was ugly! */
                     80:
                     81:
                     82: int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
                     83: int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
                     84:
                     85: int *scon_stk;
                     86: int scon_stk_ptr;
                     87:
                     88: static int madeany = false;  /* whether we've made the '.' character class */
                     89: int previous_continued_action; /* whether the previous rule's action was '|' */
                     90:
                     91: /* Expand a POSIX character class expression. */
                     92: #define CCL_EXPR(func) \
                     93:        { \
                     94:        int c; \
                     95:        for ( c = 0; c < csize; ++c ) \
                     96:                if ( isascii(c) && func(c) ) \
                     97:                        ccladd( currccl, c ); \
                     98:        }
                     99:
                    100: /* While POSIX defines isblank(), it's not ANSI C. */
                    101: #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
                    102:
                    103: /* On some over-ambitious machines, such as DEC Alpha's, the default
                    104:  * token type is "long" instead of "int"; this leads to problems with
                    105:  * declaring yylval in flexdef.h.  But so far, all the yacc's I've seen
                    106:  * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
                    107:  * following should ensure that the default token type is "int".
                    108:  */
                    109: #define YYSTYPE int
                    110:
                    111: %}
                    112:
                    113: %%
                    114: goal           :  initlex sect1 sect1end sect2 initforrule
                    115:                        { /* add default rule */
                    116:                        int def_rule;
                    117:
                    118:                        pat = cclinit();
                    119:                        cclnegate( pat );
                    120:
                    121:                        def_rule = mkstate( -pat );
                    122:
                    123:                        /* Remember the number of the default rule so we
                    124:                         * don't generate "can't match" warnings for it.
                    125:                         */
                    126:                        default_rule = num_rules;
                    127:
                    128:                        finish_rule( def_rule, false, 0, 0 );
                    129:
                    130:                        for ( i = 1; i <= lastsc; ++i )
                    131:                                scset[i] = mkbranch( scset[i], def_rule );
                    132:
                    133:                        if ( spprdflt )
                    134:                                add_action(
                    135:                                "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
                    136:                        else
                    137:                                add_action( "ECHO" );
                    138:
                    139:                        add_action( ";\n\tYY_BREAK\n" );
                    140:                        }
                    141:                ;
                    142:
                    143: initlex                :
                    144:                        { /* initialize for processing rules */
                    145:
                    146:                        /* Create default DFA start condition. */
                    147:                        scinstal( "INITIAL", false );
                    148:                        }
                    149:                ;
                    150:
                    151: sect1          :  sect1 startconddecl namelist1
                    152:                |  sect1 options
                    153:                |
                    154:                |  error
                    155:                        { synerr( "unknown error processing section 1" ); }
                    156:                ;
                    157:
                    158: sect1end       :  SECTEND
                    159:                        {
                    160:                        check_options();
                    161:                        scon_stk = allocate_integer_array( lastsc + 1 );
                    162:                        scon_stk_ptr = 0;
                    163:                        }
                    164:                ;
                    165:
                    166: startconddecl  :  SCDECL
                    167:                        { xcluflg = false; }
                    168:
                    169:                |  XSCDECL
                    170:                        { xcluflg = true; }
                    171:                ;
                    172:
                    173: namelist1      :  namelist1 NAME
                    174:                        { scinstal( nmstr, xcluflg ); }
                    175:
                    176:                |  NAME
                    177:                        { scinstal( nmstr, xcluflg ); }
                    178:
                    179:                |  error
                    180:                        { synerr( "bad start condition list" ); }
                    181:                ;
                    182:
                    183: options                :  OPTION_OP optionlist
                    184:                ;
                    185:
                    186: optionlist     :  optionlist option
                    187:                |
                    188:                ;
                    189:
                    190: option         :  OPT_OUTFILE '=' NAME
                    191:                        {
                    192:                        outfilename = copy_string( nmstr );
                    193:                        did_outfilename = 1;
                    194:                        }
                    195:                |  OPT_PREFIX '=' NAME
                    196:                        { prefix = copy_string( nmstr ); }
                    197:                |  OPT_YYCLASS '=' NAME
                    198:                        { yyclass = copy_string( nmstr ); }
                    199:                ;
                    200:
                    201: sect2          :  sect2 scon initforrule flexrule '\n'
                    202:                        { scon_stk_ptr = $2; }
                    203:                |  sect2 scon '{' sect2 '}'
                    204:                        { scon_stk_ptr = $2; }
                    205:                |
                    206:                ;
                    207:
                    208: initforrule    :
                    209:                        {
                    210:                        /* Initialize for a parse of one rule. */
                    211:                        trlcontxt = variable_trail_rule = varlength = false;
                    212:                        trailcnt = headcnt = rulelen = 0;
                    213:                        current_state_type = STATE_NORMAL;
                    214:                        previous_continued_action = continued_action;
                    215:                        in_rule = true;
                    216:
                    217:                        new_rule();
                    218:                        }
                    219:                ;
                    220:
                    221: flexrule       :  '^' rule
                    222:                        {
                    223:                        pat = $2;
                    224:                        finish_rule( pat, variable_trail_rule,
                    225:                                headcnt, trailcnt );
                    226:
                    227:                        if ( scon_stk_ptr > 0 )
                    228:                                {
                    229:                                for ( i = 1; i <= scon_stk_ptr; ++i )
                    230:                                        scbol[scon_stk[i]] =
                    231:                                                mkbranch( scbol[scon_stk[i]],
                    232:                                                                pat );
                    233:                                }
                    234:
                    235:                        else
                    236:                                {
                    237:                                /* Add to all non-exclusive start conditions,
                    238:                                 * including the default (0) start condition.
                    239:                                 */
                    240:
                    241:                                for ( i = 1; i <= lastsc; ++i )
                    242:                                        if ( ! scxclu[i] )
                    243:                                                scbol[i] = mkbranch( scbol[i],
                    244:                                                                        pat );
                    245:                                }
                    246:
                    247:                        if ( ! bol_needed )
                    248:                                {
                    249:                                bol_needed = true;
                    250:
                    251:                                if ( performance_report > 1 )
                    252:                                        pinpoint_message(
                    253:                        "'^' operator results in sub-optimal performance" );
                    254:                                }
                    255:                        }
                    256:
                    257:                |  rule
                    258:                        {
                    259:                        pat = $1;
                    260:                        finish_rule( pat, variable_trail_rule,
                    261:                                headcnt, trailcnt );
                    262:
                    263:                        if ( scon_stk_ptr > 0 )
                    264:                                {
                    265:                                for ( i = 1; i <= scon_stk_ptr; ++i )
                    266:                                        scset[scon_stk[i]] =
                    267:                                                mkbranch( scset[scon_stk[i]],
                    268:                                                                pat );
                    269:                                }
                    270:
                    271:                        else
                    272:                                {
                    273:                                for ( i = 1; i <= lastsc; ++i )
                    274:                                        if ( ! scxclu[i] )
                    275:                                                scset[i] =
                    276:                                                        mkbranch( scset[i],
                    277:                                                                pat );
                    278:                                }
                    279:                        }
                    280:
                    281:                |  EOF_OP
                    282:                        {
                    283:                        if ( scon_stk_ptr > 0 )
                    284:                                build_eof_action();
                    285:
                    286:                        else
                    287:                                {
                    288:                                /* This EOF applies to all start conditions
                    289:                                 * which don't already have EOF actions.
                    290:                                 */
                    291:                                for ( i = 1; i <= lastsc; ++i )
                    292:                                        if ( ! sceof[i] )
                    293:                                                scon_stk[++scon_stk_ptr] = i;
                    294:
                    295:                                if ( scon_stk_ptr == 0 )
                    296:                                        warn(
                    297:                        "all start conditions already have <<EOF>> rules" );
                    298:
                    299:                                else
                    300:                                        build_eof_action();
                    301:                                }
                    302:                        }
                    303:
                    304:                |  error
                    305:                        { synerr( "unrecognized rule" ); }
                    306:                ;
                    307:
                    308: scon_stk_ptr   :
                    309:                        { $$ = scon_stk_ptr; }
                    310:                ;
                    311:
                    312: scon           :  '<' scon_stk_ptr namelist2 '>'
                    313:                        { $$ = $2; }
                    314:
                    315:                |  '<' '*' '>'
                    316:                        {
                    317:                        $$ = scon_stk_ptr;
                    318:
                    319:                        for ( i = 1; i <= lastsc; ++i )
                    320:                                {
                    321:                                int j;
                    322:
                    323:                                for ( j = 1; j <= scon_stk_ptr; ++j )
                    324:                                        if ( scon_stk[j] == i )
                    325:                                                break;
                    326:
                    327:                                if ( j > scon_stk_ptr )
                    328:                                        scon_stk[++scon_stk_ptr] = i;
                    329:                                }
                    330:                        }
                    331:
                    332:                |
                    333:                        { $$ = scon_stk_ptr; }
                    334:                ;
                    335:
                    336: namelist2      :  namelist2 ',' sconname
                    337:
                    338:                |  sconname
                    339:
                    340:                |  error
                    341:                        { synerr( "bad start condition list" ); }
                    342:                ;
                    343:
                    344: sconname       :  NAME
                    345:                        {
                    346:                        if ( (scnum = sclookup( nmstr )) == 0 )
                    347:                                format_pinpoint_message(
                    348:                                        "undeclared start condition %s",
                    349:                                        nmstr );
                    350:                        else
                    351:                                {
                    352:                                for ( i = 1; i <= scon_stk_ptr; ++i )
                    353:                                        if ( scon_stk[i] == scnum )
                    354:                                                {
                    355:                                                format_warn(
                    356:                                                        "<%s> specified twice",
                    357:                                                        scname[scnum] );
                    358:                                                break;
                    359:                                                }
                    360:
                    361:                                if ( i > scon_stk_ptr )
                    362:                                        scon_stk[++scon_stk_ptr] = scnum;
                    363:                                }
                    364:                        }
                    365:                ;
                    366:
                    367: rule           :  re2 re
                    368:                        {
                    369:                        if ( transchar[lastst[$2]] != SYM_EPSILON )
                    370:                                /* Provide final transition \now/ so it
                    371:                                 * will be marked as a trailing context
                    372:                                 * state.
                    373:                                 */
                    374:                                $2 = link_machines( $2,
                    375:                                                mkstate( SYM_EPSILON ) );
                    376:
                    377:                        mark_beginning_as_normal( $2 );
                    378:                        current_state_type = STATE_NORMAL;
                    379:
                    380:                        if ( previous_continued_action )
                    381:                                {
                    382:                                /* We need to treat this as variable trailing
                    383:                                 * context so that the backup does not happen
                    384:                                 * in the action but before the action switch
                    385:                                 * statement.  If the backup happens in the
                    386:                                 * action, then the rules "falling into" this
                    387:                                 * one's action will *also* do the backup,
                    388:                                 * erroneously.
                    389:                                 */
                    390:                                if ( ! varlength || headcnt != 0 )
                    391:                                        warn(
                    392:                "trailing context made variable due to preceding '|' action" );
                    393:
                    394:                                /* Mark as variable. */
                    395:                                varlength = true;
                    396:                                headcnt = 0;
                    397:                                }
                    398:
                    399:                        if ( lex_compat || (varlength && headcnt == 0) )
                    400:                                { /* variable trailing context rule */
                    401:                                /* Mark the first part of the rule as the
                    402:                                 * accepting "head" part of a trailing
                    403:                                 * context rule.
                    404:                                 *
                    405:                                 * By the way, we didn't do this at the
                    406:                                 * beginning of this production because back
                    407:                                 * then current_state_type was set up for a
                    408:                                 * trail rule, and add_accept() can create
                    409:                                 * a new state ...
                    410:                                 */
                    411:                                add_accept( $1,
                    412:                                        num_rules | YY_TRAILING_HEAD_MASK );
                    413:                                variable_trail_rule = true;
                    414:                                }
                    415:
                    416:                        else
                    417:                                trailcnt = rulelen;
                    418:
                    419:                        $$ = link_machines( $1, $2 );
                    420:                        }
                    421:
                    422:                |  re2 re '$'
                    423:                        { synerr( "trailing context used twice" ); }
                    424:
                    425:                |  re '$'
                    426:                        {
                    427:                        headcnt = 0;
                    428:                        trailcnt = 1;
                    429:                        rulelen = 1;
                    430:                        varlength = false;
                    431:
                    432:                        current_state_type = STATE_TRAILING_CONTEXT;
                    433:
                    434:                        if ( trlcontxt )
                    435:                                {
                    436:                                synerr( "trailing context used twice" );
                    437:                                $$ = mkstate( SYM_EPSILON );
                    438:                                }
                    439:
                    440:                        else if ( previous_continued_action )
                    441:                                {
                    442:                                /* See the comment in the rule for "re2 re"
                    443:                                 * above.
                    444:                                 */
                    445:                                warn(
                    446:                "trailing context made variable due to preceding '|' action" );
                    447:
                    448:                                varlength = true;
                    449:                                }
                    450:
                    451:                        if ( lex_compat || varlength )
                    452:                                {
                    453:                                /* Again, see the comment in the rule for
                    454:                                 * "re2 re" above.
                    455:                                 */
                    456:                                add_accept( $1,
                    457:                                        num_rules | YY_TRAILING_HEAD_MASK );
                    458:                                variable_trail_rule = true;
                    459:                                }
                    460:
                    461:                        trlcontxt = true;
                    462:
                    463:                        eps = mkstate( SYM_EPSILON );
                    464:                        $$ = link_machines( $1,
                    465:                                link_machines( eps, mkstate( '\n' ) ) );
                    466:                        }
                    467:
                    468:                |  re
                    469:                        {
                    470:                        $$ = $1;
                    471:
                    472:                        if ( trlcontxt )
                    473:                                {
                    474:                                if ( lex_compat || (varlength && headcnt == 0) )
                    475:                                        /* Both head and trail are
                    476:                                         * variable-length.
                    477:                                         */
                    478:                                        variable_trail_rule = true;
                    479:                                else
                    480:                                        trailcnt = rulelen;
                    481:                                }
                    482:                        }
                    483:                ;
                    484:
                    485:
                    486: re             :  re '|' series
                    487:                        {
                    488:                        varlength = true;
                    489:                        $$ = mkor( $1, $3 );
                    490:                        }
                    491:
                    492:                |  series
                    493:                        { $$ = $1; }
                    494:                ;
                    495:
                    496:
                    497: re2            :  re '/'
                    498:                        {
                    499:                        /* This rule is written separately so the
                    500:                         * reduction will occur before the trailing
                    501:                         * series is parsed.
                    502:                         */
                    503:
                    504:                        if ( trlcontxt )
                    505:                                synerr( "trailing context used twice" );
                    506:                        else
                    507:                                trlcontxt = true;
                    508:
                    509:                        if ( varlength )
                    510:                                /* We hope the trailing context is
                    511:                                 * fixed-length.
                    512:                                 */
                    513:                                varlength = false;
                    514:                        else
                    515:                                headcnt = rulelen;
                    516:
                    517:                        rulelen = 0;
                    518:
                    519:                        current_state_type = STATE_TRAILING_CONTEXT;
                    520:                        $$ = $1;
                    521:                        }
                    522:                ;
                    523:
                    524: series         :  series singleton
                    525:                        {
                    526:                        /* This is where concatenation of adjacent patterns
                    527:                         * gets done.
                    528:                         */
                    529:                        $$ = link_machines( $1, $2 );
                    530:                        }
                    531:
                    532:                |  singleton
                    533:                        { $$ = $1; }
                    534:                ;
                    535:
                    536: singleton      :  singleton '*'
                    537:                        {
                    538:                        varlength = true;
                    539:
                    540:                        $$ = mkclos( $1 );
                    541:                        }
                    542:
                    543:                |  singleton '+'
                    544:                        {
                    545:                        varlength = true;
                    546:                        $$ = mkposcl( $1 );
                    547:                        }
                    548:
                    549:                |  singleton '?'
                    550:                        {
                    551:                        varlength = true;
                    552:                        $$ = mkopt( $1 );
                    553:                        }
                    554:
                    555:                |  singleton '{' NUMBER ',' NUMBER '}'
                    556:                        {
                    557:                        varlength = true;
                    558:
                    559:                        if ( $3 > $5 || $3 < 0 )
                    560:                                {
                    561:                                synerr( "bad iteration values" );
                    562:                                $$ = $1;
                    563:                                }
                    564:                        else
                    565:                                {
                    566:                                if ( $3 == 0 )
                    567:                                        {
                    568:                                        if ( $5 <= 0 )
                    569:                                                {
                    570:                                                synerr(
                    571:                                                "bad iteration values" );
                    572:                                                $$ = $1;
                    573:                                                }
                    574:                                        else
                    575:                                                $$ = mkopt(
                    576:                                                        mkrep( $1, 1, $5 ) );
                    577:                                        }
                    578:                                else
                    579:                                        $$ = mkrep( $1, $3, $5 );
                    580:                                }
                    581:                        }
                    582:
                    583:                |  singleton '{' NUMBER ',' '}'
                    584:                        {
                    585:                        varlength = true;
                    586:
                    587:                        if ( $3 <= 0 )
                    588:                                {
                    589:                                synerr( "iteration value must be positive" );
                    590:                                $$ = $1;
                    591:                                }
                    592:
                    593:                        else
                    594:                                $$ = mkrep( $1, $3, INFINITY );
                    595:                        }
                    596:
                    597:                |  singleton '{' NUMBER '}'
                    598:                        {
                    599:                        /* The singleton could be something like "(foo)",
                    600:                         * in which case we have no idea what its length
                    601:                         * is, so we punt here.
                    602:                         */
                    603:                        varlength = true;
                    604:
                    605:                        if ( $3 <= 0 )
                    606:                                {
                    607:                                synerr( "iteration value must be positive" );
                    608:                                $$ = $1;
                    609:                                }
                    610:
                    611:                        else
                    612:                                $$ = link_machines( $1,
                    613:                                                copysingl( $1, $3 - 1 ) );
                    614:                        }
                    615:
                    616:                |  '.'
                    617:                        {
                    618:                        if ( ! madeany )
                    619:                                {
                    620:                                /* Create the '.' character class. */
                    621:                                anyccl = cclinit();
                    622:                                ccladd( anyccl, '\n' );
                    623:                                cclnegate( anyccl );
                    624:
                    625:                                if ( useecs )
                    626:                                        mkeccl( ccltbl + cclmap[anyccl],
                    627:                                                ccllen[anyccl], nextecm,
                    628:                                                ecgroup, csize, csize );
                    629:
                    630:                                madeany = true;
                    631:                                }
                    632:
                    633:                        ++rulelen;
                    634:
                    635:                        $$ = mkstate( -anyccl );
                    636:                        }
                    637:
                    638:                |  fullccl
                    639:                        {
                    640:                        if ( ! cclsorted )
                    641:                                /* Sort characters for fast searching.  We
                    642:                                 * use a shell sort since this list could
                    643:                                 * be large.
                    644:                                 */
                    645:                                cshell( ccltbl + cclmap[$1], ccllen[$1], true );
                    646:
                    647:                        if ( useecs )
                    648:                                mkeccl( ccltbl + cclmap[$1], ccllen[$1],
                    649:                                        nextecm, ecgroup, csize, csize );
                    650:
                    651:                        ++rulelen;
                    652:
                    653:                        $$ = mkstate( -$1 );
                    654:                        }
                    655:
                    656:                |  PREVCCL
                    657:                        {
                    658:                        ++rulelen;
                    659:
                    660:                        $$ = mkstate( -$1 );
                    661:                        }
                    662:
                    663:                |  '"' string '"'
                    664:                        { $$ = $2; }
                    665:
                    666:                |  '(' re ')'
                    667:                        { $$ = $2; }
                    668:
                    669:                |  CHAR
                    670:                        {
                    671:                        ++rulelen;
                    672:
                    673:                        if ( caseins && $1 >= 'A' && $1 <= 'Z' )
                    674:                                $1 = clower( $1 );
                    675:
                    676:                        $$ = mkstate( $1 );
                    677:                        }
                    678:                ;
                    679:
                    680: fullccl                :  '[' ccl ']'
                    681:                        { $$ = $2; }
                    682:
                    683:                |  '[' '^' ccl ']'
                    684:                        {
                    685:                        cclnegate( $3 );
                    686:                        $$ = $3;
                    687:                        }
                    688:                ;
                    689:
                    690: ccl            :  ccl CHAR '-' CHAR
                    691:                        {
                    692:                        if ( caseins )
                    693:                                {
                    694:                                if ( $2 >= 'A' && $2 <= 'Z' )
                    695:                                        $2 = clower( $2 );
                    696:                                if ( $4 >= 'A' && $4 <= 'Z' )
                    697:                                        $4 = clower( $4 );
                    698:                                }
                    699:
                    700:                        if ( $2 > $4 )
                    701:                                synerr( "negative range in character class" );
                    702:
                    703:                        else
                    704:                                {
                    705:                                for ( i = $2; i <= $4; ++i )
                    706:                                        ccladd( $1, i );
                    707:
                    708:                                /* Keep track if this ccl is staying in
                    709:                                 * alphabetical order.
                    710:                                 */
                    711:                                cclsorted = cclsorted && ($2 > lastchar);
                    712:                                lastchar = $4;
                    713:                                }
                    714:
                    715:                        $$ = $1;
                    716:                        }
                    717:
                    718:                |  ccl CHAR
                    719:                        {
                    720:                        if ( caseins && $2 >= 'A' && $2 <= 'Z' )
                    721:                                $2 = clower( $2 );
                    722:
                    723:                        ccladd( $1, $2 );
                    724:                        cclsorted = cclsorted && ($2 > lastchar);
                    725:                        lastchar = $2;
                    726:                        $$ = $1;
                    727:                        }
                    728:
                    729:                |  ccl ccl_expr
                    730:                        {
                    731:                        /* Too hard to properly maintain cclsorted. */
                    732:                        cclsorted = false;
                    733:                        $$ = $1;
                    734:                        }
                    735:
                    736:                |
                    737:                        {
                    738:                        cclsorted = true;
                    739:                        lastchar = 0;
                    740:                        currccl = $$ = cclinit();
                    741:                        }
                    742:                ;
                    743:
                    744: ccl_expr:         CCE_ALNUM    { CCL_EXPR(isalnum) }
                    745:                |  CCE_ALPHA    { CCL_EXPR(isalpha) }
                    746:                |  CCE_BLANK    { CCL_EXPR(IS_BLANK) }
                    747:                |  CCE_CNTRL    { CCL_EXPR(iscntrl) }
                    748:                |  CCE_DIGIT    { CCL_EXPR(isdigit) }
                    749:                |  CCE_GRAPH    { CCL_EXPR(isgraph) }
                    750:                |  CCE_LOWER    { CCL_EXPR(islower) }
                    751:                |  CCE_PRINT    { CCL_EXPR(isprint) }
                    752:                |  CCE_PUNCT    { CCL_EXPR(ispunct) }
                    753:                |  CCE_SPACE    { CCL_EXPR(isspace) }
                    754:                |  CCE_UPPER    {
                    755:                                if ( caseins )
                    756:                                        CCL_EXPR(islower)
                    757:                                else
                    758:                                        CCL_EXPR(isupper)
                    759:                                }
                    760:                |  CCE_XDIGIT   { CCL_EXPR(isxdigit) }
                    761:                ;
                    762:
                    763: string         :  string CHAR
                    764:                        {
                    765:                        if ( caseins && $2 >= 'A' && $2 <= 'Z' )
                    766:                                $2 = clower( $2 );
                    767:
                    768:                        ++rulelen;
                    769:
                    770:                        $$ = link_machines( $1, mkstate( $2 ) );
                    771:                        }
                    772:
                    773:                |
                    774:                        { $$ = mkstate( SYM_EPSILON ); }
                    775:                ;
                    776:
                    777: %%
                    778:
                    779:
                    780: /* build_eof_action - build the "<<EOF>>" action for the active start
                    781:  *                    conditions
                    782:  */
                    783:
                    784: void build_eof_action()
                    785:        {
                    786:        register int i;
                    787:        char action_text[MAXLINE];
                    788:
                    789:        for ( i = 1; i <= scon_stk_ptr; ++i )
                    790:                {
                    791:                if ( sceof[scon_stk[i]] )
                    792:                        format_pinpoint_message(
                    793:                                "multiple <<EOF>> rules for start condition %s",
                    794:                                scname[scon_stk[i]] );
                    795:
                    796:                else
                    797:                        {
                    798:                        sceof[scon_stk[i]] = true;
1.7     ! deraadt   799:                        snprintf( action_text, sizeof action_text,
        !           800:                                "case YY_STATE_EOF(%s):\n",
1.1       deraadt   801:                                scname[scon_stk[i]] );
                    802:                        add_action( action_text );
                    803:                        }
                    804:                }
                    805:
                    806:        line_directive_out( (FILE *) 0, 1 );
                    807:
                    808:        /* This isn't a normal rule after all - don't count it as
                    809:         * such, so we don't have any holes in the rule numbering
                    810:         * (which make generating "rule can never match" warnings
                    811:         * more difficult.
                    812:         */
                    813:        --num_rules;
                    814:        ++num_eof_rules;
                    815:        }
                    816:
                    817:
                    818: /* format_synerr - write out formatted syntax error */
                    819:
                    820: void format_synerr( msg, arg )
                    821: char msg[], arg[];
                    822:        {
                    823:        char errmsg[MAXLINE];
                    824:
1.7     ! deraadt   825:        (void) snprintf( errmsg, sizeof errmsg, msg, arg );
1.1       deraadt   826:        synerr( errmsg );
                    827:        }
                    828:
                    829:
                    830: /* synerr - report a syntax error */
                    831:
                    832: void synerr( str )
                    833: char str[];
                    834:        {
                    835:        syntaxerror = true;
                    836:        pinpoint_message( str );
                    837:        }
                    838:
                    839:
                    840: /* format_warn - write out formatted warning */
                    841:
                    842: void format_warn( msg, arg )
                    843: char msg[], arg[];
                    844:        {
                    845:        char warn_msg[MAXLINE];
                    846:
1.7     ! deraadt   847:        (void) snprintf( warn_msg, sizeof warn_msg, msg, arg );
1.1       deraadt   848:        warn( warn_msg );
                    849:        }
                    850:
                    851:
                    852: /* warn - report a warning, unless -w was given */
                    853:
                    854: void warn( str )
                    855: char str[];
                    856:        {
                    857:        line_warning( str, linenum );
                    858:        }
                    859:
                    860: /* format_pinpoint_message - write out a message formatted with one string,
                    861:  *                          pinpointing its location
                    862:  */
                    863:
                    864: void format_pinpoint_message( msg, arg )
                    865: char msg[], arg[];
                    866:        {
                    867:        char errmsg[MAXLINE];
                    868:
1.7     ! deraadt   869:        (void) snprintf( errmsg, sizeof errmsg, msg, arg );
1.1       deraadt   870:        pinpoint_message( errmsg );
                    871:        }
                    872:
                    873:
                    874: /* pinpoint_message - write out a message, pinpointing its location */
                    875:
                    876: void pinpoint_message( str )
                    877: char str[];
                    878:        {
                    879:        line_pinpoint( str, linenum );
                    880:        }
                    881:
                    882:
                    883: /* line_warning - report a warning at a given line, unless -w was given */
                    884:
                    885: void line_warning( str, line )
                    886: char str[];
                    887: int line;
                    888:        {
                    889:        char warning[MAXLINE];
                    890:
                    891:        if ( ! nowarn )
                    892:                {
1.7     ! deraadt   893:                snprintf( warning, sizeof warning, "warning, %s", str );
1.1       deraadt   894:                line_pinpoint( warning, line );
                    895:                }
                    896:        }
                    897:
                    898:
                    899: /* line_pinpoint - write out a message, pinpointing it at the given line */
                    900:
                    901: void line_pinpoint( str, line )
                    902: char str[];
                    903: int line;
                    904:        {
                    905:        fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
                    906:        }
                    907:
                    908:
                    909: /* yyerror - eat up an error message from the parser;
                    910:  *          currently, messages are ignore
                    911:  */
                    912:
                    913: void yyerror( msg )
                    914: char msg[];
                    915:        {
                    916:        }