sedexec.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 911 行 · 第 1/3 页

C
911
字号
            curlp = lp;
            while( memeql( bbeg, lp, ct ) )
                lp += ct;

            while( lp >= curlp ) {
                if( advance( lp, ep ) )
                    return( TRUE );
                lp -= ct;
            }
            return( FALSE );

        case CDOT | STAR:               /* match .* */
            curlp = lp;                 /* save closure start loc */
            while( ( *lp++ ) != 0 ) ;   /* match anything */
            goto star;                  /* now look for followers */

        case CCHR | STAR:               /* match <literal char>* */
            curlp = lp;                 /* save closure start loc */
            while( (int)( *lp++ == *ep ) != 0 ) ; /* match many of that char */
            ep++;                       /* to start of next element */
            goto star;                  /* match it and followers */

        case CCL | STAR:                /* match [...]* */
            curlp = lp;                 /* save closure start loc */
            while( c = *lp++ & 0x7F, ep[c >> 3] & bits[c & 07] ) ;
            ep += 16;                   /* skip past the set */
            goto star;                  /* match followers */

        star:                           /* the repeat part of a * or + match */
            if( --lp == curlp )         /* 0 matches */
                break;

            switch( *ep ) {
                case CCHR:
                    c = ep[1];
                    break;
                case CBACK:
                    c = *brastart[ep[1]];
                    break;
                default:
                    do {
                        if( lp == locs )
                            break;
                        if( advance( lp, ep ) )
                            return( TRUE );
                    } while( lp-- > curlp );
                    return( FALSE );
            }

            do {
                if( *lp == c )
                    if( advance( lp, ep ) )
                        return( TRUE );
            } while( lp-- > curlp );
            return( FALSE );

        default:
            fprintf( stderr, "sed: RE error, %o\n", *--ep );
            exit( 2 );

        case CBRA | STAR:               /* start of starred tagged pattern */
            {
                int const       tagindex = *ep;
                int             matched = FALSE;

                curlp = lp;                 /* save closure start loc */
                ct = ep[1];
                bracend[tagindex] = bbeg = tep = lp;
                ep++;
                while( advance( brastart[tagindex] = bracend[tagindex], ep+1 ) && bracend[tagindex] > brastart[tagindex] )
                    if( advance( bracend[tagindex], ep + ct ) ) { /* Try to match RE after \(...\) */
                        matched = TRUE;          /* Remember greediest match */
                        bbeg = brastart[tagindex];
                        tep = bracend[tagindex];
                    }

                if( matched ) {                  /* Did we match RE after \(...\) */
                    brastart[tagindex] = bbeg;    /* Set details of match */
                    bracend[tagindex] = tep;
                    return( TRUE );
                }

                return( advance( bracend[tagindex], ep + ct ) ); /* Zero matches */
            }

        case CBRA | MTYPE:              /* \(...\)\{m,n\} WFB */
            {
                int const       tagindex = *ep;
                int             matched = FALSE;

                curlp = lp;             /* save closure start loc */
                ct = ep[1];
                i1 = ep[ct-1] & 0xFF, i2 = ep[ct] & 0xFF;
                bracend[tagindex] = bbeg = tep = lp;

                while( i1 && advance( lp, ep+2 ) && bracend[tagindex] > lp )
                    brastart[tagindex] = lp, lp = bracend[tagindex], i1--;
                if( i1 )
                    return( FALSE );
                if( !i2 )
                    return( advance( bracend[tagindex], ep + ct + 1 ) ); /* Zero matches */
                if( i2 == 0xFF )
                    i2 = MAXBUF;

                while( advance( brastart[tagindex] = bracend[tagindex], ep+2 ) && bracend[tagindex] > brastart[tagindex] && i2 )
                    if( i2--, advance( bracend[tagindex], ep + ct + 1 ) ) { /* Try to match RE after \(...\) */
                        matched = TRUE; /* Remember greediest match */
                        bbeg = brastart[tagindex];
                        tep = bracend[tagindex];
                    }

                if( matched ) {         /* Did we match RE after \(...\) */
                    brastart[tagindex] = bbeg; /* Set details of match */
                    bracend[tagindex] = tep;
                    return( TRUE );
                }

                if( i1 )
                    return( FALSE );
                return( advance( bracend[tagindex], ep + ct + 1 ) ); /* Zero matches */
            }

        case CCHR | MTYPE:              /* Match <literal char>\{...\} */
            c = *ep++;                  /* Get byte and skip to next element */
            i1 = *ep++ & 0xFF, i2 = *ep++ & 0xFF;
            while( c == *lp && i1 )
                lp++, i1--;
            if( i1 )
                return( FALSE );
            if( !i2 )
                break;
            if( i2 == 0xFF )
                i2 = MAXBUF;
            curlp = lp;
            while( c == *lp++ && i2 )
                i2--;
            goto star;

        case CKET | STAR:               /* match \(..\)* */
        case CKET | MTYPE:              /* match \(..\)\{...\} */
            bracend[*ep] = lp;          /* mark it */
            return( TRUE );

        case CDOT | MTYPE:              /* match .\{...\} */
            i1 = *ep++ & 0xFF, i2 = *ep++ & 0xFF;
            while( *lp && i1 )
                lp++, i1--;
            if( i1 )
                return( FALSE );
            if( !i2 )
                break;
            if( i2 == 0xFF )
                i2 = MAXBUF;
            curlp = lp;
            while( *lp++ && i2 )
                i2--;
            goto star;

        case CCL | MTYPE:               /* match [...]\{...\} */
            tep = ep;
            ep += 16;
            i1 = *ep++ & 0xFF, i2 = *ep++ & 0xFF;
            /* WFB 1 CCL|MTYPE handler must be like CCHR|MTYPE or off by 1 */
            while( ct = *lp, tep[(unsigned)ct >> 3] & bits[ct & 7] && i1 )
                lp++, i1--;
            if( i1 )
                return( FALSE );
            if( !i2 )
                break;
            if( i2 == 0xFF )
                i2 = MAXBUF;
            curlp = lp;
            while( ct = *lp++ & 0xff, tep[(unsigned)ct >> 3] & bits[ct & 7] && i2 )
                i2--;
            goto star;

        case CBACK | MTYPE:             /* e.g. \(.\)\1\{5\} */
            bbeg = brastart[*ep];
            ct = bracend[*ep++] - bbeg;
            i1 = *ep++ & 0xFF, i2 = *ep++ & 0xFF;
            while( memeql( bbeg, lp, ct ) && i1 )
                lp += ct, i1--;
            if( i1 )
                return( FALSE );
            if( !i2 )
                break;
            if( i2 == 0xFF )
                i2 = MAXBUF;
            curlp = lp;
            while( memeql( bbeg, lp, ct ) && i2 )
                lp+= ct, i2--;
            while( lp >= curlp ) {
                if( advance( lp, ep ) )
                    return( TRUE );
                lp -= ct;
            }
            return( FALSE );

        } /* switch( *ep++ ) */
}

/* perform s command */
static int substitute( sedcmd const *ipc ) /* ptr to s command struct */
{
    int fcnt = ipc->flags.nthone;

    if( !match( ipc->u.lhs, 0, 0 ) )    /* if no match */
        return( FALSE );                /* command fails */

    if( fcnt ) {
        while( --fcnt > 0 && *loc2 && match( ipc->u.lhs, 0, 1 ) )
            ;
        if( fcnt != 0 )
            return( FALSE );            /* command fails */
    }

    dosub( ipc->rhs );                  /* perform it once */

    if( ipc->flags.global )             /* if global flag enabled */
        while( *loc2 && match( ipc->u.lhs, 1, 0 ) ) /* cycle through possibles */
            dosub( ipc->rhs );          /* so substitute */
    return( TRUE );                     /* we succeeded */
}

/* generate substituted right-hand side (of s command) */
static void dosub( char const *rhsbuf ) /* where to put the result */
                                        /* uses linebuf, genbuf, spend */
{
    register char       *lp;
    register char       *sp;
    register char const *rp;
    int                 c;
                                        /* linebuf upto location 1 -> genbuf */
    lp = linebuf;
    sp = genbuf;
    while( lp < loc1 ) {
        if( sp >= genbuf + sizeof genbuf ) { /* Not exercised by sedtest.mak */
            fprintf( stderr, NOROOM, sizeof genbuf, lnum );
            break;
        }
        *sp++ = *lp++;
    }

    for( rp = rhsbuf; ( c = *rp++ ) != 0; ) {
        if( c == '&' ) {
            sp = place( sp, loc1, loc2 );
        } else if( c & 0200 && ( c &= 0177 ) >= '1' && c < MAXTAGS + '1' ) {
            sp = place( sp, brastart[c - '0'], bracend[c - '0'] );
        } else {
            if( sp >= genbuf + sizeof genbuf ) { /* Not exercised by sedtest.mak */
                fprintf( stderr, NOROOM, sizeof genbuf, lnum );
                break;
            }
            *sp++ = c & 0177;
        }
    }
    lp = loc2;
    loc2 = sp - ( genbuf - linebuf );   /* Last character to remove */
    do{
        if( sp >= genbuf + sizeof genbuf ) { /* Not exercised by sedtest.mak */
            fprintf( stderr, NOROOM, sizeof genbuf, lnum );
            break;
        }
    } while( ( *sp++ = *lp++ ) != 0 );
    lp = linebuf;
    sp = genbuf;
    while( ( *lp++ = *sp++ ) != 0 ) ;
    spend = lp - 1;
}

/* place chars at *al1...*(al1 - 1) at asp... in genbuf[] */
static char *place(
    register char       *asp,
    register char const *al1,
    register char const *al2 )
{
    while( al1 < al2 ) {
        if( asp >= genbuf + sizeof genbuf ) { /* Not exercised by sedtest.mak */
            fprintf( stderr, NOROOM, sizeof genbuf, lnum );
            break;
        }
        *asp++ = *al1++;
    }
    return( asp );
}

/* write a hex dump expansion of *p1... to fp */
static void listto(
    register char const *p1,            /* the source */
    FILE                *fp )           /* output stream to write to */
{
    int const   linesize = 64;
    int         written = 0;

    p1--;
    while( *++p1 ) {
        if( ++written >= linesize )
            fprintf( fp, "%c\n", '\\' ), written = 1;
        if( *p1 == '\\' )
            putc( *p1, fp ), putc( *p1, fp ), written++; /* Double literal backslash */
        else if( *p1 == '\n' || isprint( *p1 ) )
            putc( *p1, fp );            /* pass it through */
        else {
            written++;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?