+-+-+-+ Beginning of part 12 +-+-+-+ X`009p_len = tp_len; X#endif X`009if (p_char == Nullch) X`009 free((char*)p_char); X`009p_char = tp_char; X`009return FALSE;`009`009/* not enough memory to swap hunk! */ X `125 X X /* now turn the new into the old */ X X i = p_ptrn_lines + 1; X if (tp_char[i] == '\n') `123`009`009/* account for possible blank line */ X`009blankline = TRUE; X`009i++; X `125 X if (p_efake >= 0) `123`009`009`009/* fix non-freeable ptr range */ X`009if (p_efake <= i) X`009 n = p_end - i + 1; X`009else X`009 n = -i; X`009p_efake += n; X`009p_bfake += n; X `125 X for (n=0; i <= p_end; i++,n++) `123 X`009p_line[n] = tp_line[i]; X`009p_char[n] = tp_char[i]; X`009if (p_char[n] == '+') X`009 p_char[n] = '-'; X`009p_len[n] = tp_len[i]; X `125 X if (blankline) `123 X`009i = p_ptrn_lines + 1; X`009p_line[n] = tp_line[i]; X`009p_char[n] = tp_char[i]; X`009p_len[n] = tp_len[i]; X`009n++; X `125 X assert(p_char[0] == '='); X p_char[0] = '*'; X for (s=p_line[0]; *s; s++) X`009if (*s == '-') X`009 *s = '*'; X X /* now turn the old into the new */ X X assert(tp_char[0] == '*'); X tp_char[0] = '='; X for (s=tp_line[0]; *s; s++) X`009if (*s == '*') X`009 *s = '-'; X for (i=0; n <= p_end; i++,n++) `123 X`009p_line[n] = tp_line[i]; X`009p_char[n] = tp_char[i]; X`009if (p_char[n] == '-') X`009 p_char[n] = '+'; X`009p_len[n] = tp_len[i]; X `125 X assert(i == p_ptrn_lines + 1); X i = p_ptrn_lines; X p_ptrn_lines = p_repl_lines; X p_repl_lines = i; X#ifndef lint X if (tp_line == Null(char**)) X`009free((char*)tp_line); X if (tp_len == Null(short*)) X`009free((char*)tp_len); X#endif X if (tp_char == Nullch) X`009free((char*)tp_char); X return TRUE; X`125 X X/* Return the specified line position in the old file of the old context. */ X XLINENUM Xpch_first() X`123 X return p_first; X`125 X X/* Return the number of lines of old context. */ X XLINENUM Xpch_ptrn_lines() X`123 X return p_ptrn_lines; X`125 X X/* Return the probable line position in the new file of the first line. */ X XLINENUM Xpch_newfirst() X`123 X return p_newfirst; X`125 X X/* Return the number of lines in the replacement text including context. */ X XLINENUM Xpch_repl_lines() X`123 X return p_repl_lines; X`125 X X/* Return the number of lines in the whole hunk. */ X XLINENUM Xpch_end() X`123 X return p_end; X`125 X X/* Return the number of context lines before the first changed line. */ X XLINENUM Xpch_context() X`123 X return p_context; X`125 X X/* Return the length of a particular patch line. */ X Xshort Xpch_line_len(line) XLINENUM line; X`123 X return p_len[line]; X`125 X X/* Return the control character (+, -, *, !, etc) for a patch line. */ X Xchar Xpch_char(line) XLINENUM line; X`123 X return p_char[line]; X`125 X X/* Return a pointer to a particular patch line. */ X Xchar * Xpfetch(line) XLINENUM line; X`123 X return p_line[line]; X`125 X X/* Return where in the patch file this hunk began, for error messages. */ X XLINENUM Xpch_hunk_beg() X`123 X return p_hunk_beg; X`125 X X/* Apply an ed script by feeding ed itself. */ X Xvoid Xdo_ed_script() X`123 X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X Reg4 FILE *pipefp; X FILE *popen(); X X if (!skip_rest_of_patch) `123 X`009Unlink(TMPOUTNAME); X`009copy_file(filearg[0], TMPOUTNAME); X`009if (verbose) X`009 Sprintf(buf, "/bin/ed %s", TMPOUTNAME); X`009else X`009 Sprintf(buf, "/bin/ed - %s", TMPOUTNAME); X`009pipefp = popen(buf, "w"); X `125 X for (;;) `123 X`009beginning_of_this_line = ftell(pfp); X`009if (pgets(buf, sizeof buf, pfp) == Nullch) `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X`009p_input_line++; X`009for (t=buf; isdigit(*t) `124`124 *t == ','; t++) ; X`009this_line_is_command = (isdigit(*buf) && X`009 (*t == 'd' `124`124 *t == 'c' `124`124 *t == 'a') ); X`009if (this_line_is_command) `123 X`009 if (!skip_rest_of_patch) X`009`009fputs(buf, pipefp); X`009 if (*t != 'd') `123 X`009`009while (pgets(buf, sizeof buf, pfp) != Nullch) `123 X`009`009 p_input_line++; X`009`009 if (!skip_rest_of_patch) X`009`009`009fputs(buf, pipefp); X`009`009 if (strEQ(buf, ".\n")) X`009`009`009break; X`009`009`125 X`009 `125 X`009`125 X`009else `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X `125 X if (skip_rest_of_patch) X`009return; X fprintf(pipefp, "w\n"); X fprintf(pipefp, "q\n"); X Fflush(pipefp); X Pclose(pipefp); X ignore_signals(); X if (move_file(TMPOUTNAME, outname) < 0) `123 X`009toutkeep = TRUE; X`009chmod(TMPOUTNAME, filemode); X `125 X else X`009chmod(outname, filemode); X set_signals(1); X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "PCH.H" $ CHECKSUM_IS = 1833039821 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $ X * X * $Log:`009pch.h,v $ X * Revision 2.0.1.1 87/01/30 22:47:16 lwall X * Added do_ed_script(). X * X * Revision 2.0 86/09/17 15:39:57 lwall X * Baseline for netwide release. X * X */ X XEXT FILE *pfp INIT(Nullfp);`009`009/* patch file pointer */ X Xvoid re_patch(); Xvoid open_patch_file(); Xvoid set_hunkmax(); Xvoid grow_hunkmax(); Xbool there_is_another_patch(); Xint intuit_diff_type(); Xvoid next_intuit_at(); Xvoid skip_to(); Xbool another_hunk(); Xbool pch_swap(); Xchar *pfetch(); Xshort pch_line_len(); XLINENUM pch_first(); XLINENUM pch_ptrn_lines(); XLINENUM pch_newfirst(); XLINENUM pch_repl_lines(); XLINENUM pch_end(); XLINENUM pch_context(); XLINENUM pch_hunk_beg(); Xchar pch_char(); Xchar *pfetch(); Xchar *pgets(); Xvoid do_ed_script(); $ GOSUB UNPACK_FILE $ FILE_IS = "PCH.PATCH" $ CHECKSUM_IS = 0 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X $ GOSUB UNPACK_FILE $ FILE_IS = "PCH.VMS_PATCH" $ CHECKSUM_IS = 2131642568 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X*** pch.c_unix X--- pch.c X************** X*** 1063,1068 X void X do_ed_script() X `123 X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X--- 1063,1072 ----- X void X do_ed_script() X `123 X+ #ifdef VMS X+ fprintf (stderr, "Ed scripts not supported\n"); X+ exit(1); X+ #else X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X************** X*** 1120,1123 X else X `009chmod(outname, filemode); X set_signals(1); X `125 X--- 1124,1128 ----- X else X chmod(outname, filemode); X set_signals(1); X+ #endif X `125 $ GOSUB UNPACK_FILE $ FILE_IS = "README." $ CHECKSUM_IS = 1647594057 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X`009`009`009Patch Kit, Version 2.0 X X`009`009 Copyright (c) 1988, Larry Wall X XYou may copy the patch kit in whole or in part as long as you don't try to Xmake money off it, or pretend that you wrote it. X-------------------------------------------------------------------------- X XPlease read all the directions below before you proceed any further, and Xthen follow them carefully. Failure to do so may void your warranty. :-) X XAfter you have unpacked your kit, you should have all the files listed Xin MANIFEST. X XInstallation X X1) Run Configure. This will figure out various things about your system. X Some things Configure will figure out for itself, other things it will X ask you about. It will then proceed to make config.h, config.sh, and X Makefile. X X You might possibly have to trim # comments from the front of Configure X if your sh doesn't handle them, but all other # comments will be taken X care of. X X If you don't have sh, you'll have to rip the prototype of config.h out X of Configure and generate the defines by hand. X X2) Glance through config.h to make sure system dependencies are correct. V Most of them should have been taken care of by running the Configure scri Xpt. X X If you have any additional changes to make to the C definitions, they X can be done in the Makefile, or in config.h. Bear in mind that they may X get undone next time you run Configure. X X3) make X X This will attempt to make patch in the current directory. X X4) make install X X This will put patch into a public directory (normally /usr/local/bin). X It will also try to put the man pages in a reasonable place. It will not X nroff the man page, however. X X5) Read the manual entry before running patch. X X6) IMPORTANT! Help save the world! Communicate any problems and X suggested patches to me, lwall@jpl-devvax.Jpl.Nasa.Gov (Larry Wall), X so we can keep the world in sync. If you have a problem, there's X someone else out there who either has had or will have the same problem. X X If possible, send in patches such that the patch program will apply them. X Context diffs are the best, then normal diffs. Don't send ed scripts-- X I've probably changed my copy since the version you have. X X Watch for patch patches in net.sources.bugs. Patches will generally be X in a form usable by the patch program. If you are just now bringing up X patch and aren't sure how many patches there are, write to me and I'll V send any you don't have. Your current patch level is shown in patchlevel X.h. X X XNEW FEATURES IN THIS RELEASE X X(Correct) support for 4.3bsd-style context diffs. XFiles can be created from scratch. XYou can specify a fuzz-factor for context matching. XYou can force patch to ask no questions. XYou can specify how much of the leading pathname to strip off filenames. XUses a Configure script for greater portability. XYou are now asked if you want to apply a reversed patch. XNo limit (apart from memory) on the size of hunks. $ GOSUB UNPACK_FILE $ FILE_IS = "UTIL.C" $ CHECKSUM_IS = 1044993938 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#include "EXTERN.h" X#include "common.h" X#include "INTERN.h" X#include "util.h" X X/* Rename a file, copying it if necessary. */ X Xint Xmove_file(from,to) Xchar *from, *to; X`123 X char bakname[512]; X Reg1 char *s; X Reg2 int i; X Reg3 int fromfd; X X /* to stdout? */ X X if (strEQ(to, "-")) `123 X#ifdef DEBUGGING X if (debug & 4) X say2("Moving %s to stdout.\n", from); X#endif X fromfd = open(from, 0); X if (fromfd < 0) X fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X if (write(1, buf, i) != 1) X fatal1("patch: write failed\n"); X Close(fromfd); X return 0; X `125 X X if (origprae) `123 X Strcpy (bakname, origprae); X Strcat(bakname, to); X `125 else `123 X Strcpy(bakname, to); X Strcat(bakname, origext?origext:ORIGEXT); X `125 X if (stat(to, &filestat) >= 0) `123 /* output file exists */ X dev_t to_device = filestat.st_dev; X ino_t to_inode = filestat.st_ino; X char *simplename = bakname; X X for (s=bakname; *s; s++) `123 X if (*s == '/') X simplename = s+1; X `125 X /* find a backup name that is not the same file */ X while (stat(bakname, &filestat) >= 0 && V to_device == filestat.st_dev && to_inode == filestat.st_ino) X `123 X for (s=simplename; *s && !islower(*s); s++) ; X if (*s) X *s = toupper(*s); X else X Strcpy(simplename, simplename+1); X `125 V while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice * X/ X#ifdef DEBUGGING X if (debug & 4) X say3("Moving %s to %s.\n", to, bakname); X#endif X#ifdef VMS X if (vms_rename(to,bakname) < 0) `123 X say3("patch: can't backup %s, output is in %s\n", X to, from); X return -1; X `125 X#else X if (link(to, bakname) < 0) `123 X say3("patch: can't backup %s, output is in %s\n", X to, from); X return -1; X `125 X while (unlink(to) >= 0) ; X#endif X `125 X#ifdef DEBUGGING X if (debug & 4) X say3("Moving %s to %s.\n", from, to); X#endif X#ifdef VMS X if (vms_rename(from, to) < 0) `123 /* different file system? */ X#else X if (link(from, to) < 0) `123 /* different file system? */ X#endif X Reg4 int tofd; X X tofd = creat(to, 0666); X if (tofd < 0) `123 X say3("patch: can't create %s, output is in %s.\n", X to, from); X return -1; X `125 X fromfd = open(from, 0); X if (fromfd < 0) X fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X if (write(tofd, buf, i) != i) X fatal1("patch: write failed\n"); X Close(fromfd); X Close(tofd); X `125 X Unlink(from); X return 0; X`125 X X/* Copy a file. */ X Xvoid Xcopy_file(from,to) Xchar *from, *to; X`123 X Reg3 int tofd; X Reg2 int fromfd; X Reg1 int i; X X tofd = creat(to, 0666); X if (tofd < 0) X fatal2("patch: can't create %s.\n", to); X fromfd = open(from, 0); X if (fromfd < 0) X fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X if (write(tofd, buf, i) != i) X fatal2("patch: write (%s) failed\n", to); X Close(fromfd); X Close(tofd); X`125 X X/* Allocate a unique area for a string. */ X Xchar * Xsavestr(s) XReg1 char *s; X`123 X Reg3 char *rv; X Reg2 char *t; X X if (!s) X s = "Oops"; X t = s; X while (*t++); X rv = malloc((MEM) (t - s)); X if (rv == Nullch) `123 X if (using_plan_a) X out_of_mem = TRUE; X else X fatal1("patch: out of memory (savestr)\n"); X `125 X else `123 X t = rv; X while (*t++ = *s++); X `125 X return rv; X`125 X X#if defined(lint) && defined(CANVARARG) X X/*VARARGS ARGSUSED*/ Xsay(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xfatal(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xask(pat) char *pat; `123 ; `125 X X#else X X/* Vanilla terminal output (buffered). */ X Xvoid Xsay(pat,arg1,arg2,arg3) Xchar *pat; Xlong arg1,arg2,arg3; X`123 X fprintf(stderr, pat, arg1, arg2, arg3); X Fflush(stderr); X`125 X X/* Terminal output, pun intended. */ X Xvoid /* very void */ Xfatal(pat,arg1,arg2,arg3) Xchar *pat; Xlong arg1,arg2,arg3; X`123 X void my_exit(); X X say(pat, arg1, arg2, arg3); X my_exit(1); X`125 X X/* Get a response from the user, somehow or other. */ X Xvoid Xask(pat,arg1,arg2,arg3) -+-+-+-+-+ End of part 12 +-+-+-+-+-