geoff@desint.UUCP (Geoff Kuenning) (02/01/88)
Summary: /usr/bin/sdiff forces the -b switch on the user even if it's unwanted. Problem: /usr/bin/sdiff's "-o switch is a very useful tool for integrating different branches of the same program. However, this utility is limited by one questionable design decision. This is that that sdiff invokes diff with the -b (ignore whitespace differences) switch. This means that an integration of two pieces of code will miss any changes in indentation. Repeat-By: Suppose file "sdtest1.c" contains: a = b; and file "sdtest2.c" has been changed to: if (c == d) a = b; If you then execute the command: sdiff -o sdtest3.c sdtest1.c sdtest2.c and type "r" to the only prompt, you will get: if (c == d) a = b; On the other hand, if you use: sdiff -o sdtest3.c sdtest2.c sdtest1.c and type "l" to the prompt, you will get a file identical to sdtest2.c, as you should. Fix: The following context diff modifies sdiff to correct this problem, plus a minor argument-processing oversight, and also allows you to select an editor other than "ed" for use with the "e" command. Problems corrected: (1) sdiff always invoked diff with the -b switch, which hid some differences that the user might consider important. (2) The (erroneous) command "sdiff -o" caused a core dump on no-NULL-dereference machines, instead of a usage message. Improvements added: (1) The "e" command now respects the EDITOR environment variable. (2) There is now a "-e" switch which can be used to override the default editor and the EDITOR environment variable. (3) The "-b" and "-h" flags can now be passed on to diff. Geoff Kuenning geoff@ITcorp.com {uunet,trwrb}!desint!geoff Note: if you want to discuss this, please use mail, as I don't normally read these newsgroups. Index: sdiff.c *** sdiff.c.old Sun Jan 31 14:53:35 1988 --- sdiff.c Sun Jan 31 14:53:41 1988 *************** *** 10,16 */ ! /* sdiff [-l] [-s] [-w #] [-o output] file1 file2 * does side by side diff listing * -l leftside only for identical lines * -s silent; only print differences --- 10,17 ----- */ ! /* sdiff [-b] [-h] [-l] [-s] [-w #] ! * [-e editor] [-o output] file1 file2 * does side by side diff listing * -b, -h are passed on to diff * -l leftside only for identical lines *************** *** 12,17 /* sdiff [-l] [-s] [-w #] [-o output] file1 file2 * does side by side diff listing * -l leftside only for identical lines * -s silent; only print differences * -w # width of output --- 13,19 ----- /* sdiff [-b] [-h] [-l] [-s] [-w #] * [-e editor] [-o output] file1 file2 * does side by side diff listing + * -b, -h are passed on to diff * -l leftside only for identical lines * -s silent; only print differences * -w # width of output *************** *** 15,20 * -l leftside only for identical lines * -s silent; only print differences * -w # width of output * -o output interactive creation of new output commands: s silent; do not print identical lines --- 17,23 ----- * -l leftside only for identical lines * -s silent; only print differences * -w # width of output + * -e editor editor to use instead of 'ed' with -o option * -o output interactive creation of new output commands: s silent; do not print identical lines *************** *** 27,32 e call ed with empty file q exit from program * functions: cmd decode diff commands put1 output left side --- 30,39 ----- e call ed with empty file q exit from program + * If the EDITOR environment variable is defined and there is + * no '-e' switch, the value of EDITOR will be used as the + * default editor. + * functions: cmd decode diff commands put1 output left side *************** *** 52,58 char BLANKS[100] = " "; char GUTTER[WGUTTER] = " "; ! char *DIFF = "diff -b "; char diffcmd[BMAX]; char inbuf[10]; --- 59,65 ----- char BLANKS[100] = " "; char GUTTER[WGUTTER] = " "; ! char *DIFF = "diff "; char diffcmd[BMAX]; char inbuf[10]; *************** *** 68,73 char *pgmname; char *file1; FILE *fdes1; char buf1[BMAX+1]; --- 75,87 ----- char *pgmname; + char *bflag = ""; /* "-b " if -b switch specified */ + char *hflag = ""; /* "-h " if -h switch specified */ + char *editor; /* Editor to be invoked */ + char *editname; /* Editor with pathname removed. Zero if editor has + switches or if the pathname is not absolute. + */ + char *file1; FILE *fdes1; char buf1[BMAX+1]; *************** *** 105,110 char **argv; { extern onintr(); int com; register int n1, n2, n; --- 119,125 ----- char **argv; { extern onintr(); + extern char *getenv(), *strrchr(); int com; register int n1, n2, n; *************** *** 116,121 signal(SIGPIPE,onintr); if (signal(SIGTERM,SIG_IGN)!=SIG_IGN) signal(SIGTERM,onintr); pgmname = argv[0]; while(--argc>1 && **++argv == '-'){ switch(*++*argv){ --- 131,138 ----- signal(SIGPIPE,onintr); if (signal(SIGTERM,SIG_IGN)!=SIG_IGN) signal(SIGTERM,onintr); + if ((editor = getenv ("EDITOR")) == 0) + editor = "/bin/ed"; pgmname = argv[0]; while(--argc>1 && **++argv == '-'){ switch(*++*argv){ *************** *** 134,139 llen = LMAX; break; case 'l': leftonly++; break; --- 151,164 ----- llen = LMAX; break; + case 'b': + bflag = "-b "; + break; + + case 'h': + hflag = "-h "; + break; + case 'l': leftonly++; break; *************** *** 141,146 case 's': silent++; break; case 'o': oflag++; argc--; --- 166,179 ----- case 's': silent++; break; + + case 'e': + if (argc > 0) { + argc--; + editor = *++argv; + } + break; + case 'o': if (argc > 0) { oflag++; *************** *** 142,150 silent++; break; case 'o': ! oflag++; ! argc--; ! ofile = *++argv; break; default: error("Illegal argument: %s",*argv); --- 175,185 ----- break; case 'o': ! if (argc > 0) { ! oflag++; ! argc--; ! ofile = *++argv; ! } break; default: error("Illegal argument: %s",*argv); *************** *** 151,157 } } if(argc != 2){ ! fprintf(stderr,"Usage: sdiff [-l] [-s] [-o output] [-w #] file1 file2\n"); exit(2); } --- 186,192 ----- } } if(argc != 2){ ! fprintf(stderr,"Usage: sdiff [-b] [-h] [-l] [-s] [-o output] [-e editor] [-w #] file1 file2\n"); exit(2); } *************** *** 155,160 exit(2); } file1 = *argv++; file2 = *argv; file1=filename(file1,file2); --- 190,201 ----- exit(2); } + if (editor[0] == '/' + && strrchr (editor, ' ') == 0 && strrchr (editor, '\t') == 0) + editname = strrchr (editor, '/') + 1; + else + editname = 0; + file1 = *argv++; file2 = *argv; file1=filename(file1,file2); *************** *** 181,186 } /* Call DIFF command */ strcpy(diffcmd,DIFF); strcat(diffcmd,file1); strcat(diffcmd," "); strcat(diffcmd,file2); --- 222,229 ----- } /* Call DIFF command */ strcpy(diffcmd,DIFF); + strcat(diffcmd,hflag); + strcat(diffcmd,bflag); strcat(diffcmd,file1); strcat(diffcmd," "); strcat(diffcmd,file2); *************** *** 602,608 int (*oldintr) (); ! switch(pid=fork()){ case -1: error("Cannot fork",""); --- 645,652 ----- int (*oldintr) (); ! if (editname) { /* Can we just exec the editor? */ ! switch(pid=fork()){ case -1: error("Cannot fork",""); *************** *** 604,614 switch(pid=fork()){ ! case -1: ! error("Cannot fork",""); ! case 0: ! execl("/bin/ed", "ed", file, 0); ! } oldintr = signal(SIGINT, SIG_IGN); /*ignore interrupts while in ed */ while(pid != wait(&i)) --- 648,659 ----- if (editname) { /* Can we just exec the editor? */ switch(pid=fork()){ ! case -1: ! error("Cannot fork",""); ! case 0: ! execl(editor, editname, file, 0); ! error("Cannot exec '%s'", editor); ! } /*ignore interrupts while in editor */ oldintr = signal(SIGINT, SIG_IGN); *************** *** 610,619 execl("/bin/ed", "ed", file, 0); } ! oldintr = signal(SIGINT, SIG_IGN); /*ignore interrupts while in ed */ ! while(pid != wait(&i)) ! ; ! signal(SIGINT,oldintr); /*restore previous interrupt proc */ } char *filename(pa1, pa2) --- 655,673 ----- error("Cannot exec '%s'", editor); } ! /*ignore interrupts while in editor */ ! oldintr = signal(SIGINT, SIG_IGN); ! while(pid != wait(&i)) ! ; ! signal(SIGINT,oldintr); /*restore previous interrupt proc */ ! } else { /* Can't exec, must use system () */ ! char editcmd[BMAX]; ! ! strcpy (editcmd, editor); ! strcat (editcmd, " "); ! strcat (editcmd, file); ! system (editcmd); ! } } char *filename(pa1, pa2) -- Geoff Kuenning geoff@ITcorp.com {uunet,trwrb}!desint!geoff