#include #include #include static int vertical_mode = 0; typedef struct { int width; /* Maximum line length, excluding terminating LF */ int height; /* Line count */ int size; /* File size */ int capacity; /* Buffer size */ char *data; /* File contents */ char *cursor; /* Current read position */ } FileInfo; int main(int argc, char **argv) { int i, j, k, width, read_size, max_line_count = 0; FileInfo *files; FILE *infile; /* Load files */ if( (files = (FileInfo*)calloc(sizeof(FileInfo), argc)) == NULL ) return !puts("Out of memory"); for(i = 1; i < argc; i++) { for(j = 1; j < i; j++) { if( strcmp(argv[i], argv[j]) == 0 ) { /* Duplicate file specified on command line, no need to load the same file again. */ memcpy(&files[i], &files[j], sizeof(FileInfo)); break; } } if( j < i ) continue; if( strcmp(argv[i], "-") != 0 ) { if( (infile = fopen(argv[i], "rb")) == NULL ) return printf("Can not open %s\n", argv[i]); } else { infile = stdin; } /* Load file to memory */ do { files[i].capacity += 0x10000; if( (files[i].data = realloc(files[i].data, files[i].capacity + 1)) == NULL ) return !puts("Out of memory"); read_size = fread(files[i].data + files[i].size, 1, 0x10000, infile); files[i].size += read_size; } while( read_size == 0x10000 ); /* Always make sure file ends with a LF */ files[i].data[files[i].size] = '\n'; files[i].cursor = files[i].data; fclose(infile); for(k = 0; k < files[i].size; k = j + 1) { for(j = k; j < files[i].size && files[i].data[j] != '\n'; j++); width = j - k; if( width > files[i].width ) files[i].width = width; files[i].height++; } } /* Output concatenated files */ for(i = 1; i < argc; i++) { if( files[i].height > max_line_count ) max_line_count = files[i].height; } if( vertical_mode ) { for(i = 1; i < argc; i++) fwrite(files[i].data, files[i].size, 1, stdout); } else { for(i = 0; i < max_line_count; i++) { for(j = 1; j < argc; j++) { width = 0; if( files[j].cursor - files[j].data < files[j].size ) { while( *(files[j].cursor) != '\n' ) { putchar(*(files[j].cursor)); width++; files[j].cursor++; } files[j].cursor++; } for(; width < files[j].width; width++) putchar(' '); } putchar('\n'); } } /* Don't bother freeing memory */ return 0; }