[comp.bugs.sys5] /usr/bin/sdiff forces -b; also an improvement

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