egrep.c

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

C
470
字号
}

static char *getNextLine( int in, int newfile, const char *filename, unsigned lineno )
{
    static int          rd;
    static char *       offset;
    static char *       start;
    static char *       endbuf;
    static int          finalread;
    static int          done = 0;

    if( done ) {
        done = 0;
        return( NULL );
    }
    if( newfile ) {
        if( -1 == ( rd = read( in, IObuffer, IObsize ) ) ) errorExit( "I/O error" );
        start = offset = IObuffer;
        endbuf = IObuffer + rd;
        finalread = ( (size_t) rd < IObsize );
    }
    for( ; ; ) {
        size_t const    len = (unsigned int) ( ( endbuf - start ) - ( offset - start ) );
        char * const    lf = memchr( offset, '\n', len );
        char * const    line = start;

        if( lf != NULL ) {
            if( lf > IObuffer && lf[-1] == '\r' ) lf[-1] = '\0';
            *lf = '\0';
            offset = start = lf + 1;
            return( line );
        }
        if( finalread ) {
            endbuf[1] = '\0';
            done = 1;
            return( start );
        }
        if( len >= IObsize ) {
            free( IObuffer );
            if( ( IObuffer = malloc( IObsize += IObsize >> 1 ) ) == 0
            ||  -1 == lseek( in, -rd, SEEK_CUR ) )
                errorExit( "line too long: len (%lu) >= IObsize (%lu) at \"%s\":%u",
                    (unsigned long) len, (unsigned long) IObsize, filename, lineno );
            return getNextLine( in, newfile, filename, lineno );
        }
        memmove( IObuffer, offset, len );
        start = IObuffer;
        offset = IObuffer + len;
        if( -1 == ( rd = read( in, offset, IObsize - len ) ) ) errorExit( "I/O error" );
        finalread = ( (size_t) rd < IObsize - len );
        endbuf = offset + rd;
    }
}

static unsigned searchFile( const char *filename, int in, int numfile )
{
    char        *line;
    char         match;

    char const   invert  = ((Flags & M_SEARCH_INVERT) != 0);
    unsigned     lineno  = 1;
    unsigned     matches = 0;
    int          new = 1;

    while( ( line = getNextLine( in, new, filename, lineno ) ) != NULL ) {      // returns offset into IObuffer
        new  = 0;
        match = (char) searchBuffer( line );
        if( match ^ invert ) {
            matches++;
            if( Omode == OUT_LINES ) {
                if( numfile > 1 ) {
                    printf( "%s: ", filename );
                }
                if( Flags & M_PREFIX_LINE ) {
                    printf( "%u: ", lineno );
                }
                printf( "%s\n", line );
            } else if( Omode == OUT_FILES ) {
                printf( "%s\n", filename );
                break;
            }
        }
        lineno++;
    }
    return( matches );
}

static void parsePatterns( void )
{
    char * const        *pat;
    char                *p;

    for( pat = fPatterns; *pat != NULL; pat++ ) {
        for( p = *pat; *p; p++ ) {
            *p = CharTrans[ *p ];
            CharExist[ *p ] = 1;
        }
    }
}

static void insertPattern( const char *pat )
{
    if( PatCount >= MAX_SEARCH_STR ) {
        errorExit( "too many search patterns" );
    }
#ifdef FGREP
    fPatterns[ PatCount ] = strdup( pat );
#else
    ePatterns[ PatCount ] = RegComp( (char *) pat );
    if( ePatterns[ PatCount ] == NULL ) {
        errorExit( "error forming regular expression" );
    }
#endif
    PatCount++;
}

static void readPatternFile( const char *filename )
{
    FILE               *fp = fopen( filename, "r" );
    char               *cr;
    unsigned const      patstart = PatCount;

    if( fp == NULL )
        errorExit( "cannot open pattern file \"%s\"", filename );
    while( fgets( IObuffer, IObsize, fp ) ) {
        if( ( cr = strrchr( IObuffer, '\n' ) ) == NULL )
            errorExit( "invalid pattern \"%s\" in \"%s\"", IObuffer, filename );
        *cr = '\0';
        insertPattern( IObuffer );
    }
    (void) fclose( fp );
    if( patstart == PatCount )
        errorExit( "No pattern in \"%s\"", filename );
}

static void changeTransTable( void )
{
    int         ch;

    for( ch = 'A'; ch <= 'Z'; ch++ ) {      // Change uppers to lowers in
        CharTrans[ ch ] |= 0x20;            // translation table
    }
}

static void handle_options( int *pargc, char **argv, int *prematch )
{
    int         ch;             // switch chars

    while( -1 != ( ch = GetOpt( pargc, argv, (char *) "ce:f:ilnsvXx", usageMsg ) ) ) {
        switch( ch ) {
            case 'c':
                Omode = OUT_COUNT;
                break;
            case 'e':
                insertPattern( OptArg );
                break;
            case 'f':
                readPatternFile( OptArg );
                break;
            case 'i':
                Flags |= M_SEARCH_IGNORE;
                CaseIgnore = TRUE;
                changeTransTable( );
                break;
            case 'l':
                Omode = OUT_FILES;
                break;
            case 'n':
                Flags |= M_PREFIX_LINE;
                break;
            case 's':
                Flags |= M_SUPPRESS_ERROR;
                break;
            case 'v':
                Flags |= M_SEARCH_INVERT;
                break;
            case 'X':
                *prematch = 1;
                break;
            case 'x':
                Flags |= M_SEARCH_EXACT;
                break;
            default: /* Do nothing */
                break;
        }
    }
}

int main( int argc, char **argv )
{
    int         rematch = 0;    // regexp file matching is OFF
    unsigned    matches = 0;    // number of matches

    if( ( IObuffer = malloc( IObsize = IOBUF_MIN ) ) == NULL )
        errorExit( "insufficient memory for file buffer" );
    CaseIgnore  = FALSE;        // case sensitive match by default
    argv = ExpandEnv( &argc, argv );
    handle_options( &argc, argv, &rematch );

    if( PatCount == 0 ) {
        if( argc <= 1 )
            errorExit( "%s", usageMsg[0] );
        argc--, argv++;
        insertPattern( *argv );
    }

    parsePatterns( );
    argv = ExpandArgv( &argc, argv, rematch );

    if( *++argv == NULL ) {
        (void) setmode( STDIN_FILENO, O_BINARY );
        matches = searchFile( "stdin", STDIN_FILENO, 1 );
    } else {
        while( *argv != NULL ) {
            int const   in = open( *argv, O_BINARY | O_RDONLY );        // input file handle

            if( in == -1 ) {
                if( !(Flags & M_SUPPRESS_ERROR) )
                    fprintf( stderr, "%s: cannot open input file \"%s\"\n",
                        OptEnvVar, *argv );
            } else {
                matches += searchFile( *argv, in, argc - 1 );
                close( in );
            }
            argv++;
        }
    }
    if( Omode == OUT_COUNT )
        printf( "%u\n", matches );
    free( IObuffer );
    freePatterns( );

    return( matches == 0 );
}

⌨️ 快捷键说明

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