From fcefe3e6d93c86b7491c9e5af8372173ae01ed03 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Mon, 24 Feb 2014 04:38:09 +0100 Subject: Allow for multiple files to be acted upon --- el.c | 160 +++++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 88 insertions(+), 72 deletions(-) (limited to 'el.c') diff --git a/el.c b/el.c index 40dccbd..518b3a7 100644 --- a/el.c +++ b/el.c @@ -8,21 +8,29 @@ #include #include -// Our index into the already scanned lines. -// memory buffer is estimated to 1/32th of the -// indexed file's size, meaning each line -// containing approx 31 letters. If it hits the -// top, we increase in 1/32th steps -static unsigned char **index = NULL; - -// this denotes the number of fields, NOT the -// memory occupied (would be a size_t, then!!!) -static long indexsize = 0; - -// this specifies, how many lines have been indexed -// already, scanning always only happens to the -// last reqeusted line -static long indexfilled = 1; +typedef struct { + // Our mmap()ed file, from mystlib + MAP map; + + // Our index into the already scanned lines. + // memory buffer is estimated to 1/32th of the + // indexed file's size, meaning each line + // containing approx 31 letters. If it hits the + // top, we increase in 1/32th steps + uint8_t **index; + + // this denotes the number of fields, NOT the + // memory occupied (would be a size_t, then!!!) + long index_size; + + // this specifies, how many lines have been indexed + // already, scanning always only happens to the + // last reqeusted line + long index_filled; + + // indicates that we've been through all lines in the file + int all_lines_scanned; +} EL_FILE; // If set, the stream of linenums specified calls // the first line number 0... *shiver* @@ -59,66 +67,57 @@ static int nextchar( void ) { // to prevent huge numbers from stdin to steal our // memory -static unsigned char * scanforline( MAP file, const long lineno, long *size ) { - unsigned char *scanline, *const e_o_f = file->addr + file->size; - static int alllinesscanned = 0; +static uint8_t * scanforline( EL_FILE *file, const long lineno, long *size ) { + uint8_t *scanline, *const e_o_f = file->map->addr + file->map->size; *size = 0; // lines start at 1 if( lineno < 1 ) return NULL; // lines we already found can simply be returned - if( lineno < indexfilled ) { - *size = index[lineno] - index[lineno-1]; - return index[lineno-1]; - } + if( lineno < file->index_filled ) + goto return_line; - // if alllines were scanned, were either on + // if all lines were scanned, were either on // or behind last line - if( alllinesscanned ) { - if( lineno == indexfilled ) { - *size = e_o_f - index[lineno-1]; - return index[lineno-1]; - } + if( file->all_lines_scanned ) { + if( lineno == file->index_filled ) + goto return_line; return NULL; } // exploring undiscovered land... - scanline = index[indexfilled-1]; + scanline = file->index[file->index_filled-1]; - while( indexfilled <= lineno ) { + while( file->index_filled <= lineno ) { // scan for next line while( ( scanline < e_o_f ) && ( *scanline++ != '\n' )); + file->index[file->index_filled++] = scanline; + // store pointer if( scanline == e_o_f ) { - alllinesscanned = 1; - if( indexfilled == lineno ) { - *size = e_o_f - index[lineno-1]; - return index[lineno-1]; - } else - return NULL; + file->all_lines_scanned = 1; + if( file->index_filled == lineno + 1 ) + goto return_line; + return NULL; } - index[indexfilled++] = scanline; - // reallocate some memory - if( indexfilled == indexsize ) { - unsigned char ** newblock = (unsigned char**) realloc( index, sizeof(char *) * ( indexsize + file->size / 32 ) ); + if( file->index_filled == file->index_size ) { + void *newblock = realloc( file->index, sizeof(uint8_t*) * ( file->index_size + file->map->size / 32 ) ); if( !newblock ) { fputs( "Could not allocate memory, exiting.\n", stderr); - // unmap file and zero pointer - unmap_file( &file ); exit ( 1 ); } - indexsize += file->size / 32; - index = newblock; + file->index_size += file->map->size / 32; + file->index = newblock; } - } - *size = index[lineno] - index[lineno-1]; - return index[lineno-1]; +return_line: + *size = file->index[lineno] - file->index[lineno-1]; + return file->index[lineno-1]; } // Reads all characters up to the next white space @@ -164,7 +163,7 @@ static int acquire_lineno( int c ) { input[inputindex] = 0; - // Try to read + // Try to read if( sscanf( input, g_scanfmodifier, &lineno ) != 1 ) return 0; @@ -172,12 +171,12 @@ static int acquire_lineno( int c ) { } static void usage() { - fputs( "Usage: el [-0Ggnxh] [-i linenums] filename < linenum_file\n", stderr); + fputs( "Usage: el [-0Ggnxh] [-i linenums] filename .. < linenum_file\n", stderr); } int main( int argc, char **argv ) { - // Our handle to the mapped text file - MAP textfile = NULL; + EL_FILE *textfiles; + size_t i, textfiles_count; int c; while ((c = getopt(argc, argv, ":0i:gGnxh")) != -1) { @@ -209,34 +208,51 @@ int main( int argc, char **argv ) { argc -= optind; argv += optind; - if( argc != 1 ) { usage(); exit(1); } + if( argc < 1 ) { usage(); exit(1); } + textfiles_count = argc; + if( ( textfiles = malloc( textfiles_count * sizeof( EL_FILE ) ) ) == NULL ) { + fputs( "Could not allocate memory, exiting.\n", stderr); + exit(1); + } - // Map text file read only - if( (textfile = map_file( argv[0], 1 )) == NULL ) exit(1); + for( i=0; isize < 32 ? 32 : textfile->size / 32; - if( (index = malloc( sizeof(char *) * indexsize )) == NULL ) { - fputs( "Could not allocate memory, exiting.\n", stderr); - // unmap file and zero pointer - unmap_file( &textfile ); - exit ( 1 ); - } + textfiles[i].index_size = textfiles[i].map->size < 32 ? 32 : textfiles[i].map->size / 32; + if( (textfiles[i].index = malloc( sizeof(uint8_t*) * textfiles[i].index_size )) == NULL ) { + fputs( "Could not allocate memory, exiting.\n", stderr); + exit ( 1 ); + } + + // First line starts at begin of file. + textfiles[i].index[0] = textfiles[i].map->addr; + textfiles[i].index_filled = 1; + textfiles[i].all_lines_scanned = 0; + } - // First line starts at begin of file. - index[0] = textfile->addr; while( (c = nextchar()) != EOF ) { - // get linenumber, pass on eof test char - long slen, lineno = acquire_lineno(c); - unsigned char *line = scanforline( textfile, lineno, &slen ); - - if( line && slen ) - fwrite( line, slen, 1, stdout ); - else - putchar('\n'); + // get linenumber, pass on eof test char + long lineno = acquire_lineno(c); + + for( i=0; i