[gnu.utils.bug] patches to GNU diff v1.15

chip@chinacat.unicom.com (Chip Rosenthal) (01/11/91)

--text follows this line--
This patch allows GNU diff 1.15 to run on SCO XENIX and SCO UNIX, and adds
a merged diff format.  For example, using the merged format with the command:

    diff -M76 Distrib/diff.h diff.h

gives the result:

    -------------------------------------+-------------------------------------
    Distrib/diff.h                       | diff.h                              
    --- insert at 85 --------------------+- 86 --------------------------------
					 | #if !defined (INT_MAX) /* SCO UNIX g
    --- insert at 86 --------------------+- 88 --------------------------------
					 | #endif                              
    --- change at 123 -------------------+- 125-128 ---------------------------
      OUTPUT_IFDEF };                    |   OUTPUT_IFDEF,                     
					 |   /* Output merged in side-by-side d
					 |   OUTPUT_MERGED                     
					 | };                                  
    --- insert at 200 -------------------+- 206-208 ---------------------------
					 |                                     
					 | /* Line width for the merged display
					 | EXTERN int line_width;              
    -------------------------------------+-------------------------------------

Two command line switches were added to get the merged format `-M line_width'
and `-m'.  The only difference is that the latter implies a 80-char line width.

The following files are affected by this patch:

    diff.h		merged format support, bugfix for SCO UNIX
    diff.c		merged format support
    analyze.c		merged format support
    alloca.c		bugfix for ansish cpp warnings
    merged.c		new file - print merged format
    Makefile		bugfix for SCO XENIX flags and to make alloca.c work
    make.sco-xenix	new file - see below
    make.sco-unix	new file - see below

About the easiest way to `plug and go' under SCO XENIX or UNIX would be
to link either `make.sco-xenix' or `make.sco-unix' to `makefile', edit
the definitions at the top (most notably `bindir'), and run `make'.

BTW...this stuff has been tested under SCO XENIX 2.3.3OS/2.3.1DS and
SCO UNIX 3.2.1.

--- start of patch -----------------------------------------------------------
Index: diff.h
*** Distrib/diff.h	Sun Jan  6 17:04:45 1991
--- diff.h	Thu Jan 10 18:55:23 1991
***************
*** 83,89 ****
--- 83,91 ----
  
  /* Support old-fashioned C compilers.  */
  #if defined (__STDC__) || defined (__GNUC__)
+ #if !defined (INT_MAX) /* SCO UNIX grabs this through <stdio.h> */
  #include "limits.h"
+ #endif
  #else
  #define INT_MAX 2147483647
  #define CHAR_BIT 8
***************
*** 120,126 ****
    /* Like -f, but output a count of changed lines in each "command" (-n). */
    OUTPUT_RCS,
    /* Output merged #ifdef'd file (-D).  */
!   OUTPUT_IFDEF };
  
  /* True for output styles that are robust,
     i.e. can handle a file that ends in a non-newline.  */
--- 122,131 ----
    /* Like -f, but output a count of changed lines in each "command" (-n). */
    OUTPUT_RCS,
    /* Output merged #ifdef'd file (-D).  */
!   OUTPUT_IFDEF,
!   /* Output merged in side-by-side display (-m). */
!   OUTPUT_MERGED
! };
  
  /* True for output styles that are robust,
     i.e. can handle a file that ends in a non-newline.  */
***************
*** 198,203 ****
--- 203,211 ----
  
  /* Pipe each file's output through pr (-l).  */
  EXTERN int	paginate_flag;
+ 
+ /* Line width for the merged display (-m,-M).  */
+ EXTERN int	line_width;
  
  /* String to use for #ifdef (-D).  */
  EXTERN char *	ifdef_string;
Index: diff.c
*** Distrib/diff.c	Sun Jan  6 17:53:25 1991
--- diff.c	Thu Jan 10 00:41:56 1991
***************
*** 143,153 ****
    msg_chain = NULL;
    msg_chain_end = NULL;
    no_discards = 0;
  
    /* Decode the options.  */
  
    while ((c = getopt_long (argc, argv,
! 			   "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvw",
  			   longopts, &longind)) != EOF)
      {
        if (c == 0)		/* Long option. */
--- 143,154 ----
    msg_chain = NULL;
    msg_chain_end = NULL;
    no_discards = 0;
+   line_width = 0;
  
    /* Decode the options.  */
  
    while ((c = getopt_long (argc, argv,
! 			   "0123456789abBcC:dD:efF:hHiI:lL:mM:nNpqrsS:tTuvw",
  			   longopts, &longind)) != EOF)
      {
        if (c == 0)		/* Long option. */
***************
*** 281,286 ****
--- 282,299 ----
  	    file_label[1] = optarg;
  	  else
  	    fatal ("too many file label options");
+ 	  break;
+ 
+ 	case 'm':
+ 	  /* Make output merged in side-by-side display. */
+ 	  specify_style (OUTPUT_MERGED);
+ 	  line_width = 80;
+ 	  break;
+ 
+ 	case 'M':
+ 	  /* Make output merged in side-by-side display. */
+ 	  specify_style (OUTPUT_MERGED);
+ 	  line_width = atoi(optarg);
  	  break;
  
  	case 'n':
Index: analyze.c
*** Distrib/analyze.c	Sun Jan  6 17:05:11 1991
--- analyze.c	Thu Jan 10 00:53:16 1991
***************
*** 32,37 ****
--- 32,38 ----
  void print_normal_script ();
  void print_rcs_script ();
  void pr_forward_ed_script ();
+ void print_merged_script ();
  void setup_output ();
  
  extern int no_discards;
***************
*** 844,849 ****
--- 845,854 ----
  
  	case OUTPUT_IFDEF:
  	  print_ifdef_script (script);
+ 	  break;
+ 
+ 	case OUTPUT_MERGED:
+ 	  print_merged_script (script);
  	  break;
  	}
  
Index: alloca.c
*** Distrib/alloca.c	Sun Jan  6 17:25:02 1991
--- alloca.c	Thu Jan 10 18:35:07 1991
***************
*** 42,49 ****
  lose
  -- must know STACK_DIRECTION at compile-time
  #endif /* STACK_DIRECTION undefined */
! #endif static
! #endif emacs
  
  #ifdef X3J11
  typedef void	*pointer;		/* generic pointer type */
--- 42,49 ----
  lose
  -- must know STACK_DIRECTION at compile-time
  #endif /* STACK_DIRECTION undefined */
! #endif /* static */
! #endif /* emacs */
  
  #ifdef X3J11
  typedef void	*pointer;		/* generic pointer type */
Index: merged.c
*** /dev/null	Thu Jan 10 21:10:10 1991
--- merged.c	Thu Jan 10 20:52:52 1991
***************
*** 0 ****
--- 1,193 ----
+ /*
+  * The merged diff format added by Chip Rosenthal <chip@chinacat.unicom.com>
+  */
+  
+ #include "diff.h"
+ 
+ #define TABSTOP	8	/* must be a power of two (e.g. 4, 8, etc.) */
+ 
+ #define Fput3(FP,S1,S2,S3) \
+ 	( fputs((S1),(FP)), fputs((S2),(FP)), fputs((S3),(FP)), putc('\n',(FP)) )
+ 
+ #define Strncpy(OUT,IN,LEN) \
+ 	( (OUT)[(LEN)] = '\0', strncpy((OUT),(IN),(LEN)) )
+ 
+ static int field_width;
+ static char *field0_buf, *field1_buf, *tmp_buf;
+ 
+ static void print_merged_hunk();
+ static void expand_field();
+ 
+ extern struct change *find_change();
+ 
+ 
+ void print_merged_script(script)
+ struct changed *script;
+ {
+ 
+ 	/*
+ 	 * Figure out how big a field to print the file differences in.
+ 	 */
+ 	field_width = ( line_width - (sizeof("-+-")-1) ) / 2;
+ 	if ( field_width < 1 ) {
+ 		fputs("diff: bad field width specified\n",stderr);
+ 		exit(1);
+ 	}
+ 
+ 	/*
+ 	 * Create the space for formatting.
+ 	 */
+ 	field0_buf = (char*) xmalloc((unsigned)field_width+1);
+ 	field1_buf = (char*) xmalloc((unsigned)field_width+1);
+ 	tmp_buf = (char*) xmalloc((unsigned)field_width+1);
+ 
+ 	/*
+ 	 * Print the header.
+ 	 */
+ 	expand_field(tmp_buf, (char*)NULL, field_width, '-'),
+ 	Fput3(outfile, tmp_buf, "-+-", tmp_buf);
+ 
+ 	(void) Strncpy(tmp_buf, files[0].name, field_width);
+ 	expand_field(field0_buf, tmp_buf, field_width, ' '),
+ 	(void) Strncpy(tmp_buf, files[1].name, field_width);
+ 	expand_field(field1_buf, tmp_buf, field_width, ' '),
+ 	Fput3(outfile, field0_buf, " | ", field1_buf);
+ 
+ 	/*
+ 	 * Print the hunks.
+ 	 */
+ 	print_script(script, find_change, print_merged_hunk);
+ 
+ 	/*
+ 	 * Print the trailer.
+ 	 */
+ 	expand_field(tmp_buf, (char*)NULL, field_width, '-'),
+ 	Fput3(outfile, tmp_buf, "-+-", tmp_buf);
+ 
+ 	free(field0_buf);
+ 	free(field1_buf);
+ 	free(tmp_buf);
+ }
+ 
+ 
+ static void print_merged_hunk(hunk)
+ struct change *hunk;
+ {
+ 	int first0, last0, first1, last1, deletes, inserts, tr_first, tr_last, len;
+ 	char *action;
+ 	register int i0, i1;
+ 
+ 	/*
+ 	 * Determine range of line numbers involved in each file.
+ 	 */
+ 	analyze_hunk(hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
+ 	if ( deletes > 0 && inserts > 0 )
+ 		action = "change";
+ 	else if ( deletes > 0 )
+ 		action = "delete";
+ 	else if ( inserts > 0 )
+ 		action = "insert";
+ 	else
+ 		return;
+ 
+ 	/*
+ 	 * Print the header for this hunk.
+ 	 */
+ 	translate_range(&files[0], first0, last0, &tr_first, &tr_last);
+ 	if ( tr_last > tr_first )
+ 		(void) sprintf(tmp_buf, "--- %s at %d-%d ", action, tr_first, tr_last);
+ 	else
+ 		(void) sprintf(tmp_buf, "--- %s at %d ", action, tr_last);
+ 	expand_field(field0_buf, tmp_buf, field_width, '-');
+ 
+ 	translate_range(&files[1], first1, last1, &tr_first, &tr_last);
+ 	if ( tr_last > tr_first )
+ 		(void) sprintf(tmp_buf, " %d-%d ", tr_first, tr_last);
+ 	else
+ 		(void) sprintf(tmp_buf, " %d ", tr_last);
+ 	expand_field(field1_buf, tmp_buf, field_width, '-');
+ 
+ 	Fput3(outfile, field0_buf, "-+-", field1_buf);
+ 
+ 	/*
+ 	 * Format and print each line in this hunk.
+ 	 */
+ 	for ( i0 = first0, i1 = first1 ; i0 <= last0 || i1 <= last1 ; ++i0, ++i1 ) {
+ 
+ 		if ( i0 <= last0 ) {
+ 			len = ( files[0].linbuf[i0].length < field_width ?
+ 				files[0].linbuf[i0].length : field_width );
+ 			Strncpy(tmp_buf, files[0].linbuf[i0].text, len);
+ 			expand_field(field0_buf, tmp_buf, field_width, ' ');
+ 		} else {
+ 			expand_field(field0_buf, (char*)NULL, field_width, ' ');
+ 		}
+ 
+ 		if ( i1 <= last1 ) {
+ 			len = ( files[1].linbuf[i1].length < field_width ?
+ 				files[1].linbuf[i1].length : field_width );
+ 			Strncpy(tmp_buf, files[1].linbuf[i1].text, len);
+ 			expand_field(field1_buf, tmp_buf, field_width, ' ');
+ 		} else {
+ 			expand_field(field1_buf, (char*)NULL, field_width, ' ');
+ 		}
+ 
+ 		Fput3(outfile, field0_buf, " | ", field1_buf);
+ 
+ 	}
+ 
+ }
+ 
+ 
+ /*
+  * The expand_field() routine performs two functions.  First, it goes
+  * through "inbuf" and reformats the line doing stuff like expanding
+  * tabs and stripping out newlines.  Second, it expands the text to
+  * "fieldlen" characters, using the "padchar" to fill to this length.
+  * If the "inbuf" is NULL, we just generate a string of the "padchar".
+  */
+ static void expand_field(outbuf,inbuf,fieldlen,padchar)
+ char *outbuf;
+ char *inbuf;
+ int fieldlen;
+ int padchar;
+ {
+ 	int currcol;
+ 
+ 	/*
+ 	 * If no string was passed to us, make one of the full field length.
+ 	 */
+ 	if ( inbuf == NULL ) {
+ 		while ( --fieldlen >= 0 )
+ 			*outbuf++ = padchar;
+ 		*outbuf = '\0';
+ 		return;
+ 	}
+ 
+ 	/*
+ 	 * Go through the string doing translations (tab expansion, etc.).
+ 	 */
+ 	currcol = 1;
+ 	while ( *inbuf != '\0' && fieldlen > 0 ) {
+ 		if ( *inbuf == '\t' ) {
+ 			do {
+ 				*outbuf++ = ' ';
+ 			} while ( --fieldlen >= 0 && !( currcol++ & TABSTOP ) ) ;
+ 			++inbuf;
+ 		} else if ( isascii(*inbuf) && isprint(*inbuf) ) {
+ 			*outbuf++ = *inbuf++;
+ 			++currcol;
+ 			--fieldlen;
+ 		} else {
+ 			++inbuf; /* elide this character */
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Finally, pad it out to the required length.
+ 	 */
+ 	while ( --fieldlen >= 0 )
+ 		*outbuf++ = padchar;
+ 	*outbuf = '\0';
+ }
+ 
Index: Makefile
*** Distrib/Makefile	Sun Jan  6 18:02:56 1991
--- Makefile	Thu Jan 10 19:26:28 1991
***************
*** 38,65 ****
  # Use these definitions for XENIX:
  # There are rumors of bugs in various Xenix's dirent.h and -ldir.  As
  # a result, we suggest using HAVE_NDIR and not using -ldir.
! # CFLAGS = -O -DUSG -DXENIX -DHAVE_NDIR -DHAVE_DIRECT -DNDIR_IN_SYS
! # LIBS = -lx -lPW
  # INSTALL = cp
  
  # Some System V machines do not come with libPW.  If this is true, use
  # the GNU alloca by switching the comment on the following lines.
  ALLOCA = 
! # ALLOCA = $(archpfx)/alloca.o
  
  bindir=/usr/local/bin
  prefix=
  
  # All source files
! srcs=diff.c analyze.c io.c context.c ed.c normal.c ifdef.c util.c dir.c \
! 	version.c diff.h regex.c regex.h limits.h diff3.c \
! 	getopt.c getopt1.c getopt.h alloca.c
  # Object files for diff only.
  objs=$(archpfx)diff.o $(archpfx)analyze.o $(archpfx)io.o $(archpfx)context.o \
!      $(archpfx)ed.o $(archpfx)normal.o $(archpfx)util.o $(archpfx)dir.o \
!      $(archpfx)regex.o $(archpfx)ifdef.o $(archpfx)version.o \
       $(archpfx)getopt.o $(archpfx)getopt1.o
! tapefiles = $(srcs) README diagmeet.note Makefile COPYING ChangeLog
  
  all: $(archpfx)diff $(archpfx)diff3
  
--- 38,65 ----
  # Use these definitions for XENIX:
  # There are rumors of bugs in various Xenix's dirent.h and -ldir.  As
  # a result, we suggest using HAVE_NDIR and not using -ldir.
! # CFLAGS = -O -DUSG -DXENIX -DHAVE_NDIR -DHAVE_DIRECT -DNDIR_IN_SYS -Dconst=
! # LIBS = -lx
  # INSTALL = cp
  
  # Some System V machines do not come with libPW.  If this is true, use
  # the GNU alloca by switching the comment on the following lines.
  ALLOCA = 
! # ALLOCA = $(archpfx)alloca.o
  
  bindir=/usr/local/bin
  prefix=
  
  # All source files
! srcs=diff.c analyze.c io.c context.c ed.c normal.c ifdef.c merged.c \
! 	util.c dir.c version.c regex.c diff3.c getopt.c getopt1.c alloca.c
! hdrs=diff.h regex.h limits.h getopt.h 
  # Object files for diff only.
  objs=$(archpfx)diff.o $(archpfx)analyze.o $(archpfx)io.o $(archpfx)context.o \
!      $(archpfx)ed.o $(archpfx)normal.o $(archpfx)merged.o $(archpfx)util.o \
!      $(archpfx)dir.o $(archpfx)regex.o $(archpfx)ifdef.o $(archpfx)version.o \
       $(archpfx)getopt.o $(archpfx)getopt1.o
! tapefiles = $(srcs) $(hdrs) README diagmeet.note Makefile COPYING ChangeLog
  
  all: $(archpfx)diff $(archpfx)diff3
  
***************
*** 66,78 ****
  $(archpfx)diff3: $(archpfx)diff3.o
  	$(CC) -o $(archpfx)diff3 $(CFLAGS) $(LDFLAGS) $(archpfx)diff3.o $(LIBS)
  
! $(archpfx)diff: $(objs)
! 	$(CC) -o $(archpfx)diff $(CFLAGS) $(LDFLAGS) $(objs) $(LIBS)
  
  $(objs): diff.h
  
  $(archpfx)context.o $(archpfx)diff.o: regex.h
  
  $(archpfx)diff3.o: diff3.c
  	$(CC) -c $(CFLAGS) -DDIFF_PROGRAM=\"$(bindir)/diff\" diff3.c \
   $(OUTPUT_OPTION)
--- 66,80 ----
  $(archpfx)diff3: $(archpfx)diff3.o
  	$(CC) -o $(archpfx)diff3 $(CFLAGS) $(LDFLAGS) $(archpfx)diff3.o $(LIBS)
  
! $(archpfx)diff: $(objs) $(ALLOCA)
! 	$(CC) -o $(archpfx)diff $(CFLAGS) $(LDFLAGS) $(objs) $(ALLOCA) $(LIBS)
  
  $(objs): diff.h
  
  $(archpfx)context.o $(archpfx)diff.o: regex.h
  
+ $(archpfx)alloca.o: alloca.c diff.h
+ 
  $(archpfx)diff3.o: diff3.c
  	$(CC) -c $(CFLAGS) -DDIFF_PROGRAM=\"$(bindir)/diff\" diff3.c \
   $(OUTPUT_OPTION)
***************
*** 91,96 ****
--- 93,103 ----
  
  $(prefix)$(bindir)/diff3: $(archpfx)diff3
  	$(INSTALL) $(archpfx)diff3 $(prefix)$(bindir)/diff3
+ 
+ lint: diff.lint
+ 
+ diff.lint: $(srcs)
+ 	lint $(CFLAGS) $(LDFLAGS) $(srcs) $(LIBS) >$@
  
  diff.tar: $(tapefiles)
  	mkdir tmp
Index: make.sco-xenix
*** /dev/null	Thu Jan 10 21:10:10 1991
--- make.sco-xenix	Thu Jan 10 19:26:50 1991
***************
*** 0 ****
--- 1,16 ----
+ SHELL = /bin/sh
+ CC = cc
+ CFLAGS = -O -DUSG -DXENIX -DHAVE_NDIR -DHAVE_DIRECT -DNDIR_IN_SYS -Dconst=
+ LIBS = -lx
+ INSTALL = cp
+ ALLOCA = alloca.o
+ bindir = /local/bin
+ 
+ ENV = CC="$(CC)" CFLAGS="$(CFLAGS)" LIBS="$(LIBS)" INSTALL="$(INSTALL)" \
+ 	ALLOCA="$(ALLOCA)" bindir="$(bindir)"
+ 
+ all:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ clean:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ install:		;  $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ lint:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ 
Index: make.sco-unix
*** /dev/null	Thu Jan 10 21:10:10 1991
--- make.sco-unix	Thu Jan 10 19:26:42 1991
***************
*** 0 ****
--- 1,16 ----
+ SHELL = /bin/sh
+ CC = cc
+ CFLAGS = -O -DUSG -Dconst=
+ LIBS =
+ INSTALL = cp
+ ALLOCA = alloca.o
+ bindir = /local/bin
+ 
+ ENV = CC="$(CC)" CFLAGS="$(CFLAGS)" LIBS="$(LIBS)" INSTALL="$(INSTALL)" \
+ 	ALLOCA="$(ALLOCA)" bindir="$(bindir)"
+ 
+ all:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ clean:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ install:		;  $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ lint:			; $(ENV) $(MAKE) -e$(MAKEFLAGS) -f Makefile $@
+ 
--- end of patch -------------------------------------------------------------
-- 
Chip Rosenthal  512-482-8260  |  If software look-and-feel can be protected,
Unicom Systems Development    |  then I'd like to claim a copyright upon
<chip@chinacat.Unicom.COM>    |  `Memory fault - core dumped'.