+-+-+-+ 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 +-+-+-+-+-
