#ifdef ournix #include "ournix.h" #endif char sccsID[] = "@(#) overlay.c V1.14 Copyright Julian H. Stacey, Munich, May 1989.\n"; /* See manual for explanation */ #include #include #include #include #include #ifdef MSDOS /* { */ #include #endif /* } */ char *output_name = (char *)0 ; struct stat stat_buf ; typedef int FD ; typedef char FLAG ; FD fd ; FLAG silent = 0 ; FLAG force = 0 ; FLAG f_brother = 0 ; #ifdef scs /* { */ extern char *mktemp() ; #define TMP_NAME "ovXXXXXX" #else /* }{ */ #include #ifdef MSDOS /* { */ #define TMP_NAME "ovXXXXXX" #else /* }{ */ #define TMP_NAME "overlay.XXXXXX" #endif /* } */ #endif /* } */ #include /* for MAXPATHLEN */ char tmp_name[MAXPATHLEN] ; /* temporary file name */ char txt_complain[] = "%s: Cannot open %s.\n"; unsigned current_line = 1 ; #define LINE_LN 1000 FILE *fp_1, *fp_2 ; FILE *fp_out ; char **ARGV ; char a_out_array[LINE_LN] ; char *p_out_array = a_out_array ; #undef USE_STRCHR #if ( vax || i386 || MSDOS ) /* { */ #define USE_STRCHR #endif /* } */ #ifdef USE_STRCHR /* { */ extern char *strchr() ; #define index(s,c) strchr(s,c) #else /* } { */ extern char *index() ; #endif /* } */ /* ---------------------------------------------------- */ char *get_line(fp,where,max_length) FILE *fp ; register char *where ; register int max_length ; /* max. size of array including null */ { register int ch ; max_length-- ; /* allow for \n */ while (((ch = getc(fp)) != EOF) && ((char)ch != '\n')) { if (--max_length <= 0 ) { fprintf(stderr,"%s: Error line %d too long.\n", *ARGV, current_line); exit(-1); } *where++ = (char)ch ; } if ((char)ch == '\n') *where++ = '\n' ; *where = '\0' ; return(where); } cleanup() { (void) unlink(tmp_name) ; } main(argc, argv) int argc ; char **argv; { char *name_1, *name_2 ; char line_1[LINE_LN], line_2[LINE_LN] ; char *p_1, *p_2, c_1, c_2 , *rslt_1, *rslt_2 ; unsigned out_line = 0, out_char = 0 ; unsigned current_char = 1 ; register int ch ; ARGV = argv ; fp_out = stdout ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ strcpy(tmp_name,TMP_NAME) ; for (argc--, argv++ ; argc > 0 ; argv++ ) { if(**argv != '-') break /* no more parameters */ ; argc-- ; switch(*++*argv) { /* option detect */ case 'o': /* syntax:"overlay -o out in1 in2" functionality: like -o flag of cc only outputs to file if no error */ if (argc-- == 0) { fprintf(stderr, "%s: -o must have a parameter.\n", *ARGV); exit(-1); } output_name = *++argv ; break ; case 's': /* silent, no normal output, just returns error output & status */ silent = 1 ; break ; case 'f': /* force output. (normally -o only produces output if there is no everlay error) */ force = 1 ; break ; case 'b': /* bad brother printer */ f_brother = 1 ; break ; default: fprintf(stderr, "%s: Unknown flag %c\n", *ARGV, **argv); break; } } /* finished taking parameters */ if ((argc == 0) || (argc > 2)) { fprintf(stderr,"%s: Error, must specify 1 or 2 input files.\n", *ARGV); exit(-1); } if (silent && force) { fprintf(stderr,"%s: Error -s & -f cannot be used together.\n", *ARGV); exit(-1); } name_1 = *argv++ ; if ( ( fp_1 = fopen(name_1, "r")) == (FILE *)0 ) { fprintf(stderr, txt_complain, *ARGV ,name_1); exit(-1); } if(argc == 1) { name_2 = "\0" ; fp_2 = stdin ; } else { name_2 = *argv++ ; if ( ( fp_2 = fopen(name_2, "r")) == (FILE *)0 ) { fprintf(stderr, txt_complain, *ARGV ,name_2); exit(-1); } } if (output_name != (char *)0 ) { if (mktemp(tmp_name) == (char *)0) { fprintf(stderr,"%s: cant mktemp %s.\n",*ARGV,tmp_name); exit(-1) ; } /* Mask signals */ (void)signal(SIGINT, (void *)&cleanup) ; #ifndef MSDOS /* { */ (void)signal(SIGALRM, (void *)&cleanup) ; (void)signal(SIGHUP, (void *)&cleanup) ; (void)signal(SIGQUIT, (void *)&cleanup) ; (void)signal(SIGILL, (void *)&cleanup) ; (void)signal(SIGIOT, (void *)&cleanup) ; (void)signal(SIGEMT, (void *)&cleanup) ; (void)signal(SIGFPE, (void *)&cleanup) ; (void)signal(SIGBUS, (void *)&cleanup) ; (void)signal(SIGSEGV, (void *)&cleanup) ; (void)signal(SIGTERM, (void *)&cleanup) ; #ifdef BSD4_2 /* { */ (void)signal(SIGTSTP, (void *)&cleanup) ; #endif /* } */ #endif /* } */ /* create temp file */ fd = #ifdef MSDOS /* { */ open #else /* MSDOS } { */ creat #endif /* !MSDOS } */ ( tmp_name, #ifdef MSDOS /* { */ O_WRONLY | O_CREAT , S_IREAD | S_IWRITE #else /* MSDOS } { */ 0644 #endif /* !MSDOS } */ ) ; (void) close(fd) ; if (( fp_out = fopen(tmp_name, "r+")) == (FILE *)0 ) { fprintf(stderr, txt_complain, *ARGV, tmp_name); exit(-1); } } rslt_1 = get_line(fp_1,line_1,LINE_LN) ; rslt_2 = get_line(fp_2,line_2,LINE_LN) ; while ( (rslt_1 != line_1) || (rslt_2 != line_2) ) { /* new lines */ p_1 = line_1 ; p_2 = line_2 ; current_char = 0 ; c_1 = *p_1 ; c_2 = *p_2 ; while ( ( c_1 != '\0' ) || ( c_2 != '\0' ) ) { current_char++ ; /* warning the order of the following ifs is important*/ if (c_1 == '\0') my_putc(c_2,fp_out) ; else if (c_2 == '\0') my_putc(c_1,fp_out) ; else if (c_1 == '\n') my_putc(c_2,fp_out) ; else if (c_2 == '\n') my_putc(c_1,fp_out) ; else if (c_1 == c_2) my_putc(c_1,fp_out) ; else if (c_1 == ' ') my_putc(c_2,fp_out) ; else if (c_2 == ' ') my_putc(c_1,fp_out) ; /* tab handling is not ideal, a bit of a cludge, but better than nothing */ /* '\t' should be dealt with before '_' */ else if (c_1 == '\t') { my_putc(c_2,fp_out) ; my_putc('\t',fp_out) ; } else if (c_2 == '\t') { my_putc(c_1,fp_out) ; my_putc('\t',fp_out) ; } else if (c_1 == '_') { my_putc('_',fp_out) ; my_putc('\b',fp_out) ; my_putc(c_2,fp_out) ; } else if (c_2 == '_') { if (!silent) my_putc('_',fp_out) ; my_putc('\b',fp_out) ; my_putc(c_1,fp_out) ; } else { #define BELL ((char)7 /* bell*/ ) my_putc(BELL,fp_out) ; if (out_line == 0) { out_line = current_line ; out_char = current_char ; } } if ( c_1 != '\0' ) c_1 = *++p_1 ; if ( c_2 != '\0' ) c_2 = *++p_2 ; } current_line++ ; rslt_1 = get_line(fp_1,line_1,LINE_LN) ; rslt_2 = get_line(fp_2,line_2,LINE_LN) ; } if (out_line) fprintf(stderr, "%s: Error 1st conflicting character at line %d char %d.\n", *ARGV, out_line,(int)out_char); (void)fclose(fp_1); (void)fclose(fp_2); if (output_name == (char *)0 ) { /* output to stdout, whether overlay collision or not */ if (!silent) { rewind(fp_out) ; while ((ch = getc(fp_out)) != EOF) putchar(ch) ; } (void) fclose(fp_out) ; (void) unlink(tmp_name) ; } else { /* output to a file only if no overlay collision */ if ((out_line && !force) || silent) { /* overlay collision */ (void) fclose(fp_out) ; (void) unlink(tmp_name) ; } else { /* no overlay collision */ if ( (*output_name == '-' ) /* stdout */ #ifdef unix /* { */ || ((stat(output_name, &stat_buf) == 0) && (stat_buf.st_nlink > 1) ) #endif /* } */ ) { /* stdout or linked file so overwrite */ rewind(fp_out) ; if (*output_name != '-' ) fp_1 = fopen(output_name,"w"); else fp_1 = stdout ; while ((ch = getc(fp_out)) != EOF) (void)fputc(ch,fp_1) ; (void) fclose(fp_out) ; (void) fclose(fp_1) ; (void) unlink(tmp_name) ; } else (void)rename(tmp_name, output_name) ; } } exit((int)out_line); } my_putc(ch,where) char ch ; FILE *where ; { if (silent) return ; *p_out_array++ = ch ; if (p_out_array - a_out_array > LINE_LN - 5) { *p_out_array = '\0' ; fprintf(stderr, "%s: Aborting, Output line too long.\n%s\n",*ARGV, a_out_array) ; exit(1) ; } if (ch == '\n') { *p_out_array++ = '\0' ; if (f_brother && (index(a_out_array,'_') != (char *)0)) brother() ; fprintf(where,"%s",a_out_array) ; /* for (p_out_array = a_out_array; (ch = *p_out_array++) != '\0'; ) (void)fputc((int)ch,where) ; */ p_out_array = a_out_array ; } } brother() /* Allow for brother that does a single pixel down shift when doing italic bold underlines */ { register int count ; /* spaces to right perforation */ #define XX 100 /* 100 for elite (small) 84 for pica (big) */ #define YY 40 for ( count = XX ; count-- ; putchar(' ') ) ; /* down one pixel each underscore, till brother is stable */ for ( count = YY ; count-- ; ) { putchar('_') ; putchar('\b') ; } /* back space to left margin */ for ( count = XX ; count-- ; putchar('\b') ) ; }