home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume7 / patch2 / patch7 < prev    next >
Internet Message Format  |  1987-02-01  |  24KB

  1. From ihnp4!sdcrdcf!lwall Sat Jan 31 10:42:41 1987
  2. Received: by mirror.TMC.COM (4.12/UUCP-Project/rel-1.0/08-20-86)
  3.     id AA22616; Sat, 31 Jan 87 10:41:49 est
  4. Received: by ihnp4.ATT.COM id AA16645; 31 Jan 87 07:18:03 CST (Sat)
  5. Received: by sdc.uucp (4.12/sdcrdcf)
  6.     id AA20106; Fri, 30 Jan 87 23:02:07 pst
  7. Date: Fri, 30 Jan 87 23:02:07 pst
  8. From: ihnp4!sdcrdcf!lwall (Larry Wall)
  9. Message-Id: <8701310702.AA20106@sdc.uucp>
  10. Subject: patch 2.0 patch #7
  11. Organization: System Development Corporation, Santa Monica
  12. Apparently-To: hplabs!seismo!mirror!source-archives
  13. Status: R
  14.  
  15. System: patch version 2.0
  16. Patch #: 7
  17. Priority: LOW (MEDIUM if you're trying to install mangled patches)
  18. Subject: Some mangled patches result in misleading diagnostics.
  19. From: lwall@sdcrdcf.UUCP
  20.  
  21. Description:
  22.     Certain kinds of mangled patches (namely ones in which the line
  23.     numbers are wrong) can give misleading error messages.  At best,
  24.     the line numbers (in the patch file) are wrong.  At worst, the
  25.     error message reads, "core dumped".  At least I hope that was
  26.     the worst.
  27.  
  28. Repeat-By:
  29.     Take a new-style context diff, one which adds some lines, and edit
  30.     the replacement line numbers so that the maximim line number is one
  31.     less than it ought to be.  Run patch.  Watch it puke.
  32.  
  33.     Make an old-style diff of the same patch.  Run patch.  Note the
  34.     uninformative error message with incorrect line numbers.
  35.  
  36. Fix:    From rn, say "| patch -d DIR", where DIR is your patch source
  37.     directory.  Outside of rn, say "cd DIR; patch <thisarticle".
  38.     If you don't have the patch program, apply the following by hand,
  39.     or get patch.
  40.  
  41.     If patch indicates that patchlevel is the wrong version, you may need
  42.     to apply one or more previous patches, or the patch may already
  43.     have been applied.  See the patchlevel.h file to find out what has or
  44.     has not been applied.  In any event, don't continue with the patch.
  45.  
  46.     If you are missing previous patches they can be obtained from me:
  47.  
  48.     Larry Wall
  49.     {allegra,burdvax,cbosgd,hplabs,ihnp4,sdcsvax}!sdcrdcf!lwall
  50.  
  51.     If you send a mail message of the following form (only left-justified)
  52.     it will greatly speed processing:
  53.  
  54.     Subject: Command
  55.     @SH mailpatch PATH patch 2.0 LIST
  56.            ^ note the c
  57.  
  58.     where PATH is a return path FROM ME TO YOU in bang notation, and LIST
  59.     is the number of one or more patches you need, separated by spaces,
  60.     commas, and/or hyphens.  Saying 35- says everything from 35 to the end.
  61.  
  62. Index: patchlevel.h
  63. Prereq: 6
  64. 1c1
  65. < #define PATCHLEVEL 6
  66. ---
  67. > #define PATCHLEVEL 7
  68.  
  69. Index: patch.c
  70. Prereq: 2.0.1.2
  71. *** patch.c.old    Fri Jan 30 22:48:49 1987
  72. *** patch.c    Fri Jan 30 22:49:04 1987
  73. ***************
  74. *** 1,5
  75.   char rcsid[] =
  76. !     "$Header: patch.c,v 2.0.1.2 86/11/21 09:39:15 lwall Exp $";
  77.   
  78.   /* patch - a program to apply diffs to original files
  79.    *
  80.  
  81. --- 1,5 -----
  82.   char rcsid[] =
  83. !     "$Header: patch.c,v 2.0.1.3 87/01/30 22:45:50 lwall Exp $";
  84.   
  85.   /* patch - a program to apply diffs to original files
  86.    *
  87. ***************
  88. *** 9,14
  89.    * money off of it, or pretend that you wrote it.
  90.    *
  91.    * $Log:    patch.c,v $
  92.    * Revision 2.0.1.2  86/11/21  09:39:15  lwall
  93.    * Fuzz factor caused offset of installed lines.
  94.    * 
  95.  
  96. --- 9,18 -----
  97.    * money off of it, or pretend that you wrote it.
  98.    *
  99.    * $Log:    patch.c,v $
  100. +  * Revision 2.0.1.3  87/01/30  22:45:50  lwall
  101. +  * Improved diagnostic on sync error.
  102. +  * Moved do_ed_script() to pch.c.
  103. +  * 
  104.    * Revision 2.0.1.2  86/11/21  09:39:15  lwall
  105.    * Fuzz factor caused offset of installed lines.
  106.    * 
  107. ***************
  108. *** 88,94
  109.   LINENUM locate_hunk();
  110.   void abort_hunk();
  111.   void apply_hunk();
  112. - void do_ed_script();
  113.   void init_output();
  114.   void init_reject();
  115.   void copy_till();
  116.  
  117. --- 92,97 -----
  118.   LINENUM locate_hunk();
  119.   void abort_hunk();
  120.   void apply_hunk();
  121.   void init_output();
  122.   void init_reject();
  123.   void copy_till();
  124. ***************
  125. *** 584,592
  126.       }
  127.       else {
  128.           if (pch_char(new) != pch_char(old)) {
  129. !         say3("Out-of-sync patch, lines %ld,%ld\n",
  130. !             pch_hunk_beg() + old - 1,
  131. !             pch_hunk_beg() + new - 1);
  132.   #ifdef DEBUGGING
  133.           say3("oldchar = '%c', newchar = '%c'\n",
  134.               pch_char(old), pch_char(new));
  135.  
  136. --- 587,595 -----
  137.       }
  138.       else {
  139.           if (pch_char(new) != pch_char(old)) {
  140. !         say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
  141. !             pch_hunk_beg() + old,
  142. !             pch_hunk_beg() + new);
  143.   #ifdef DEBUGGING
  144.           say3("oldchar = '%c', newchar = '%c'\n",
  145.               pch_char(old), pch_char(new));
  146. ***************
  147. *** 646,713
  148.       if (R_do_defines && def_state != OUTSIDE) {
  149.       fputs(end_defined, ofp);
  150.       }
  151. - }
  152. - /* Apply an ed script by feeding ed itself. */
  153. - void
  154. - do_ed_script()
  155. - {
  156. -     Reg1 char *t;
  157. -     Reg2 long beginning_of_this_line;
  158. -     Reg3 bool this_line_is_command = FALSE;
  159. -     Reg4 FILE *pipefp;
  160. -     FILE *popen();
  161. -     if (!skip_rest_of_patch) {
  162. -     Unlink(TMPOUTNAME);
  163. -     copy_file(filearg[0], TMPOUTNAME);
  164. -     if (verbose)
  165. -         Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
  166. -     else
  167. -         Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
  168. -     pipefp = popen(buf, "w");
  169. -     }
  170. -     for (;;) {
  171. -     beginning_of_this_line = ftell(pfp);
  172. -     if (pgets(buf, sizeof buf, pfp) == Nullch) {
  173. -         next_intuit_at(beginning_of_this_line);
  174. -         break;
  175. -     }
  176. -     for (t=buf; isdigit(*t) || *t == ','; t++) ;
  177. -     this_line_is_command = (isdigit(*buf) &&
  178. -       (*t == 'd' || *t == 'c' || *t == 'a') );
  179. -     if (this_line_is_command) {
  180. -         if (!skip_rest_of_patch)
  181. -         fputs(buf, pipefp);
  182. -         if (*t != 'd') {
  183. -         while (pgets(buf, sizeof buf, pfp) != Nullch) {
  184. -             if (!skip_rest_of_patch)
  185. -             fputs(buf, pipefp);
  186. -             if (strEQ(buf, ".\n"))
  187. -             break;
  188. -         }
  189. -         }
  190. -     }
  191. -     else {
  192. -         next_intuit_at(beginning_of_this_line);
  193. -         break;
  194. -     }
  195. -     }
  196. -     if (skip_rest_of_patch)
  197. -     return;
  198. -     fprintf(pipefp, "w\n");
  199. -     fprintf(pipefp, "q\n");
  200. -     Fflush(pipefp);
  201. -     Pclose(pipefp);
  202. -     ignore_signals();
  203. -     if (move_file(TMPOUTNAME, outname) < 0) {
  204. -     toutkeep = TRUE;
  205. -     chmod(TMPOUTNAME, filemode);
  206. -     }
  207. -     else
  208. -     chmod(outname, filemode);
  209. -     set_signals();
  210.   }
  211.   
  212.   /* Open the new file. */
  213.  
  214. --- 649,654 -----
  215.       if (R_do_defines && def_state != OUTSIDE) {
  216.       fputs(end_defined, ofp);
  217.       }
  218.   }
  219.   
  220.   /* Open the new file. */
  221.  
  222. Index: pch.c
  223. Prereq: 2.0.1.4
  224. *** pch.c.old    Fri Jan 30 22:50:06 1987
  225. *** pch.c    Fri Jan 30 22:50:30 1987
  226. ***************
  227. *** 1,4
  228. ! /* $Header: pch.c,v 2.0.1.4 87/01/05 16:59:53 lwall Exp $
  229.    *
  230.    * $Log:    pch.c,v $
  231.    * Revision 2.0.1.4  87/01/05  16:59:53  lwall
  232.  
  233. --- 1,4 -----
  234. ! /* $Header: pch.c,v 2.0.1.5 87/01/30 22:47:42 lwall Exp $
  235.    *
  236.    * $Log:    pch.c,v $
  237.    * Revision 2.0.1.5  87/01/30  22:47:42  lwall
  238. ***************
  239. *** 1,6
  240.   /* $Header: pch.c,v 2.0.1.4 87/01/05 16:59:53 lwall Exp $
  241.    *
  242.    * $Log:    pch.c,v $
  243.    * Revision 2.0.1.4  87/01/05  16:59:53  lwall
  244.    * New-style context diffs caused double call to free().
  245.    * 
  246.  
  247. --- 1,9 -----
  248.   /* $Header: pch.c,v 2.0.1.5 87/01/30 22:47:42 lwall Exp $
  249.    *
  250.    * $Log:    pch.c,v $
  251. +  * Revision 2.0.1.5  87/01/30  22:47:42  lwall
  252. +  * Improved responses to mangled patches.
  253. +  * 
  254.    * Revision 2.0.1.4  87/01/05  16:59:53  lwall
  255.    * New-style context diffs caused double call to free().
  256.    * 
  257. ***************
  258. *** 42,47
  259.   static int hunkmax = INITHUNKMAX;    /* size of above arrays to begin with */
  260.   static int p_indent;            /* indent to patch */
  261.   static LINENUM p_base;            /* where to intuit this time */
  262.   static LINENUM p_start;            /* where intuit found a patch */
  263.   static LINENUM p_efake = -1;        /* end of faked up lines--don't free */
  264.   static LINENUM p_bfake = -1;        /* beg of faked up lines */
  265.  
  266. --- 45,51 -----
  267.   static int hunkmax = INITHUNKMAX;    /* size of above arrays to begin with */
  268.   static int p_indent;            /* indent to patch */
  269.   static LINENUM p_base;            /* where to intuit this time */
  270. + static LINENUM p_bline;            /* line # of p_base */
  271.   static LINENUM p_start;            /* where intuit found a patch */
  272.   static LINENUM p_sline;            /* and the line number for it */
  273.   static LINENUM p_hunk_beg;        /* line number of current hunk */
  274. ***************
  275. *** 43,48
  276.   static int p_indent;            /* indent to patch */
  277.   static LINENUM p_base;            /* where to intuit this time */
  278.   static LINENUM p_start;            /* where intuit found a patch */
  279.   static LINENUM p_efake = -1;        /* end of faked up lines--don't free */
  280.   static LINENUM p_bfake = -1;        /* beg of faked up lines */
  281.   
  282.  
  283. --- 47,54 -----
  284.   static LINENUM p_base;            /* where to intuit this time */
  285.   static LINENUM p_bline;            /* line # of p_base */
  286.   static LINENUM p_start;            /* where intuit found a patch */
  287. + static LINENUM p_sline;            /* and the line number for it */
  288. + static LINENUM p_hunk_beg;        /* line number of current hunk */
  289.   static LINENUM p_efake = -1;        /* end of faked up lines--don't free */
  290.   static LINENUM p_bfake = -1;        /* beg of faked up lines */
  291.   
  292. ***************
  293. *** 80,86
  294.       fatal2("patch file %s not found\n", filename);
  295.       Fstat(fileno(pfp), &filestat);
  296.       p_filesize = filestat.st_size;
  297. !     next_intuit_at(0L);            /* start at the beginning */
  298.       set_hunkmax();
  299.   }
  300.   
  301.  
  302. --- 86,92 -----
  303.       fatal2("patch file %s not found\n", filename);
  304.       Fstat(fileno(pfp), &filestat);
  305.       p_filesize = filestat.st_size;
  306. !     next_intuit_at(0L,1L);            /* start at the beginning */
  307.       set_hunkmax();
  308.   }
  309.   
  310. ***************
  311. *** 155,161
  312.           "an ed script" );
  313.       if (p_indent && verbose)
  314.       say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
  315. !     skip_to(p_start);
  316.       while (filearg[0] == Nullch) {
  317.       if (force) {
  318.           say1("No file to patch.  Skipping...\n");
  319.  
  320. --- 161,167 -----
  321.           "an ed script" );
  322.       if (p_indent && verbose)
  323.       say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
  324. !     skip_to(p_start,p_sline);
  325.       while (filearg[0] == Nullch) {
  326.       if (force) {
  327.           say1("No file to patch.  Skipping...\n");
  328. ***************
  329. *** 192,197
  330.       Reg4 long this_line = 0;
  331.       Reg5 long previous_line;
  332.       Reg6 long first_command_line = -1;
  333.       Reg7 bool last_line_was_command = FALSE;
  334.       Reg8 bool this_is_a_command = FALSE;
  335.       Reg9 bool stars_last_line = FALSE;
  336.  
  337. --- 198,204 -----
  338.       Reg4 long this_line = 0;
  339.       Reg5 long previous_line;
  340.       Reg6 long first_command_line = -1;
  341. +     long fcl_line;
  342.       Reg7 bool last_line_was_command = FALSE;
  343.       Reg8 bool this_is_a_command = FALSE;
  344.       Reg9 bool stars_last_line = FALSE;
  345. ***************
  346. *** 210,215
  347.   
  348.       ok_to_create_file = FALSE;
  349.       Fseek(pfp, p_base, 0);
  350.       for (;;) {
  351.       previous_line = this_line;
  352.       last_line_was_command = this_is_a_command;
  353.  
  354. --- 217,223 -----
  355.   
  356.       ok_to_create_file = FALSE;
  357.       Fseek(pfp, p_base, 0);
  358. +     p_input_line = p_bline - 1;
  359.       for (;;) {
  360.       previous_line = this_line;
  361.       last_line_was_command = this_is_a_command;
  362. ***************
  363. *** 216,221
  364.       stars_last_line = stars_this_line;
  365.       this_line = ftell(pfp);
  366.       indent = 0;
  367.       if (fgets(buf, sizeof buf, pfp) == Nullch) {
  368.           if (first_command_line >= 0L) {
  369.                       /* nothing but deletes!? */
  370.  
  371. --- 224,230 -----
  372.       stars_last_line = stars_this_line;
  373.       this_line = ftell(pfp);
  374.       indent = 0;
  375. +     p_input_line++;
  376.       if (fgets(buf, sizeof buf, pfp) == Nullch) {
  377.           if (first_command_line >= 0L) {
  378.                       /* nothing but deletes!? */
  379. ***************
  380. *** 220,225
  381.           if (first_command_line >= 0L) {
  382.                       /* nothing but deletes!? */
  383.           p_start = first_command_line;
  384.           retval = ED_DIFF;
  385.           goto scan_exit;
  386.           }
  387.  
  388. --- 229,235 -----
  389.           if (first_command_line >= 0L) {
  390.                       /* nothing but deletes!? */
  391.           p_start = first_command_line;
  392. +         p_sline = fcl_line;
  393.           retval = ED_DIFF;
  394.           goto scan_exit;
  395.           }
  396. ***************
  397. *** 225,230
  398.           }
  399.           else {
  400.           p_start = this_line;
  401.           retval = 0;
  402.           goto scan_exit;
  403.           }
  404.  
  405. --- 235,241 -----
  406.           }
  407.           else {
  408.           p_start = this_line;
  409. +         p_sline = p_input_line;
  410.           retval = 0;
  411.           goto scan_exit;
  412.           }
  413. ***************
  414. *** 240,245
  415.         (*t == 'd' || *t == 'c' || *t == 'a') );
  416.       if (first_command_line < 0L && this_is_a_command) { 
  417.           first_command_line = this_line;
  418.           p_indent = indent;        /* assume this for now */
  419.       }
  420.       if (!stars_last_line && strnEQ(s, "*** ", 4))
  421.  
  422. --- 251,257 -----
  423.         (*t == 'd' || *t == 'c' || *t == 'a') );
  424.       if (first_command_line < 0L && this_is_a_command) { 
  425.           first_command_line = this_line;
  426. +         fcl_line = p_input_line;
  427.           p_indent = indent;        /* assume this for now */
  428.       }
  429.       if (!stars_last_line && strnEQ(s, "*** ", 4))
  430. ***************
  431. *** 263,268
  432.         strEQ(s, ".\n") ) {
  433.           p_indent = indent;
  434.           p_start = first_command_line;
  435.           retval = ED_DIFF;
  436.           goto scan_exit;
  437.       }
  438.  
  439. --- 275,281 -----
  440.         strEQ(s, ".\n") ) {
  441.           p_indent = indent;
  442.           p_start = first_command_line;
  443. +         p_sline = fcl_line;
  444.           retval = ED_DIFF;
  445.           goto scan_exit;
  446.       }
  447. ***************
  448. *** 277,282
  449.           s++;
  450.           p_indent = indent;
  451.           p_start = previous_line;
  452.           retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
  453.           goto scan_exit;
  454.       }
  455.  
  456. --- 290,296 -----
  457.           s++;
  458.           p_indent = indent;
  459.           p_start = previous_line;
  460. +         p_sline = p_input_line - 1;
  461.           retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
  462.           goto scan_exit;
  463.       }
  464. ***************
  465. *** 284,289
  466.         last_line_was_command &&
  467.         (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
  468.           p_start = previous_line;
  469.           p_indent = indent;
  470.           retval = NORMAL_DIFF;
  471.           goto scan_exit;
  472.  
  473. --- 298,304 -----
  474.         last_line_was_command &&
  475.         (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
  476.           p_start = previous_line;
  477. +         p_sline = p_input_line - 1;
  478.           p_indent = indent;
  479.           retval = NORMAL_DIFF;
  480.           goto scan_exit;
  481. ***************
  482. *** 352,358
  483.   /* Remember where this patch ends so we know where to start up again. */
  484.   
  485.   void
  486. ! next_intuit_at(file_pos)
  487.   long file_pos;
  488.   {
  489.       p_base = file_pos;
  490.  
  491. --- 367,373 -----
  492.   /* Remember where this patch ends so we know where to start up again. */
  493.   
  494.   void
  495. ! next_intuit_at(file_pos,file_line)
  496.   long file_pos;
  497.   long file_line;
  498.   {
  499. ***************
  500. *** 354,359
  501.   void
  502.   next_intuit_at(file_pos)
  503.   long file_pos;
  504.   {
  505.       p_base = file_pos;
  506.   }
  507.  
  508. --- 369,375 -----
  509.   void
  510.   next_intuit_at(file_pos,file_line)
  511.   long file_pos;
  512. + long file_line;
  513.   {
  514.       p_base = file_pos;
  515.       p_bline = file_line;
  516. ***************
  517. *** 356,361
  518.   long file_pos;
  519.   {
  520.       p_base = file_pos;
  521.   }
  522.   
  523.   /* Basically a verbose fseek() to the actual diff listing. */
  524.  
  525. --- 372,378 -----
  526.   long file_line;
  527.   {
  528.       p_base = file_pos;
  529. +     p_bline = file_line;
  530.   }
  531.   
  532.   /* Basically a verbose fseek() to the actual diff listing. */
  533. ***************
  534. *** 361,367
  535.   /* Basically a verbose fseek() to the actual diff listing. */
  536.   
  537.   void
  538. ! skip_to(file_pos)
  539.   long file_pos;
  540.   {
  541.       char *ret;
  542.  
  543. --- 378,384 -----
  544.   /* Basically a verbose fseek() to the actual diff listing. */
  545.   
  546.   void
  547. ! skip_to(file_pos,file_line)
  548.   long file_pos;
  549.   long file_line;
  550.   {
  551. ***************
  552. *** 363,368
  553.   void
  554.   skip_to(file_pos)
  555.   long file_pos;
  556.   {
  557.       char *ret;
  558.   
  559.  
  560. --- 380,386 -----
  561.   void
  562.   skip_to(file_pos,file_line)
  563.   long file_pos;
  564. + long file_line;
  565.   {
  566.       char *ret;
  567.   
  568. ***************
  569. *** 379,384
  570.       }
  571.       else
  572.       Fseek(pfp, file_pos, 0);
  573.   }
  574.   
  575.   /* True if there is more of the current diff listing to process. */
  576.  
  577. --- 397,403 -----
  578.       }
  579.       else
  580.       Fseek(pfp, file_pos, 0);
  581. +     p_input_line = file_line - 1;
  582.   }
  583.   
  584.   /* True if there is more of the current diff listing to process. */
  585. ***************
  586. *** 419,424
  587.                       /* # of copiable lines in ptrn */
  588.   
  589.       ret = pgets(buf, sizeof buf, pfp);
  590.       if (ret == Nullch || strnNE(buf, "********", 8)) {
  591.           next_intuit_at(line_beginning);
  592.           return FALSE;
  593.  
  594. --- 438,444 -----
  595.                       /* # of copiable lines in ptrn */
  596.   
  597.       ret = pgets(buf, sizeof buf, pfp);
  598. +     p_input_line++;
  599.       if (ret == Nullch || strnNE(buf, "********", 8)) {
  600.           next_intuit_at(line_beginning,p_input_line);
  601.           return FALSE;
  602. ***************
  603. *** 420,426
  604.   
  605.       ret = pgets(buf, sizeof buf, pfp);
  606.       if (ret == Nullch || strnNE(buf, "********", 8)) {
  607. !         next_intuit_at(line_beginning);
  608.           return FALSE;
  609.       }
  610.       p_context = 100;
  611.  
  612. --- 440,446 -----
  613.       ret = pgets(buf, sizeof buf, pfp);
  614.       p_input_line++;
  615.       if (ret == Nullch || strnNE(buf, "********", 8)) {
  616. !         next_intuit_at(line_beginning,p_input_line);
  617.           return FALSE;
  618.       }
  619.       p_context = 100;
  620. ***************
  621. *** 424,429
  622.           return FALSE;
  623.       }
  624.       p_context = 100;
  625.       while (p_end < p_max) {
  626.           line_beginning = ftell(pfp);
  627.           ret = pgets(buf, sizeof buf, pfp);
  628.  
  629. --- 444,450 -----
  630.           return FALSE;
  631.       }
  632.       p_context = 100;
  633. +     p_hunk_beg = p_input_line + 1;
  634.       while (p_end < p_max) {
  635.           line_beginning = ftell(pfp);
  636.           ret = pgets(buf, sizeof buf, pfp);
  637. ***************
  638. *** 427,432
  639.       while (p_end < p_max) {
  640.           line_beginning = ftell(pfp);
  641.           ret = pgets(buf, sizeof buf, pfp);
  642.           if (ret == Nullch) {
  643.           if (p_max - p_end < 4)
  644.               Strcpy(buf, "  \n");  /* assume blank lines got chopped */
  645.  
  646. --- 448,454 -----
  647.       while (p_end < p_max) {
  648.           line_beginning = ftell(pfp);
  649.           ret = pgets(buf, sizeof buf, pfp);
  650. +         p_input_line++;
  651.           if (ret == Nullch) {
  652.           if (p_max - p_end < 4)
  653.               Strcpy(buf, "  \n");  /* assume blank lines got chopped */
  654. ***************
  655. *** 438,444
  656.               fatal1("Unexpected end of file in patch.\n");
  657.           }
  658.           }
  659. -         p_input_line++;
  660.           p_end++;
  661.           assert(p_end < hunkmax);
  662.           p_char[p_end] = *buf;
  663.  
  664. --- 460,465 -----
  665.               fatal1("Unexpected end of file in patch.\n");
  666.           }
  667.           }
  668.           p_end++;
  669.           assert(p_end < hunkmax);
  670.           p_char[p_end] = *buf;
  671. ***************
  672. *** 491,498
  673.           break;
  674.           case '-':
  675.           if (buf[1] == '-') {
  676. !             if (p_end != p_ptrn_lines + 1 &&
  677. !             p_end != p_ptrn_lines + 2) {
  678.               if (p_end == 1) {
  679.                   /* `old' lines were omitted - set up to fill */
  680.                   /* them in from 'new' context lines. */
  681.  
  682. --- 512,520 -----
  683.           break;
  684.           case '-':
  685.           if (buf[1] == '-') {
  686. !             if (repl_beginning ||
  687. !             (p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
  688. !             {
  689.               if (p_end == 1) {
  690.                   /* `old' lines were omitted - set up to fill */
  691.                   /* them in from 'new' context lines. */
  692. ***************
  693. *** 502,510
  694.                   fillcnt = p_ptrn_lines;
  695.               }
  696.               else {
  697. !                 if (repl_beginning && repl_could_be_missing){
  698. !                 repl_missing = TRUE;
  699. !                 goto hunk_done;
  700.                   }
  701.                   fatal3("Unexpected --- at line %ld: %s",
  702.                   p_input_line, buf);
  703.  
  704. --- 524,537 -----
  705.                   fillcnt = p_ptrn_lines;
  706.               }
  707.               else {
  708. !                 if (repl_beginning) {
  709. !                 if (repl_could_be_missing){
  710. !                     repl_missing = TRUE;
  711. !                     goto hunk_done;
  712. !                 }
  713. !                 fatal3(
  714. ! "Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
  715. !                     p_input_line, p_hunk_beg + repl_beginning);
  716.                   }
  717.                   else {
  718.                   fatal4(
  719. ***************
  720. *** 506,513
  721.                   repl_missing = TRUE;
  722.                   goto hunk_done;
  723.                   }
  724. !                 fatal3("Unexpected --- at line %ld: %s",
  725. !                 p_input_line, buf);
  726.               }
  727.               }
  728.               repl_beginning = p_end;
  729.  
  730. --- 533,546 -----
  731.   "Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
  732.                       p_input_line, p_hunk_beg + repl_beginning);
  733.                   }
  734. !                 else {
  735. !                 fatal4(
  736. ! "%s \"---\" at line %ld--check line numbers at line %ld.\n",
  737. !                     (p_end <= p_ptrn_lines
  738. !                     ? "Premature"
  739. !                     : "Overdue" ),
  740. !                     p_input_line, p_hunk_beg);
  741. !                 }
  742.               }
  743.               }
  744.               repl_beginning = p_end;
  745. ***************
  746. *** 649,655
  747.           p_bfake = filldst;        /* remember where not to free() */
  748.           p_efake = filldst + fillcnt - 1;
  749.           while (fillcnt-- > 0) {
  750. !         while (p_char[fillsrc] != ' ')
  751.               fillsrc++;
  752.           p_line[filldst] = p_line[fillsrc];
  753.           p_char[filldst] = p_char[fillsrc];
  754.  
  755. --- 682,688 -----
  756.           p_bfake = filldst;        /* remember where not to free() */
  757.           p_efake = filldst + fillcnt - 1;
  758.           while (fillcnt-- > 0) {
  759. !         while (fillsrc <= p_end && p_char[fillsrc] != ' ')
  760.               fillsrc++;
  761.           if (fillsrc > p_end)
  762.               fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
  763. ***************
  764. *** 651,656
  765.           while (fillcnt-- > 0) {
  766.           while (p_char[fillsrc] != ' ')
  767.               fillsrc++;
  768.           p_line[filldst] = p_line[fillsrc];
  769.           p_char[filldst] = p_char[fillsrc];
  770.           p_len[filldst] = p_len[fillsrc];
  771.  
  772. --- 684,692 -----
  773.           while (fillcnt-- > 0) {
  774.           while (fillsrc <= p_end && p_char[fillsrc] != ' ')
  775.               fillsrc++;
  776. +         if (fillsrc > p_end)
  777. +             fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
  778. +             p_hunk_beg);
  779.           p_line[filldst] = p_line[fillsrc];
  780.           p_char[filldst] = p_char[fillsrc];
  781.           p_len[filldst] = p_len[fillsrc];
  782. ***************
  783. *** 678,684
  784.       ret = pgets(buf, sizeof buf, pfp);
  785.       p_input_line++;
  786.       if (ret == Nullch || !isdigit(*buf)) {
  787. !         next_intuit_at(line_beginning);
  788.           return FALSE;
  789.       }
  790.       p_first = (LINENUM)atol(buf);
  791.  
  792. --- 714,720 -----
  793.       ret = pgets(buf, sizeof buf, pfp);
  794.       p_input_line++;
  795.       if (ret == Nullch || !isdigit(*buf)) {
  796. !         next_intuit_at(line_beginning,p_input_line);
  797.           return FALSE;
  798.       }
  799.       p_first = (LINENUM)atol(buf);
  800. ***************
  801. *** 994,999
  802.   LINENUM
  803.   pch_hunk_beg()
  804.   {
  805. !     return p_input_line - p_end - 1;
  806.   }
  807.   
  808.  
  809. --- 1030,1036 -----
  810.   LINENUM
  811.   pch_hunk_beg()
  812.   {
  813. !     return p_hunk_beg;
  814.   }
  815.   
  816.   /* Apply an ed script by feeding ed itself. */
  817. ***************
  818. *** 997,999
  819.       return p_input_line - p_end - 1;
  820.   }
  821.   
  822.  
  823. --- 1033,1098 -----
  824.       return p_hunk_beg;
  825.   }
  826.   
  827. + /* Apply an ed script by feeding ed itself. */
  828. + void
  829. + do_ed_script()
  830. + {
  831. +     Reg1 char *t;
  832. +     Reg2 long beginning_of_this_line;
  833. +     Reg3 bool this_line_is_command = FALSE;
  834. +     Reg4 FILE *pipefp;
  835. +     FILE *popen();
  836. +     if (!skip_rest_of_patch) {
  837. +     Unlink(TMPOUTNAME);
  838. +     copy_file(filearg[0], TMPOUTNAME);
  839. +     if (verbose)
  840. +         Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
  841. +     else
  842. +         Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
  843. +     pipefp = popen(buf, "w");
  844. +     }
  845. +     for (;;) {
  846. +     beginning_of_this_line = ftell(pfp);
  847. +     if (pgets(buf, sizeof buf, pfp) == Nullch) {
  848. +         next_intuit_at(beginning_of_this_line,p_input_line);
  849. +         break;
  850. +     }
  851. +     p_input_line++;
  852. +     for (t=buf; isdigit(*t) || *t == ','; t++) ;
  853. +     this_line_is_command = (isdigit(*buf) &&
  854. +       (*t == 'd' || *t == 'c' || *t == 'a') );
  855. +     if (this_line_is_command) {
  856. +         if (!skip_rest_of_patch)
  857. +         fputs(buf, pipefp);
  858. +         if (*t != 'd') {
  859. +         while (pgets(buf, sizeof buf, pfp) != Nullch) {
  860. +             p_input_line++;
  861. +             if (!skip_rest_of_patch)
  862. +             fputs(buf, pipefp);
  863. +             if (strEQ(buf, ".\n"))
  864. +             break;
  865. +         }
  866. +         }
  867. +     }
  868. +     else {
  869. +         next_intuit_at(beginning_of_this_line,p_input_line);
  870. +         break;
  871. +     }
  872. +     }
  873. +     if (skip_rest_of_patch)
  874. +     return;
  875. +     fprintf(pipefp, "w\n");
  876. +     fprintf(pipefp, "q\n");
  877. +     Fflush(pipefp);
  878. +     Pclose(pipefp);
  879. +     ignore_signals();
  880. +     if (move_file(TMPOUTNAME, outname) < 0) {
  881. +     toutkeep = TRUE;
  882. +     chmod(TMPOUTNAME, filemode);
  883. +     }
  884. +     else
  885. +     chmod(outname, filemode);
  886. +     set_signals();
  887. + }
  888.  
  889. Index: pch.h
  890. Prereq: 2.0
  891. *** pch.h.old    Fri Jan 30 22:49:38 1987
  892. *** pch.h    Fri Jan 30 22:49:40 1987
  893. ***************
  894. *** 1,4
  895. ! /* $Header: pch.h,v 2.0 86/09/17 15:39:57 lwall Exp $
  896.    *
  897.    * $Log:    pch.h,v $
  898.    * Revision 2.0  86/09/17  15:39:57  lwall
  899.  
  900. --- 1,4 -----
  901. ! /* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $
  902.    *
  903.    * $Log:    pch.h,v $
  904.    * Revision 2.0.1.1  87/01/30  22:47:16  lwall
  905. ***************
  906. *** 1,6
  907.   /* $Header: pch.h,v 2.0 86/09/17 15:39:57 lwall Exp $
  908.    *
  909.    * $Log:    pch.h,v $
  910.    * Revision 2.0  86/09/17  15:39:57  lwall
  911.    * Baseline for netwide release.
  912.    * 
  913.  
  914. --- 1,9 -----
  915.   /* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $
  916.    *
  917.    * $Log:    pch.h,v $
  918. +  * Revision 2.0.1.1  87/01/30  22:47:16  lwall
  919. +  * Added do_ed_script().
  920. +  * 
  921.    * Revision 2.0  86/09/17  15:39:57  lwall
  922.    * Baseline for netwide release.
  923.    * 
  924. ***************
  925. *** 30,32
  926.   char pch_char();
  927.   char *pfetch();
  928.   char *pgets();
  929.  
  930. --- 33,36 -----
  931.   char pch_char();
  932.   char *pfetch();
  933.   char *pgets();
  934. + void do_ed_script();
  935.  
  936.