Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site sdcrdcf.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!ittvax!dcdwest!sdcsvax!sdcrdcf!lwall
From: lwall@sdcrdcf.UUCP (Larry Wall)
Newsgroups: net.sources.bugs
Subject: patch bug #2
Message-ID: <1532@sdcrdcf.UUCP>
Date: Wed, 5-Dec-84 14:33:25 EST
Article-I.D.: sdcrdcf.1532
Posted: Wed Dec  5 14:33:25 1984
Date-Received: Fri, 7-Dec-84 06:04:28 EST
Reply-To: lwall@sdcrdcf.UUCP (Larry Wall)
Organization: System Development Corp. R+D, Santa Monica
Lines: 257

System: patch version 1.2
Bug #: 2
Priority: MEDIUM
Subject: patch won't work on files with munged whitespace

Description:
	Patch uses a strncmp to match context lines with the input file.
	This works as long as the input file hasn't been munged by an
	editor or some other program that translates spaces to tabs or tabs
	to spaces.

Repeat-By:
	Run a source file through expand(1), and then try to do a patch on it.

Fix:	Add a -l switch to do "loose" string comparison.

	From rn, say "| patch -d DIR", where DIR is your patch source
	directory.  Outside of rn, say "cd DIR; patch = 0)),
  		   pfetch(pline),
  		   pch_line_len(pline) ))
  	    return FALSE;

--- 709,721 -----
      register LINENUM pat_lines = pch_ptrn_lines();
  
      for (pline = 1, iline=base+offset; pline <= pat_lines; pline++,iline++) {
! 	if (canonicalize) {
! 	    if (!similar(ifetch(iline,(offset >= 0)),
! 			 pfetch(pline),
! 			 pch_line_len(pline) ))
! 		return FALSE;
! 	}
! 	else if (strnNE(ifetch(iline,(offset >= 0)),
  		   pfetch(pline),
  		   pch_line_len(pline) ))
  	    return FALSE;
***************
*** 707,712
  	    return FALSE;
      }
      return TRUE;
  }
  
  /* input file with indexable lines abstract type */

--- 721,753 -----
  	    return FALSE;
      }
      return TRUE;
+ }
+ 
+ /* match two lines with canonicalized white space */
+ 
+ bool
+ similar(a,b,len)
+ register char *a, *b;
+ register int len;
+ {
+     while (len) {
+ 	if (isspace(*b)) {		/* whitespace (or \n) to match? */
+ 	    if (!isspace(*a))		/* no corresponding whitespace? */
+ 		return FALSE;
+ 	    while (len && isspace(*b) && *b != '\n')
+ 		b++,len--;		/* skip pattern whitespace */
+ 	    while (isspace(*a) && *a != '\n')
+ 		a++;			/* skip target whitespace */
+ 	    if (*a == '\n' || *b == '\n')
+ 		return (*a == *b);	/* should end in sync */
+ 	}
+ 	else if (*a++ != *b++)		/* match non-whitespace chars */
+ 	    return FALSE;
+ 	else
+ 	    len--;			/* probably not necessary */
+     }
+     return TRUE;			/* actually, this is not reached */
+ 					/* since there is always a \n */
  }
  
  /* input file with indexable lines abstract type */

Index: patch.nr
***************
*** 1,4
! ''' $Header:$
  ''' 
  ''' $Log:$
  .de Sh

--- 1,4 -----
! ''' $Header: patch.nr,v 1.2.1.2 84/12/05 11:06:55 lwall Exp $
  ''' 
  ''' $Log:	patch.nr,v $
  ''' Revision 1.2.1.2  84/12/05  11:06:55  lwall
***************
*** 1,6
  ''' $Header:$
  ''' 
! ''' $Log:$
  .de Sh
  .br
  .ne 5

--- 1,15 -----
  ''' $Header: patch.nr,v 1.2.1.2 84/12/05 11:06:55 lwall Exp $
  ''' 
! ''' $Log:	patch.nr,v $
! ''' Revision 1.2.1.2  84/12/05  11:06:55  lwall
! ''' Added -l switch, and noted bistability bug.
! ''' 
! ''' Revision 1.2.1.1  84/12/04  17:23:39  lwall
! ''' Branch for sdcrdcf changes.
! ''' 
! ''' Revision 1.2  84/12/04  17:22:02  lwall
! ''' Baseline version.
! ''' 
  .de Sh
  .br
  .ne 5
***************
*** 175,180
  .I patch
  to interpret the patch file as an ed script.
  .TP 5
  .B \-n
  forces
  .I patch

--- 184,197 -----
  .I patch
  to interpret the patch file as an ed script.
  .TP 5
+ .B \-l
+ causes the pattern matching to be done loosely, in case the tabs and
+ spaces have been munged in you input file.
+ Any sequence of whitespace in the pattern line will match any sequence
+ in the input file.
+ Normal characters must still match exactly.
+ Each line of the context must still match a line in the input file.
+ .TP 5
  .B \-n
  forces
  .I patch
***************
*** 251,253
  .SH BUGS
  Could be smarter about partial matches, excessively \&deviant offsets and
  swapped code, but that would take an extra pass.

--- 268,275 -----
  .SH BUGS
  Could be smarter about partial matches, excessively \&deviant offsets and
  swapped code, but that would take an extra pass.
+ .PP
+ If you apply a patch you've already applied,
+ .I patch
+ will think it is a reversed patch, and un-apply the patch.
+ This could be construed as a feature.