/* overlay - overlay two or more files ** ** Let's say you have these two files: ** ** "This is file 1." ** " And this is file 2." ** ** "overlay file1 file2" will produce: ** ** "This is file 1. And this is file 2." ** ** Copyright (C) 1993 by Jef Poskanzer . ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. */ #include #include static char* argv0; int main( int argc, char** argv ) { int nfiles, i, j; int stdin_used, got_line; FILE** fp; char a_line[1024], the_line[1024]; char* cp; /* Check args. */ argv0 = argv[0]; nfiles = argc - 1; if ( nfiles < 2 ) { (void) fprintf( stderr, "usage: %s file1 file2 ...\n", argv0 ); exit( 1 ); } /* Allocate file pointer array. */ fp = (FILE**) malloc( nfiles * sizeof(FILE*) ); if ( fp == (FILE**) 0 ) { (void) fprintf( stderr, "%s: out of memory\n", argv0 ); exit( 1 ); } /* Open files. */ stdin_used = 0; for ( i = 0; i < nfiles; ++i ) { if ( strcmp( argv[i+1], "-" ) == 0 ) { if ( stdin_used ) { (void) fprintf( stderr, "%s: can't use stdin twice\n", argv0 ); exit( 1 ); } fp[i] = stdin; stdin_used = 1; } else { fp[i] = fopen( argv[i+1], "r" ); if ( fp[i] == (FILE*) 0 ) { perror( argv[i+1] ); exit( 1 ); } } } /* Read and overlay lines until all files are done. */ for (;;) { /* Clear out the result line. */ for ( i = 0; i < sizeof(the_line); ++i ) the_line[i] = ' '; /* Read a line from each still-open file. */ got_line = 0; for ( i = 0; i < nfiles; ++i ) { if ( fp[i] != (FILE*) 0 ) { if ( fgets( a_line, sizeof(a_line), fp[i] ) == (char*) 0 ) { if ( fp[i] != stdin ) (void) fclose( fp[i] ); fp[i] = (FILE*) 0; } else { got_line = 1; /* Add this line to the result line. */ for ( j = 0, cp = a_line; *cp != '\0'; ++cp ) { switch ( *cp ) { case ' ': ++j; break; case '\t': j = ( ( j / 8 ) + 1 ) * 8; break; case '\n': break; default: the_line[j] = *cp; ++j; break; } } } } } if ( ! got_line ) break; /* Remove trailing blanks. */ for ( i = sizeof(the_line) - 2; i > 0; --i ) if ( the_line[i] != ' ' ) break; the_line[i+1] = '\0'; /* And write it out. */ puts( the_line ); } /* Finished. */ exit( 0 ); }