[news.software.anu-news] Patch part 7 of 7

conslt32@ZEUS.UNL.EDU (Tim Russell) (08/04/89)

+-+-+-+ Beginning of part 7 +-+-+-+
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#ifdef VMS
X    printf ("Sorry, there's no ed on VMS.\n");
X    exit(0);
X#else
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`009while (unlink(TMPOUTNAME) >= 0);
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();
X#endif /* VMS */
X`125
$ GOSUB UNPACK_FILE
     
$ FILE_IS = "PCH.H"
$ CHECKSUM_IS = 1832979341
$ 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 *`032
X * Revision 2.0  86/09/17  15:39:57  lwall
X * Baseline for netwide release.
X *`032
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 = "README."
$ CHECKSUM_IS = 1413047131
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X`009`009`009Patch Kit, Version 2.0
X
X`009`009    Copyright (c) 1986, 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
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.
X
XFeatures added by Tim Russell (russell@zeus.unl.edu)
X
XAdded support for VMS from earlier version to patchlevel 9.
XAdded parsing support for "patch <patchfile" syntax.
$ GOSUB UNPACK_FILE
     
$ FILE_IS = "UTIL.C"
$ CHECKSUM_IS = 438711646
$ 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`009if (debug & 4)
X`009    say2("Moving %s to stdout.\n", from);
X#endif
X`009fromfd = open(from, 0);
X`009if (fromfd < 0)
X`009    fatal2("patch: internal error, can't reopen %s\n", from);
X`009while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009    if (write(1, buf, i) != 1)
X`009`009fatal1("patch: write failed\n");
X`009Close(fromfd);
X`009return 0;
X    `125
X
X#ifdef VMS
X    /* This is not robust -- we just rename the file, hoping for the best. */
X    if (*to == '/') Strcpy(bakname, to);
X    else `123
X`009Strcpy(bakname, "./");
X`009Strcat(bakname, to);
X    `125
X    i=rename (from, bakname);
V/*   printf ("Attempted to rename %s to %s; status %d\n", from, bakname, i);
X */
X#else
X    Strcpy(bakname, to);
X    Strcat(bakname, origext?origext:ORIGEXT);
X    if (stat(to, &filestat) >= 0) `123`009/* output file exists */
X`009dev_t to_device = filestat.st_dev;
X`009ino_t to_inode  = filestat.st_ino;
X`009char *simplename = bakname;
X`009
X`009for (s=bakname; *s; s++) `123
X`009    if (*s == '/')
X`009`009simplename = s+1;
X`009`125
X`009/* find a backup name that is not the same file */
X`009while (stat(bakname, &filestat) >= 0 &&
X`009`009to_device == filestat.st_dev && to_inode == filestat.st_ino) `123
X`009    for (s=simplename; *s && !islower(*s); s++) ;
X`009    if (*s)
X`009`009*s = toupper(*s);
X`009    else
X`009`009Strcpy(simplename, simplename+1);
X`009`125
X`009while (unlink(bakname) >= 0) ;`009/* while() is for benefit of Eunice */
X#ifdef DEBUGGING
X`009if (debug & 4)
X`009    say3("Moving %s to %s.\n", to, bakname);
X#endif
X`009if (link(to, bakname) < 0) `123
X`009    say3("patch: can't backup %s, output is in %s\n",
X`009`009to, from);
X`009    return -1;
X`009`125
X`009while (unlink(to) >= 0) ;
X    `125
X#ifdef DEBUGGING
X    if (debug & 4)
X`009say3("Moving %s to %s.\n", from, to);
X#endif
X    if (link(from, to) < 0) `123`009`009/* different file system? */
X`009Reg4 int tofd;
X`009
X`009tofd = creat(to, 0666);
X`009if (tofd < 0) `123
X`009    say3("patch: can't create %s, output is in %s.\n",
X`009      to, from);
X`009    return -1;
X`009`125
X`009fromfd = open(from, 0);
X`009if (fromfd < 0)
X`009    fatal2("patch: internal error, can't reopen %s\n", from);
X`009while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009    if (write(tofd, buf, i) != i)
X`009`009fatal1("patch: write failed\n");
X`009Close(fromfd);
X`009Close(tofd);
X    `125
X    Unlink(from);
X#endif  /* VMS */
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   `032
X    tofd = creat(to, 0666);
X    if (tofd < 0)
X`009fatal2("patch: can't create %s.\n", to);
X    fromfd = open(from, 0);
X    if (fromfd < 0)
X`009fatal2("patch: internal error, can't reopen %s\n", from);
X    while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009if (write(tofd, buf, i) != i)
X`009    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`009s = "Oops";
X    t = s;
X    while (*t++);
X    rv = malloc((MEM) (t - s));
X    if (rv == Nullch) `123
X`009if (using_plan_a)
X`009    out_of_mem = TRUE;
X`009else
X`009    fatal1("patch: out of memory (savestr)\n");
X    `125
X    else `123
X`009t = rv;
X`009while (*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;
Xint 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`009`009`009`009/* very void */
Xfatal(pat,arg1,arg2,arg3)
Xchar *pat;
Xint 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)
Xchar *pat;
Xint arg1,arg2,arg3;
X`123
X    int ttyfd;
X    int r;
X    bool tty2 = isatty(2);
X
X    Sprintf(buf, pat, arg1, arg2, arg3);
X    Fflush(stderr);
X    write(2, buf, strlen(buf));
X    if (tty2) `123`009`009`009`009/* might be redirected to a file */
X`009r = read(2, buf, sizeof buf);
X    `125
X    else if (isatty(1)) `123`009`009/* this may be new file output */
X`009Fflush(stdout);
X`009write(1, buf, strlen(buf));
X`009r = read(1, buf, sizeof buf);
X    `125
X    else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) `123
X`009`009`009`009`009/* might be deleted or unwriteable */
X`009write(ttyfd, buf, strlen(buf));
X`009r = read(ttyfd, buf, sizeof buf);
X`009Close(ttyfd);
X    `125
X    else if (isatty(0)) `123`009`009/* this is probably patch input */
X`009Fflush(stdin);
X`009write(0, buf, strlen(buf));
X`009r = read(0, buf, sizeof buf);
X    `125
X    else `123`009`009`009`009/* no terminal at all--default it */
X`009buf[0] = '\n';
X`009r = 1;
X    `125
X    if (r <= 0)
X`009buf[0] = 0;
X    else
X`009buf[r] = '\0';
X    if (!tty2)
X`009say1(buf);
X`125
X#endif lint
X
X/* How to handle certain events when not in a critical region. */
X
Xvoid
Xset_signals()
X`123
X    void my_exit();
X
X#ifndef lint
X    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X`009Signal(SIGHUP, my_exit);
X    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X`009Signal(SIGINT, my_exit);
X#endif
X`125
X
X/* How to handle certain events when in a critical region. */
X
Xvoid
Xignore_signals()
X`123
X#ifndef lint
X    Signal(SIGHUP, SIG_IGN);
X    Signal(SIGINT, SIG_IGN);
X#endif
X`125
X
X/* Make sure we'll have the directories to create a file. */
X
Xvoid
Xmakedirs(filename,striplast)
XReg1 char *filename;
Xbool striplast;
X`123
X    char tmpbuf[256];
X    Reg2 char *s = tmpbuf;
X    char *dirv[20];
X    Reg3 int i;
X    Reg4 int dirvp = 0;
X
X    while (*filename) `123
X`009if (*filename == '/') `123
X`009    filename++;
X`009    dirv[dirvp++] = s;
X`009    *s++ = '\0';
X`009`125
X`009else `123
X`009    *s++ = *filename++;
X`009`125
X    `125
X    *s = '\0';
X    dirv[dirvp] = s;
X    if (striplast)
X`009dirvp--;
X    if (dirvp < 0)
X`009return;
X    strcpy(buf, "mkdir");
X    s = buf;
X    for (i=0; i<=dirvp; i++) `123
X`009while (*s) s++;
X`009*s++ = ' ';
X`009strcpy(s, tmpbuf);
X`009*dirv[i] = '/';
X    `125
X    system(buf);
X`125
X
X/* Make filenames more reasonable. */
X
Xchar *
Xfetchname(at,strip_leading,assume_exists)
Xchar *at;
Xint strip_leading;
Xint assume_exists;
X`123
X    char *s;
X    char *name;
X    Reg1 char *t;
X    char tmpbuf[200];
X
X    if (!at)
X`009return Nullch;
X    s = savestr(at);
X    for (t=s; isspace(*t); t++) ;
X    name = t;
X#ifdef DEBUGGING
X    if (debug & 128)
X`009say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
X#endif
V    if (strnEQ(name, "/dev/null", 9))`009/* so files can be created by diffin
Xg */
X`009return Nullch;`009`009`009/*   against /dev/null. */
X    for (; *t && !isspace(*t); t++)
X`009if (*t == '/')
X`009    if (--strip_leading >= 0)
X`009`009name = t+1;
X    *t = '\0';
X    if (name != s && *s != '/') `123
X`009name[-1] = '\0';
X`009if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) `123
X`009    name[-1] = '/';
X`009    name=s;
X`009`125
X    `125
X    name = savestr(name);
X    Sprintf(tmpbuf, "RCS/%s", name);
X    free(s);
X    if (stat(name, &filestat) < 0 && !assume_exists) `123
X#ifdef VMS
X`009free(name);
X`009name = Nullch;
X    `125
X#else
X`009Strcat(tmpbuf, RCSSUFFIX);
X`009if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) `123
X`009    Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
V`009    if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) `12
X3
X`009`009free(name);
X`009`009name = Nullch;
X`009    `125
X`009`125
X    `125
X#endif  /* VMS */
X    return name;
X`125
$ GOSUB UNPACK_FILE
     
$ FILE_IS = "UTIL.H"
$ CHECKSUM_IS = 1802118602
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $
X *
X * $Log:`009util.h,v $
X * Revision 2.0  86/09/17  15:40:06  lwall
X * Baseline for netwide release.
X *`032
X */
X
X/* and for those machine that can't handle a variable argument list */
X
X#ifdef CANVARARG
X
X#define say1 say
X#define say2 say
X#define say3 say
X#define say4 say
X#define ask1 ask
X#define ask2 ask
X#define ask3 ask
X#define ask4 ask
X#define fatal1 fatal
X#define fatal2 fatal
X#define fatal3 fatal
X#define fatal4 fatal
X
X#else /* hope they allow multi-line macro actual arguments */
X
X#ifdef lint
X
X#define say1(a) say(a, 0, 0, 0)
X#define say2(a,b) say(a, (b)==(b), 0, 0)
X#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0)
X#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d))
X#define ask1(a) ask(a, 0, 0, 0)
X#define ask2(a,b) ask(a, (b)==(b), 0, 0)
X#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0)
X#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d))
X#define fatal1(a) fatal(a, 0, 0, 0)
X#define fatal2(a,b) fatal(a, (b)==(b), 0, 0)
X#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0)
X#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d))
X
X#else /* lint */
X    /* if this doesn't work, try defining CANVARARG above */
X#define say1(a) say(a, Nullch, Nullch, Nullch)
X#define say2(a,b) say(a, b, Nullch, Nullch)
X#define say3(a,b,c) say(a, b, c, Nullch)
X#define say4 say
X#define ask1(a) ask(a, Nullch, Nullch, Nullch)
X#define ask2(a,b) ask(a, b, Nullch, Nullch)
X#define ask3(a,b,c) ask(a, b, c, Nullch)
X#define ask4 ask
X#define fatal1(a) fatal(a, Nullch, Nullch, Nullch)
X#define fatal2(a,b) fatal(a, b, Nullch, Nullch)
X#define fatal3(a,b,c) fatal(a, b, c, Nullch)
X#define fatal4 fatal
X
X#endif /* lint */
X
X/* if neither of the above work, join all multi-line macro calls. */
X#endif
X
XEXT char serrbuf[BUFSIZ];`009`009/* buffer for stderr */
X
Xchar *fetchname();
Xint move_file();
Xvoid copy_file();
Xvoid say();
Xvoid fatal();
Xvoid ask();
Xchar *savestr();
Xvoid set_signals();
Xvoid ignore_signals();
Xvoid makedirs();
$ GOSUB UNPACK_FILE
     
$ FILE_IS = "VERSION.C"
$ CHECKSUM_IS = 1661809282
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $
X *
X * $Log:`009version.c,v $
X * Revision 2.0  86/09/17  15:40:11  lwall
X * Baseline for netwide release.
X *`032
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "INTERN.h"
X#include "patchlevel.h"
X#include "version.h"
X
X/* Print out the version number and die. */
X
Xvoid
Xversion()
X`123
X    extern char rcsid[];
X
X#ifdef lint
X    rcsid[0] = rcsid[0];
X#else
X    fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL);
X#endif
X`125
$ GOSUB UNPACK_FILE
     
$ FILE_IS = "VERSION.H"
$ CHECKSUM_IS = 122769530
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $
X *
X * $Log:`009version.h,v $
X * Revision 2.0  86/09/17  15:40:14  lwall
X * Baseline for netwide release.
X *`032
X */
X
Xvoid version();
$ GOSUB UNPACK_FILE
$ EXIT
     

fritz@unocss.UUCP (Tim Russell) (08/27/89)

+-+-+-+ Beginning of part 7 +-+-+-+
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#ifdef VMS
X    printf ("Sorry, there's no ed on VMS.\n");
X    exit(0);
X#else
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`009while (unlink(TMPOUTNAME) >= 0);
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();
X#endif /* VMS */
X`125
$ GOSUB UNPACK_FILE

$ FILE_IS = "PCH.H"
$ CHECKSUM_IS = 1832979341
$ 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 *`032
X * Revision 2.0  86/09/17  15:39:57  lwall
X * Baseline for netwide release.
X *`032
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 = "README."
$ CHECKSUM_IS = 1413047131
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X`009`009`009Patch Kit, Version 2.0
X
X`009`009    Copyright (c) 1986, 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
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.
X
XFeatures added by Tim Russell (russell@zeus.unl.edu)
X
XAdded support for VMS from earlier version to patchlevel 9.
XAdded parsing support for "patch <patchfile" syntax.
$ GOSUB UNPACK_FILE

$ FILE_IS = "UTIL.C"
$ CHECKSUM_IS = 438711646
$ 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`009if (debug & 4)
X`009    say2("Moving %s to stdout.\n", from);
X#endif
X`009fromfd = open(from, 0);
X`009if (fromfd < 0)
X`009    fatal2("patch: internal error, can't reopen %s\n", from);
X`009while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009    if (write(1, buf, i) != 1)
X`009`009fatal1("patch: write failed\n");
X`009Close(fromfd);
X`009return 0;
X    `125
X
X#ifdef VMS
X    /* This is not robust -- we just rename the file, hoping for the best. */
X    if (*to == '/') Strcpy(bakname, to);
X    else `123
X`009Strcpy(bakname, "./");
X`009Strcat(bakname, to);
X    `125
X    i=rename (from, bakname);
V/*   printf ("Attempted to rename %s to %s; status %d\n", from, bakname, i);
X */
X#else
X    Strcpy(bakname, to);
X    Strcat(bakname, origext?origext:ORIGEXT);
X    if (stat(to, &filestat) >= 0) `123`009/* output file exists */
X`009dev_t to_device = filestat.st_dev;
X`009ino_t to_inode  = filestat.st_ino;
X`009char *simplename = bakname;
X`009
X`009for (s=bakname; *s; s++) `123
X`009    if (*s == '/')
X`009`009simplename = s+1;
X`009`125
X`009/* find a backup name that is not the same file */
X`009while (stat(bakname, &filestat) >= 0 &&
X`009`009to_device == filestat.st_dev && to_inode == filestat.st_ino) `123
X`009    for (s=simplename; *s && !islower(*s); s++) ;
X`009    if (*s)
X`009`009*s = toupper(*s);
X`009    else
X`009`009Strcpy(simplename, simplename+1);
X`009`125
X`009while (unlink(bakname) >= 0) ;`009/* while() is for benefit of Eunice */
X#ifdef DEBUGGING
X`009if (debug & 4)
X`009    say3("Moving %s to %s.\n", to, bakname);
X#endif
X`009if (link(to, bakname) < 0) `123
X`009    say3("patch: can't backup %s, output is in %s\n",
X`009`009to, from);
X`009    return -1;
X`009`125
X`009while (unlink(to) >= 0) ;
X    `125
X#ifdef DEBUGGING
X    if (debug & 4)
X`009say3("Moving %s to %s.\n", from, to);
X#endif
X    if (link(from, to) < 0) `123`009`009/* different file system? */
X`009Reg4 int tofd;
X`009
X`009tofd = creat(to, 0666);
X`009if (tofd < 0) `123
X`009    say3("patch: can't create %s, output is in %s.\n",
X`009      to, from);
X`009    return -1;
X`009`125
X`009fromfd = open(from, 0);
X`009if (fromfd < 0)
X`009    fatal2("patch: internal error, can't reopen %s\n", from);
X`009while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009    if (write(tofd, buf, i) != i)
X`009`009fatal1("patch: write failed\n");
X`009Close(fromfd);
X`009Close(tofd);
X    `125
X    Unlink(from);
X#endif  /* VMS */
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   `032
X    tofd = creat(to, 0666);
X    if (tofd < 0)
X`009fatal2("patch: can't create %s.\n", to);
X    fromfd = open(from, 0);
X    if (fromfd < 0)
X`009fatal2("patch: internal error, can't reopen %s\n", from);
X    while ((i=read(fromfd, buf, sizeof buf)) > 0)
X`009if (write(tofd, buf, i) != i)
X`009    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`009s = "Oops";
X    t = s;
X    while (*t++);
X    rv = malloc((MEM) (t - s));
X    if (rv == Nullch) `123
X`009if (using_plan_a)
X`009    out_of_mem = TRUE;
X`009else
X`009    fatal1("patch: out of memory (savestr)\n");
X    `125
X    else `123
X`009t = rv;
X`009while (*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;
Xint 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`009`009`009`009/* very void */
Xfatal(pat,arg1,arg2,arg3)
Xchar *pat;
Xint 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)
Xchar *pat;
Xint arg1,arg2,arg3;
X`123
X    int ttyfd;
X    int r;
X    bool tty2 = isatty(2);
X
X    Sprintf(buf, pat, arg1, arg2, arg3);
X    Fflush(stderr);
X    write(2, buf, strlen(buf));
X    if (tty2) `123`009`009`009`009/* might be redirected to a file */
X`009r = read(2, buf, sizeof buf);
X    `125
X    else if (isatty(1)) `123`009`009/* this may be new file output */
X`009Fflush(stdout);
X`009write(1, buf, strlen(buf));
X`009r = read(1, buf, sizeof buf);
X    `125
X    else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) `123
X`009`009`009`009`009/* might be deleted or unwriteable */
X`009write(ttyfd, buf, strlen(buf));
X`009r = read(ttyfd, buf, sizeof buf);
X`009Close(ttyfd);
X    `125
X    else if (isatty(0)) `123`009`009/* this is probably patch input */
X`009Fflush(stdin);
X`009write(0, buf, strlen(buf));
X`009r = read(0, buf, sizeof buf);
X    `125
X    else `123`009`009`009`009/* no terminal at all--default it */
X`009buf[0] = '\n';
X`009r = 1;
X    `125
X    if (r <= 0)
X`009buf[0] = 0;
X    else
X`009buf[r] = '\0';
X    if (!tty2)
X`009say1(buf);
X`125
X#endif lint
X
X/* How to handle certain events when not in a critical region. */
X
Xvoid
Xset_signals()
X`123
X    void my_exit();
X
X#ifndef lint
X    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X`009Signal(SIGHUP, my_exit);
X    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X`009Signal(SIGINT, my_exit);
X#endif
X`125
X
X/* How to handle certain events when in a critical region. */
X
Xvoid
Xignore_signals()
X`123
X#ifndef lint
X    Signal(SIGHUP, SIG_IGN);
X    Signal(SIGINT, SIG_IGN);
X#endif
X`125
X
X/* Make sure we'll have the directories to create a file. */
X
Xvoid
Xmakedirs(filename,striplast)
XReg1 char *filename;
Xbool striplast;
X`123
X    char tmpbuf[256];
X    Reg2 char *s = tmpbuf;
X    char *dirv[20];
X    Reg3 int i;
X    Reg4 int dirvp = 0;
X
X    while (*filename) `123
X`009if (*filename == '/') `123
X`009    filename++;
X`009    dirv[dirvp++] = s;
X`009    *s++ = '\0';
X`009`125
X`009else `123
X`009    *s++ = *filename++;
X`009`125
X    `125
X    *s = '\0';
X    dirv[dirvp] = s;
X    if (striplast)
X`009dirvp--;
X    if (dirvp < 0)
X`009return;
X    strcpy(buf, "mkdir");
X    s = buf;
X    for (i=0; i<=dirvp; i++) `123
X`009while (*s) s++;
X`009*s++ = ' ';
X`009strcpy(s, tmpbuf);
X`009*dirv[i] = '/';
X    `125
X    system(buf);
X`125
X
X/* Make filenames more reasonable. */
X
Xchar *
Xfetchname(at,strip_leading,assume_exists)
Xchar *at;
Xint strip_leading;
Xint assume_exists;
X`123
X    char *s;
X    char *name;
X    Reg1 char *t;
X    char tmpbuf[200];
X
X    if (!at)
X`009return Nullch;
X    s = savestr(at);
X    for (t=s; isspace(*t); t++) ;
X    name = t;
X#ifdef DEBUGGING
X    if (debug & 128)
X`009say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
X#endif
V    if (strnEQ(name, "/dev/null", 9))`009/* so files can be created by diffin
Xg */
X`009return Nullch;`009`009`009/*   against /dev/null. */
X    for (; *t && !isspace(*t); t++)
X`009if (*t == '/')
X`009    if (--strip_leading >= 0)
X`009`009name = t+1;
X    *t = '\0';
X    if (name != s && *s != '/') `123
X`009name[-1] = '\0';
X`009if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) `123
X`009    name[-1] = '/';
X`009    name=s;
X`009`125
X    `125
X    name = savestr(name);
X    Sprintf(tmpbuf, "RCS/%s", name);
X    free(s);
X    if (stat(name, &filestat) < 0 && !assume_exists) `123
X#ifdef VMS
X`009free(name);
X`009name = Nullch;
X    `125
X#else
X`009Strcat(tmpbuf, RCSSUFFIX);
X`009if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) `123
X`009    Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
V`009    if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) `12
X3
X`009`009free(name);
X`009`009name = Nullch;
X`009    `125
X`009`125
X    `125
X#endif  /* VMS */
X    return name;
X`125
$ GOSUB UNPACK_FILE

$ FILE_IS = "UTIL.H"
$ CHECKSUM_IS = 1802118602
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $
X *
X * $Log:`009util.h,v $
X * Revision 2.0  86/09/17  15:40:06  lwall
X * Baseline for netwide release.
X *`032
X */
X
X/* and for those machine that can't handle a variable argument list */
X
X#ifdef CANVARARG
X
X#define say1 say
X#define say2 say
X#define say3 say
X#define say4 say
X#define ask1 ask
X#define ask2 ask
X#define ask3 ask
X#define ask4 ask
X#define fatal1 fatal
X#define fatal2 fatal
X#define fatal3 fatal
X#define fatal4 fatal
X
X#else /* hope they allow multi-line macro actual arguments */
X
X#ifdef lint
X
X#define say1(a) say(a, 0, 0, 0)
X#define say2(a,b) say(a, (b)==(b), 0, 0)
X#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0)
X#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d))
X#define ask1(a) ask(a, 0, 0, 0)
X#define ask2(a,b) ask(a, (b)==(b), 0, 0)
X#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0)
X#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d))
X#define fatal1(a) fatal(a, 0, 0, 0)
X#define fatal2(a,b) fatal(a, (b)==(b), 0, 0)
X#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0)
X#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d))
X
X#else /* lint */
X    /* if this doesn't work, try defining CANVARARG above */
X#define say1(a) say(a, Nullch, Nullch, Nullch)
X#define say2(a,b) say(a, b, Nullch, Nullch)
X#define say3(a,b,c) say(a, b, c, Nullch)
X#define say4 say
X#define ask1(a) ask(a, Nullch, Nullch, Nullch)
X#define ask2(a,b) ask(a, b, Nullch, Nullch)
X#define ask3(a,b,c) ask(a, b, c, Nullch)
X#define ask4 ask
X#define fatal1(a) fatal(a, Nullch, Nullch, Nullch)
X#define fatal2(a,b) fatal(a, b, Nullch, Nullch)
X#define fatal3(a,b,c) fatal(a, b, c, Nullch)
X#define fatal4 fatal
X
X#endif /* lint */
X
X/* if neither of the above work, join all multi-line macro calls. */
X#endif
X
XEXT char serrbuf[BUFSIZ];`009`009/* buffer for stderr */
X
Xchar *fetchname();
Xint move_file();
Xvoid copy_file();
Xvoid say();
Xvoid fatal();
Xvoid ask();
Xchar *savestr();
Xvoid set_signals();
Xvoid ignore_signals();
Xvoid makedirs();
$ GOSUB UNPACK_FILE

$ FILE_IS = "VERSION.C"
$ CHECKSUM_IS = 1661809282
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $
X *
X * $Log:`009version.c,v $
X * Revision 2.0  86/09/17  15:40:11  lwall
X * Baseline for netwide release.
X *`032
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "INTERN.h"
X#include "patchlevel.h"
X#include "version.h"
X
X/* Print out the version number and die. */
X
Xvoid
Xversion()
X`123
X    extern char rcsid[];
X
X#ifdef lint
X    rcsid[0] = rcsid[0];
X#else
X    fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL);
X#endif
X`125
$ GOSUB UNPACK_FILE

$ FILE_IS = "VERSION.H"
$ CHECKSUM_IS = 122769530
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $
X *
X * $Log:`009version.h,v $
X * Revision 2.0  86/09/17  15:40:14  lwall
X * Baseline for netwide release.
X *`032
X */
X
Xvoid version();
$ GOSUB UNPACK_FILE
$ EXIT
-- 
---------------------------------+--------------------------------------------
 Tim Russell, Computer Operator  | Internet: russell@zeus.unl.edu
 Campus Computing                | Bitnet:   russell@unoma1
 University of Nebraska at Omaha | UUCP:     uunet!zeus.unl.edu!russell