sedexec.c

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

C
911
字号
            putc( '\\', fp );           /* emit a backslash */
            switch( *p1 ) {
            case '\a':
                putc( 'a', fp );
                break;
            case '\b':
                putc( 'b', fp );
                break;
            case '\f':
                putc( 'f', fp );
                break;
            case '\n':                  /* Never activated */
                putc( 'n', fp );
                break;
            case '\r':
                putc( 'r', fp );
                break;
            case '\t':
                putc( 't', fp );
                break;
            case '\v':
                putc( 'v', fp );
                break;
            default:
                written++;
                fprintf( fp, "%02x", *p1 & 0xFF );
            }
        }
    }
    putc( '$', fp );
    putc( '\n', fp );
}

/* execute compiled command pointed at by ipc */
static void command( sedcmd *ipc )
{
    static int      didsub;             /* true if last s succeeded */
    static char     holdsp[MAXHOLD];    /* the hold space */
    static char     *hspend = holdsp;   /* hold space end pointer */
    register char   *p1;
    register char   *p2;
    char            *execp;

    switch( ipc->command ) {
    case ACMD:                          /* append */
        if( aptr >= appends + MAXAPPENDS ) /* Not exercised by sedtest.mak */
            fprintf( stderr, "sed: too many appends after line %ld\n", lnum );
        *aptr++ = ipc;
        break;

    case CCMD:                          /* change pattern space */
        delete = TRUE;
        if( !ipc->flags.inrange || lastline )
            printf( "%s\n", ipc->u.lhs );
        break;

    case DCMD:                          /* delete pattern space */
        delete++;
        break;

    case CDCMD:                         /* delete a line in pattern space */
        p1 = p2 = linebuf;
        while( *p1 && *p1 != '\n' ) p1++;
        if( !*p1++ )
            return;
        while( ( *p2++ = *p1++ ) != 0 ) ;
        spend = p2 - 1;
        delete = jump = TRUE;
        break;

    case EQCMD:                         /* show current line number */
        fprintf( stdout, "%ld\n", lnum );
        break;

    case GCMD:                          /* copy hold space to pattern space */
        p1 = linebuf;
        p2 = holdsp;
        while( ( *p1++ = *p2++ ) != 0 ) ;
        spend = p1 - 1;
        break;

    case CGCMD:                         /* append hold space to pattern space */
        *spend++ = '\n';
        p1 = spend;
        p2 = holdsp;
        while( ( *p1++ = *p2++ ) != 0 )
            if( p1 >= linebuf + MAXBUF ) {
                fprintf( stderr, NOROOM, MAXBUF, lnum );
                break;
            }
        spend = p1 - 1;
        break;

    case HCMD:                          /* copy pattern space to hold space */
        p1 = holdsp;
        p2 = linebuf;
        while( ( *p1++ = *p2++ ) != 0 ) ;
        hspend = p1 - 1;
        break;

    case CHCMD:                         /* append pattern space to hold space */
        *hspend++ = '\n';
        p1 = hspend;
        p2 = linebuf;
        while( ( *p1++ = *p2++ ) != 0 )
            if( p1 >= holdsp + MAXBUF ) {
                fprintf( stderr, NOROOM, MAXBUF, lnum );
                break;
            }
        hspend = p1 - 1;
        break;

    case ICMD:                          /* insert text */
        printf( "%s\n", ipc->u.lhs );
        break;

    case BCMD:                          /* branch to label */
        jump = TRUE;
        break;

    case LCMD:                          /* list text */
        listto( linebuf, ( ipc->fout != NULL ) ? ipc->fout : stdout );
        break;

    case NCMD:                          /* read next line into pattern space */
        if( !nflag )
            puts( linebuf );            /* flush out the current line */
        readout();                      /* do any pending a, r commands */
        if( ( execp = getline( linebuf ) ) == BAD ) {
            pending = ipc;
            delete = TRUE;
            break;
        }
        spend = execp;
        break;

    case CNCMD:                         /* append next line to pattern space */
        readout();                      /* do any pending a, r commands */
        *spend++ = '\n';                /* seperate lines with '\n' */
        if( ( execp = getline( spend ) ) == BAD ) {
            *--spend = '\0';            /* Remove '\n' added for new line */
            pending = ipc;
            delete = TRUE;
            break;
        }
        spend = execp;
        break;

    case PCMD:                          /* print pattern space */
        puts( linebuf );
        break;

    case CPCMD:                         /* print one line from pattern space */
        for( p1 = linebuf; *p1 != '\n' && *p1 != '\0'; p1++ )
            putc( *p1, stdout );
        putc( '\n', stdout );
        break;

    case QCMD:                          /* quit the stream editor */
        if( !nflag )
            puts( linebuf );            /* flush out the current line */
        readout();                      /* do any pending a and r commands */
        exit( 0 );

    case RCMD:                          /* read a file into the stream */
        if( aptr >= appends + MAXAPPENDS ) /* Not exercised by sedtest.mak */
            fprintf( stderr, "sed: too many reads after line %ld\n", lnum );
        *aptr++ = ipc;
        break;

    case SCMD:                          /* substitute RE */
        if( ( didsub = substitute( ipc ) ) != 0 ) {
            switch( ipc->flags.print ) {
            case 1:
                puts( linebuf );
                break;
            case 2:
                for( p1 = linebuf; *p1 != '\n' && *p1 != '\0'; p1++ )
                    putc( *p1, stdout );
                putc( '\n', stdout );
                break;
            }
            if( ipc->fout )
                fprintf( ipc->fout, "%s\n", linebuf );
        }
        break;

    case TCMD:                          /* branch on last s successful */
    case CTCMD:                         /* branch on last s failed */
        if( didsub == (int)( ipc->command == CTCMD ) )
            break;                      /* no branch if last s failed, else */
        didsub = FALSE;
        jump = TRUE;                    /*  set up to jump to assoc'd label */
        break;

    case CWCMD:                         /* write one line from pattern space */
        for( p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
            putc( *p1, ipc->fout ), p1++;
        putc( '\n', ipc->fout );
        break;

    case WCMD:                          /* write pattern space to file */
        fprintf( ipc->fout, "%s\n", linebuf );
        break;

    case XCMD:                          /* exchange pattern and hold spaces */
        p1 = linebuf;
        p2 = genbuf;
        while( ( *p2++ = *p1++ ) != 0 ) ;
        p1 = holdsp;
        p2 = linebuf;
        while( ( *p2++ = *p1++ ) != 0 ) ;
        spend = p2 - 1;
        p1 = genbuf;
        p2 = holdsp;
        while( ( *p2++ = *p1++ ) != 0 ) ;
        hspend = p2 - 1;
        break;

    case YCMD:
        p1 = linebuf;
        p2 = ipc->u.lhs;
        while( ( *p1 = p2[*p1] ) != 0 )
            p1++;
        break;

    default: /* Can never happen */
        fprintf( stderr, INTERR, "unrecognised command" );
    }
}

/* get next line of text to be filtered */
static char *getline( register char *buf )  /* where to send the input */
{
    static char const * const   linebufend = linebuf + MAXBUF + 2;
    int const                   room = linebufend - buf;
    int                         temp;
    char const * const          sbuf = buf;

    assert( buf >= linebuf && buf < linebufend );

    /* The OW fgets has some strange behavior:
     * 0 on input is not treated specially. sed ignores the rest of the line.
     * 26 (^Z) stops reading the current line and is stripped.
     */
    if (fgets(buf, room, stdin) != NULL) { /* gets() can smash program - WFB */
        lnum++;                         /* note that we got another line */
        while( ( *buf++ ) != 0 ) ;      /* find the end of the input */
        if( buf-- - sbuf >= room )
            fprintf( stderr, NOROOM, room, lnum ), buf++;
        if( *--buf != '\n' ) buf++;
        *buf = 0;
        if( eargc == 0 ) {              /* if no more args */
            lastline = ( ( temp = getc( stdin ) ) == EOF );
            (void)ungetc( temp, stdin );
        }
        return( buf );                  /* return ptr to terminating null */
    } else {
        if( eargc == 0 )                /* if no more args */
            lastline = TRUE;            /*    set a flag */
        return( BAD );
    }
}

/* return TRUE if *a... == *b... for count chars, FALSE otherwise */
static int memeql(
    register char const *a,
    register char const *b,
    int                 count )
{
    while( count-- )                    /* look at count characters */
        if( *a++ != *b++ )              /* if any are nonequal   */
            return( FALSE );            /*    return FALSE for false */
    return( TRUE );                     /* compare succeeded */
}

/* write file indicated by r command to output */
static void readout( void )
{
    register int        t;              /* hold input char or EOF */
    FILE                *fi;            /* ptr to file to be read */
    sedcmd * const      *ap;            /* Loops through appends */

    for( ap = appends; ap < aptr; ap ++ ) {
        sedcmd const * const    a = *ap;
        char const * const      lhs = a->u.lhs;

        if( a->command == ACMD )        /* process "a" cmd */
            printf( "%s\n", lhs );
        else {                          /* process "r" cmd */
            if( ( fi = fopen( lhs, "r" ) ) != NULL ) {
                while( ( t = getc( fi ) ) != EOF )
                    putc( ( char ) t, stdout );
                fclose( fi );
            }
        }
    }

    aptr = appends;                     /* reset the append ptr */
}

/* sedexec.c ends here */

⌨️ 快捷键说明

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