ksb@mentor.cc.purdue.edu (Kevin Braunsdorf) (09/05/90)
[ This is an unofficial patch to patch by Larry Wall. I've contacted Larry and he said I could send this out because he was busy with other things. I'm sure an official patch will be out later. -- ksb ] Priority: high (if you use `patch -D foo ...') Description: Patch will generate incorrect #if ... #else ... #endif constructs given some new-style context diff hunks. Version: $Header: patch.c,v 2.0.1.6 88/06/22 20:46:39 lwall Locked $ Patch level: 12 Repeat-By: Extract the shell archieve below then, make Note that unifdef exits with an error unifdef: Error in test line 4: Premature EOF in ifdef. (see broken.script for all the expected output). Fix: Apply the patch file (patch.c.patch) to patch.c with: patch patch.c <patch.c.patch rebuild and install patch. Then make clean make and note that patch now passes this test (see OK.script). # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # bug # This archive created: Tue Sep 4 13:46:34 1990 # By: Kevin Braunsdorf (Purdue UNIX Group) mkdir bug cd bug sed 's/^K//' << \SHAR_EOF > patch.c.patch K*** /usr/src/unsup/bin/patch/patch.c Thu Jun 23 16:35:06 1988 K--- ./patch.c Thu Aug 16 13:46:02 1990 K*************** K*** 402,422 **** K } K if (chdir(s) < 0) K fatal2("Can't cd to %s.\n", s); K break; K case 'D': K do_defines = TRUE; K if (!*++s) { K Argc--,Argv++; K s = Argv[0]; K } K! if (!isalpha(*s)) K fatal1("Argument to -D not an identifier.\n"); K Sprintf(if_defined, "#ifdef %s\n", s); K Sprintf(not_defined, "#ifndef %s\n", s); K Sprintf(end_defined, "#endif /* %s */\n", s); K break; K case 'e': K diff_type = ED_DIFF; K break; K case 'f': K force = TRUE; K--- 402,422 ---- K } K if (chdir(s) < 0) K fatal2("Can't cd to %s.\n", s); K break; K case 'D': K do_defines = TRUE; K if (!*++s) { K Argc--,Argv++; K s = Argv[0]; K } K! if (!isalpha(*s) && '_' != *s) K fatal1("Argument to -D not an identifier.\n"); K Sprintf(if_defined, "#ifdef %s\n", s); K Sprintf(not_defined, "#ifndef %s\n", s); K Sprintf(end_defined, "#endif /* %s */\n", s); K break; K case 'e': K diff_type = ED_DIFF; K break; K case 'f': K force = TRUE; K*************** K*** 595,672 **** K } K else if (def_state == IN_IFDEF) { K fputs(else_defined, ofp); K def_state = IN_ELSE; K } K fputs(pfetch(old), ofp); K } K last_frozen_line++; K old++; K } K! else if (new > pat_end) K break; K else if (pch_char(new) == '+') { K copy_till(where + old - 1); K if (R_do_defines) { K if (def_state == IN_IFNDEF) { K fputs(else_defined, ofp); K def_state = IN_ELSE; K } K else if (def_state == OUTSIDE) { K fputs(if_defined, ofp); K def_state = IN_IFDEF; K } K } K fputs(pfetch(new), ofp); K new++; K } K! else { K! if (pch_char(new) != pch_char(old)) { K! say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", K! pch_hunk_beg() + old, K! pch_hunk_beg() + new); K #ifdef DEBUGGING K! say3("oldchar = '%c', newchar = '%c'\n", K! pch_char(old), pch_char(new)); K #endif K! my_exit(1); K } K! if (pch_char(new) == '!') { K! copy_till(where + old - 1); K if (R_do_defines) { K! fputs(not_defined, ofp); K! def_state = IN_IFNDEF; K } K! while (pch_char(old) == '!') { K! if (R_do_defines) { K! fputs(pfetch(old), ofp); K! } K! last_frozen_line++; K! old++; K! } K! if (R_do_defines) { K! fputs(else_defined, ofp); K! def_state = IN_ELSE; K! } K! while (pch_char(new) == '!') { K! fputs(pfetch(new), ofp); K! new++; K! } K! if (R_do_defines) { K! fputs(end_defined, ofp); K! def_state = OUTSIDE; K! } K! } K! else { K! assert(pch_char(new) == ' '); K old++; K new++; K } K } K } K if (new <= pat_end && pch_char(new) == '+') { K copy_till(where + old - 1); K if (R_do_defines) { K if (def_state == OUTSIDE) { K fputs(if_defined, ofp); K def_state = IN_IFDEF; K } K--- 595,671 ---- K } K else if (def_state == IN_IFDEF) { K fputs(else_defined, ofp); K def_state = IN_ELSE; K } K fputs(pfetch(old), ofp); K } K last_frozen_line++; K old++; K } K! else if (new > pat_end) { K break; K+ } K else if (pch_char(new) == '+') { K copy_till(where + old - 1); K if (R_do_defines) { K if (def_state == IN_IFNDEF) { K fputs(else_defined, ofp); K def_state = IN_ELSE; K } K else if (def_state == OUTSIDE) { K fputs(if_defined, ofp); K def_state = IN_IFDEF; K } K } K fputs(pfetch(new), ofp); K new++; K } K! else if (pch_char(new) != pch_char(old)) { K! say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", K! pch_hunk_beg() + old, K! pch_hunk_beg() + new); K #ifdef DEBUGGING K! say3("oldchar = '%c', newchar = '%c'\n", K! pch_char(old), pch_char(new)); K #endif K! my_exit(1); K! } K! else if (pch_char(new) == '!') { K! copy_till(where + old - 1); K! if (R_do_defines) { K! fputs(not_defined, ofp); K! def_state = IN_IFNDEF; K } K! while (pch_char(old) == '!') { K if (R_do_defines) { K! fputs(pfetch(old), ofp); K } K! last_frozen_line++; K old++; K+ } K+ if (R_do_defines) { K+ fputs(else_defined, ofp); K+ def_state = IN_ELSE; K+ } K+ while (pch_char(new) == '!') { K+ fputs(pfetch(new), ofp); K new++; K+ } K+ } K+ else { K+ assert(pch_char(new) == ' '); K+ old++; K+ new++; K+ if (R_do_defines && def_state != OUTSIDE) { K+ fputs(end_defined, ofp); K+ def_state = OUTSIDE; K } K } K } K if (new <= pat_end && pch_char(new) == '+') { K copy_till(where + old - 1); K if (R_do_defines) { K if (def_state == OUTSIDE) { K fputs(if_defined, ofp); K def_state = IN_IFDEF; K } SHAR_EOF sed 's/^K//' << \SHAR_EOF > file1 Kline 1 Kline 2 Kline 3 Kline 4 Kline 5 Kline 6 Kline 7 Kline 8 Kline 9 Kline 10 SHAR_EOF sed 's/^K//' << \SHAR_EOF > file2 Kline 1 Kline 2 Kline 3 Kline 3a Kline 3b Kline 4 Kline 5 Kline 6 Kline 7 Kline 7a Kline 8 Kline 9a Kline 10 SHAR_EOF sed 's/^K//' << \SHAR_EOF > Makefile K K# K# handy Makefile to test patch before and after the ksb fix K# K Kall: file1 file2 shouldbe1 shouldbe2 K cmp -s shouldbe1 file1 && echo defined side OK K cmp -s shouldbe2 file2 && echo undefined side OK K Kclean: FRC K rm -f shouldbe[12] file1.patch test test.orig test~ K K Kfile1.patch: file1 file2 K -diff -c file1 file2 >file1.patch K Ktest: file1 file1.patch K cp file1 test K patch -DKSB test <file1.patch K Kshouldbe1: test K -unifdef -UKSB test >shouldbe1 K Kshouldbe2: test K -unifdef -DKSB test >shouldbe2 K K KFRC: SHAR_EOF sed 's/^K//' << \SHAR_EOF > broken.script KScript started on Tue Sep 4 13:38:28 1990 Kmentor /userb/ksb/uxg/bug 358 make K diff -c file1 file2 >file1.patch K*** Error code 1 (ignored) K cp file1 test K patch -DKSB test <file1.patch KHmm... Looks like a new-style context diff to me... KThe text leading up to this was: K-------------------------- K|*** file1 Tue Sep 4 13:01:09 1990 K|--- file2 Tue Sep 4 13:01:36 1990 K-------------------------- KPatching file test using Plan A... KHunk #1 succeeded at 1. Kdone K unifdef -UKSB test >shouldbe1 Kunifdef: Error in test line 4: Premature EOF in ifdef. K*** Error code 2 KMake: . Stop. Kmentor /userb/ksb/uxg/bug 359 exit K Kscript done on Tue Sep 4 13:38:36 1990 SHAR_EOF sed 's/^K//' << \SHAR_EOF > OK.script KScript started on Tue Sep 4 13:44:58 1990 Kmentor /userb/ksb/uxg/bug 387 make clean K rm -f shouldbe[12] file1.patch test test.orig test~ Kmentor /userb/ksb/uxg/bug 388 make K diff -c file1 file2 >file1.patch K*** Error code 1 (ignored) K cp file1 test K patch -DKSB test <file1.patch KHmm... Looks like a new-style context diff to me... KThe text leading up to this was: K-------------------------- K|*** file1 Tue Sep 4 13:01:09 1990 K|--- file2 Tue Sep 4 13:01:36 1990 K-------------------------- KPatching file test using Plan A... KHunk #1 succeeded at 1. Kdone K unifdef -UKSB test >shouldbe1 K*** Error code 1 (ignored) K unifdef -DKSB test >shouldbe2 K*** Error code 1 (ignored) K cmp -s shouldbe1 file1 && echo defined side OK Kdefined side OK K cmp -s shouldbe2 file2 && echo undefined side OK Kundefined side OK Kmentor /userb/ksb/uxg/bug 389 exit K Kscript done on Tue Sep 4 13:45:11 1990 SHAR_EOF cd .. # End of shell archive exit 0