/* * MPRINT.C * * by: Harvey Moran * * Merge print (on LST:) multiple files by lines * Re-Generated from bvp.c after disk crash - everyone but me ignore this (hrm) * * Last Update: * 10/9/83 * * Usage: * mprint [-n] -w file1 ... fileN * print multi-columns ( wide each) from file list * e.g. * mprint -nw30 f1.c f2.c f3.c * prints 90 character lines 30 * 3 files * -n if used means number the lines * -w sets the column width * * If both options are used, they may be together as in the example. * Line components from the files will NOT be truncated or * wrapped. The sets only the MINimum column width */ #include "bdscio.h" #define REV_DATE "10/9/83" #define PROC int /* PROCedure i.e. function returning no value */ #define BOOL int /* BOOLean i.e. YES or NO */ #define YES 1 #define NO 0 #define LST 2 /* FILE indicator for list device */ #define CTRLC '\3' #define BELL '\7' #define TAB 9 #define MAXFILES 7 /* Max number of files to be merge printed */ #define MAXCOLUMN 200 /* maximum length of a line read from a file */ #define COLUMNWIDTH 40 /* Default column width */ #define fputc putc /* alias */ #define getkey() (bios(3) & 0xff) /* non-echoing getchar() */ /* * Global Variables */ int column_width; char fmt[120]; /* Format Used to do the sprintf() */ char begfmt[20]; /* Leading component of fmt[] */ char format[100]; /* Middle component of fmt[] */ char endfmt[20]; /* Trailing component of fmt[] */ BOOL numbers; BOOL end_all; BOOL end_file[MAXFILES]; char ibuf[MAXFILES][BUFSIZ]; char lllbuf[MAXFILES*MAXCOLUMN]; /* * main() * * process arguments * open files * while ( there is more input ) * catenate lines into a super line * print the super line * print a '\f' * close files */ PROC main(argc, argv) int argc; char *argv[]; { char *p; int line_number; int c; int i; init(); do_args(&argc, &argv); open_files(argc, argv); end_all = NO; line_number = 0; while ( ! end_all ) { cat_lines(argc); if ( numbers ) fprintf(LST, "%4d ", ++line_number); for ( p = lllbuf; *p; ++p ) switch ( *p ) { case '\n': fputc('\r', LST); fputc('\n', LST); break; default: fputc(*p, LST); } if ( kbhit() && (getkey() == CTRLC) ) exit(1); for ( i = 1, end_all = YES; i < argc; ++i ) end_all = end_all && end_file[i-1]; } for ( i = 1; i < argc; ++i ) fclose(&ibuf[i-1][0]); fputc('\f', LST); } /* * initialize assorted junk */ PROC init() { column_width = COLUMNWIDTH; numbers = NO; } /* * collect and act on - options * re-arrange argc and argv to strip out - options */ PROC do_args(ac, avp) int *ac; char ***avp; { char **av; char *p; char c; int i; av = *avp; if ( *ac == 1 ) /* no arguments given, the man needs help */ usage(); for ( p = av[1]; *p++ == '-'; p = av[1] ) { if ( --(*ac) == 1 ) usage(); for ( i = 1; i < *ac; ++i ) /* remove option argument from av[] */ av[i] = av[i+1]; while ( c = *p++ ) { /* now interpert option argument */ switch (toupper(c)) { case 'N': numbers = YES; break; case 'W': column_width = atoi(p); while ( isdigit(*p) ) ++p; break; default: printf("Unrecognized option %c\n\n", c); usage(); } } } } /* * if you don't know, I'm not goin' to tell ya */ PROC open_files(ac, av) int ac; char *av[]; { int i; for ( i = 1; i < ac; ++i ) { if ( fopen(av[i], &ibuf[i-1][0]) == ERROR ) { printf("%cCan't open %s\n", BELL, av[i]); exit(1);; } end_file[i-1] = NO; } } /* * concatenate the lines from each file into * one super-line in lllbuf[] * mark any end_file conditions that occur while reading */ PROC cat_lines(n) int n; { char s[MAXCOLUMN]; char xs[MAXCOLUMN]; char lbuf[MAXCOLUMN]; char *p, *q; int i, j, len, size, tab_col; tab_col = 0; lllbuf[0] = '\0'; /* * get a new set of lines from any files still containing lines */ for ( i = 1; i < n; ++i ) { lbuf[0] = '\0'; if ( ! end_file[i-1] && fgets(s, &ibuf[i-1][0]) ) { for ( p = s; *p != '\r' && *p != '\n' && *p != '\0'; ++p ) ; *p = '\0'; } else { end_file[i-1] = YES; strcpy(s, " "); } /* * Expand TABS */ for ( p = s, q = xs, tab_col = 0; *p; ++p, ++q ) { if ( *p == '\t' ) { do { *q++ = ' '; } while ( ++tab_col % 8 ); --q; } #if 0 else if ( *p == '\n' ) { *q = '\n'; tab_col = 0; } #endif else { *q = *p; ++tab_col; } } *q = '\0'; sprintf(format, "%%-%ds", column_width); sprintf(lbuf, format, xs); len = strlen(lbuf) - 1; if ( lbuf[len] != ' ' ) { /* guarantee a trailing blank */ strcat(lbuf, " "); } if ( (len = strlen(lbuf)) > column_width && i > 1 ) truncate(len - column_width); strcat(lllbuf, lbuf); len = strlen(lllbuf); size = i * column_width; if ( len > size ) truncate(len - size); } /* * strip trailing blanks */ for ( j = strlen(lllbuf) - 1; j > 0; --j ) if ( lllbuf[j] == ' ' ) lllbuf[j] = '\0'; else break; strcat(lllbuf, "\r\n"); } /* * attempt to truncate lllbuf[] by stripping trailing blanks * until the desired number of spaces are squeezed out or * until there is only one remaining blank */ PROC truncate(n) int n; { int len; len = strlen(lllbuf) - 1; while ( n > 0 && lllbuf[len] == ' ' ) { /* too long */ if ( lllbuf[len-1] == ' ' ) { /* at least 1 blank preceding */ lllbuf[len--] = '\0'; --n; } else break; } } /* * tell the man how it is supposed to work, and exit() */ PROC usage() { printf("Usage:\n\n"); printf("\tmprint [-n] [-w] file1 file2 [... fileN]\n\n"); printf("print multi-columns ( wide each) from file list\n\n"); printf("\te.g.\n\n"); printf("\tmprint -nw30 f1.c f2.c f3.c\n\n"); printf("prints 90 character lines 30 * 3 files\n"); printf("-n if used means number the lines\n"); printf("-w sets the column width\n"); printf("if both options are used, they may be together as in the "); printf("example\n\n"); printf("DEFAULTS: no line numbers, width = %d\n\n", COLUMNWIDTH); printf("Line components from the files will NOT be truncated or\n"); printf("wrapped. The sets only the MINimum column width\n\n"); printf("Last Revision Date: %s\n", REV_DATE); exit(1); }