Larry Wall's patch v2.0-11 (2 of 3)
egray at fthood.UUCP
egray at fthood.UUCP
Wed Jun 8 02:43:00 AEST 1988
This is part 2 of 3 to Larry Wall's patch 2.0-11
Emmet P. Gray US Army, HQ III Corps & Fort Hood
...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
Directorate of Engineering & Housing
Environmental Management Office
Fort Hood, TX 76544-5057
-------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# config.h.SH
# inp.c
# inp.h
# malloc.c
# patch.c
# util.h
# version.c
# version.h
# This archive created: Tue Jun 7 11:32:44 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'config.h.SH'" '(4619 characters)'
if test -f 'config.h.SH'
then
echo shar: "will not over-write existing file 'config.h.SH'"
else
sed 's/^X//' << \SHAR_EOF > 'config.h.SH'
Xcase $CONFIG in
X'')
X if test ! -f config.sh; then
X ln ../config.sh . || \
X ln ../../config.sh . || \
X ln ../../../config.sh . || \
X (echo "Can't find config.sh."; exit 1)
X echo "Using config.sh from above..."
X fi
X . ./config.sh
X ;;
Xesac
Xecho "Extracting config.h (with variable substitutions)"
Xcat <<!GROK!THIS! >config.h
X/* config.h
X * This file was produced by running the config.h.SH script, which
X * gets its values from config.sh, which is generally produced by
X * running Configure.
X *
X * Feel free to modify any of this as the need arises. Note, however,
X * that running config.h.SH again will wipe out any changes you've made.
X * For a more permanent change edit config.sh and rerun config.h.SH.
X */
X
X
X/* EUNICE:
X * This symbol, if defined, indicates that the program is being compiled
X * under the EUNICE package under VMS. The program will need to handle
X * things like files that don't go away the first time you unlink them,
X * due to version numbering. It will also need to compensate for lack
X * of a respectable link() command.
X */
X/* VMS:
X * This symbol, if defined, indicates that the program is running under
X * VMS. It is currently only set in conjunction with the EUNICE symbol.
X */
X#$d_eunice EUNICE /**/
X#$d_eunice VMS /**/
X
X/* CPPSTDIN:
X * This symbol contains the first part of the string which will invoke
X * the C preprocessor on the standard input and produce to standard
X * output. Typical value of "cc -E" or "/lib/cpp".
X */
X/* CPPMINUS:
X * This symbol contains the second part of the string which will invoke
X * the C preprocessor on the standard input and produce to standard
X * output. This symbol will have the value "-" if CPPSTDIN needs a minus
X * to specify standard input, otherwise the value is "".
X */
X#define CPPSTDIN "$cppstdin"
X#define CPPMINUS "$cppminus"
X
X/* CHARSPRINTF:
X * This symbol is defined if this system declares "char *sprintf()" in
X * stdio.h. The trend seems to be to declare it as "int sprintf()". It
X * is up to the package author to declare sprintf correctly based on the
X * symbol.
X */
X#$d_charsprf CHARSPRINTF /**/
X
X/* FLEXFILENAMES:
X * This symbol, if defined, indicates that the system supports filenames
X * longer than 14 characters.
X */
X#$d_flexfnam FLEXFILENAMES /**/
X
X/* index:
X * This preprocessor symbol is defined, along with rindex, if the system
X * uses the strchr and strrchr routines instead.
X */
X/* rindex:
X * This preprocessor symbol is defined, along with index, if the system
X * uses the strchr and strrchr routines instead.
X */
X#$d_index index strchr /* cultural */
X#$d_index rindex strrchr /* differences? */
X
X/* VOIDSIG:
X * This symbol is defined if this system declares "void (*signal())()" in
X * signal.h. The old way was to declare it as "int (*signal())()". It
X * is up to the package author to declare things correctly based on the
X * symbol.
X */
X#$d_voidsig VOIDSIG /**/
X
X/* Reg1:
X * This symbol, along with Reg2, Reg3, etc. is either the word "register"
X * or null, depending on whether the C compiler pays attention to this
X * many register declarations. The intent is that you don't have to
X * order your register declarations in the order of importance, so you
X * can freely declare register variables in sub-blocks of code and as
X * function parameters. Do not use Reg<n> more than once per routine.
X */
X
X#define Reg1 $reg1 /**/
X#define Reg2 $reg2 /**/
X#define Reg3 $reg3 /**/
X#define Reg4 $reg4 /**/
X#define Reg5 $reg5 /**/
X#define Reg6 $reg6 /**/
X#define Reg7 $reg7 /**/
X#define Reg8 $reg8 /**/
X#define Reg9 $reg9 /**/
X#define Reg10 $reg10 /**/
X#define Reg11 $reg11 /**/
X#define Reg12 $reg12 /**/
X#define Reg13 $reg13 /**/
X#define Reg14 $reg14 /**/
X#define Reg15 $reg15 /**/
X#define Reg16 $reg16 /**/
X
X/* VOIDFLAGS:
X * This symbol indicates how much support of the void type is given by this
X * compiler. What various bits mean:
X *
X * 1 = supports declaration of void
X * 2 = supports arrays of pointers to functions returning void
X * 4 = supports comparisons between pointers to void functions and
X * addresses of void functions
X *
X * The package designer should define VOIDUSED to indicate the requirements
X * of the package. This can be done either by #defining VOIDUSED before
X * including config.h, or by defining defvoidused in Myinit.U. If the
X * level of void support necessary is not present, defines void to int.
X */
X#ifndef VOIDUSED
X#define VOIDUSED $defvoidused
X#endif
X#define VOIDFLAGS $voidflags
X#if (VOIDFLAGS & VOIDUSED) != VOIDUSED
X#$define void int /* is void to be avoided? */
X#$define M_VOID /* Xenix strikes again */
X#endif
X
X!GROK!THIS!
SHAR_EOF
if test 4619 -ne "`wc -c < 'config.h.SH'`"
then
echo shar: "error transmitting 'config.h.SH'" '(should have been 4619 characters)'
fi
fi
echo shar: "extracting 'inp.c'" '(8134 characters)'
if test -f 'inp.c'
then
echo shar: "will not over-write existing file 'inp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'inp.c'
X/* $Header: inp.c,v 2.0.1.1 88/06/03 15:06:13 lwall Locked $
X *
X * $Log: inp.c,v $
X * Revision 2.0.1.1 88/06/03 15:06:13 lwall
X * patch10: made a little smarter about sccs files
X *
X * Revision 2.0 86/09/17 15:37:02 lwall
X * Baseline for netwide release.
X *
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "pch.h"
X#include "INTERN.h"
X#include "inp.h"
X
X/* Input-file-with-indexable-lines abstract type */
X
Xstatic long i_size; /* size of the input file */
Xstatic char *i_womp; /* plan a buffer for entire file */
Xstatic char **i_ptr; /* pointers to lines in i_womp */
X
Xstatic int tifd = -1; /* plan b virtual string array */
Xstatic char *tibuf[2]; /* plan b buffers */
Xstatic LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
Xstatic LINENUM lines_per_buf; /* how many lines per buffer */
Xstatic int tireclen; /* length of records in tmp file */
X
X/* New patch--prepare to edit another file. */
X
Xvoid
Xre_input()
X{
X if (using_plan_a) {
X i_size = 0;
X#ifndef lint
X if (i_ptr != Null(char**))
X free((char *)i_ptr);
X#endif
X if (i_womp != Nullch)
X free(i_womp);
X i_womp = Nullch;
X i_ptr = Null(char **);
X }
X else {
X using_plan_a = TRUE; /* maybe the next one is smaller */
X Close(tifd);
X tifd = -1;
X free(tibuf[0]);
X free(tibuf[1]);
X tibuf[0] = tibuf[1] = Nullch;
X tiline[0] = tiline[1] = -1;
X tireclen = 0;
X }
X}
X
X/* Constuct the line index, somehow or other. */
X
Xvoid
Xscan_input(filename)
Xchar *filename;
X{
X if (!plan_a(filename))
X plan_b(filename);
X if (verbose) {
X say3("Patching file %s using Plan %s...\n", filename,
X (using_plan_a ? "A" : "B") );
X }
X}
X
X/* Try keeping everything in memory. */
X
Xbool
Xplan_a(filename)
Xchar *filename;
X{
X int ifd;
X Reg1 char *s;
X Reg2 LINENUM iline;
X
X if (ok_to_create_file && stat(filename, &filestat) < 0) {
X if (verbose)
X say2("(Creating file %s...)\n",filename);
X makedirs(filename, TRUE);
X close(creat(filename, 0666));
X }
X if (stat(filename, &filestat) < 0) {
X Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
X if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
X Sprintf(buf, CHECKOUT, filename);
X if (verbose)
X say2("Can't find %s--attempting to check it out from RCS.\n",
X filename);
X if (system(buf) || stat(filename, &filestat))
X fatal2("Can't check out %s.\n", filename);
X }
X else {
X Sprintf(buf+20, "SCCS/%s%s", SCCSPREFIX, filename);
X if (stat(s=buf+20, &filestat) >= 0 ||
X stat(s=buf+25, &filestat) >= 0) {
X Sprintf(buf, GET, s);
X if (verbose)
X say2("Can't find %s--attempting to get it from SCCS.\n",
X filename);
X if (system(buf) || stat(filename, &filestat))
X fatal2("Can't get %s.\n", filename);
X }
X else
X fatal2("Can't find %s.\n", filename);
X }
X }
X filemode = filestat.st_mode;
X if ((filemode & S_IFMT) & ~S_IFREG)
X fatal2("%s is not a normal file--can't patch.\n", filename);
X i_size = filestat.st_size;
X if (out_of_mem) {
X set_hunkmax(); /* make sure dynamic arrays are allocated */
X out_of_mem = FALSE;
X return FALSE; /* force plan b because plan a bombed */
X }
X#ifdef lint
X i_womp = Nullch;
X#else
X i_womp = malloc((MEM)(i_size+2)); /* lint says this may alloc less than */
X /* i_size, but that's okay, I think. */
X#endif
X if (i_womp == Nullch)
X return FALSE;
X if ((ifd = open(filename, 0)) < 0)
X fatal2("Can't open file %s\n", filename);
X#ifndef lint
X if (read(ifd, i_womp, (int)i_size) != i_size) {
X Close(ifd); /* probably means i_size > 15 or 16 bits worth */
X free(i_womp); /* at this point it doesn't matter if i_womp was */
X return FALSE; /* undersized. */
X }
X#endif
X Close(ifd);
X if (i_size && i_womp[i_size-1] != '\n')
X i_womp[i_size++] = '\n';
X i_womp[i_size] = '\0';
X
X /* count the lines in the buffer so we know how many pointers we need */
X
X iline = 0;
X for (s=i_womp; *s; s++) {
X if (*s == '\n')
X iline++;
X }
X#ifdef lint
X i_ptr = Null(char**);
X#else
X i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
X#endif
X if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
X free((char *)i_womp);
X return FALSE;
X }
X
X /* now scan the buffer and build pointer array */
X
X iline = 1;
X i_ptr[iline] = i_womp;
X for (s=i_womp; *s; s++) {
X if (*s == '\n')
X i_ptr[++iline] = s+1; /* these are NOT null terminated */
X }
X input_lines = iline - 1;
X
X /* now check for revision, if any */
X
X if (revision != Nullch) {
X if (!rev_in_string(i_womp)) {
X if (force) {
X if (verbose)
X say2(
X"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
X revision);
X }
X else {
X ask2(
X"This file doesn't appear to be the %s version--patch anyway? [n] ",
X revision);
X if (*buf != 'y')
X fatal1("Aborted.\n");
X }
X }
X else if (verbose)
X say2("Good. This file appears to be the %s version.\n",
X revision);
X }
X return TRUE; /* plan a will work */
X}
X
X/* Keep (virtually) nothing in memory. */
X
Xvoid
Xplan_b(filename)
Xchar *filename;
X{
X Reg3 FILE *ifp;
X Reg1 int i = 0;
X Reg2 int maxlen = 1;
X Reg4 bool found_revision = (revision == Nullch);
X
X using_plan_a = FALSE;
X if ((ifp = fopen(filename, "r")) == Nullfp)
X fatal2("Can't open file %s\n", filename);
X if ((tifd = creat(TMPINNAME, 0666)) < 0)
X fatal2("Can't open file %s\n", TMPINNAME);
X while (fgets(buf, sizeof buf, ifp) != Nullch) {
X if (revision != Nullch && !found_revision && rev_in_string(buf))
X found_revision = TRUE;
X if ((i = strlen(buf)) > maxlen)
X maxlen = i; /* find longest line */
X }
X if (revision != Nullch) {
X if (!found_revision) {
X if (force) {
X if (verbose)
X say2(
X"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
X revision);
X }
X else {
X ask2(
X"This file doesn't appear to be the %s version--patch anyway? [n] ",
X revision);
X if (*buf != 'y')
X fatal1("Aborted.\n");
X }
X }
X else if (verbose)
X say2("Good. This file appears to be the %s version.\n",
X revision);
X }
X Fseek(ifp, 0L, 0); /* rewind file */
X lines_per_buf = BUFFERSIZE / maxlen;
X tireclen = maxlen;
X tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
X tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
X if (tibuf[1] == Nullch)
X fatal1("Can't seem to get enough memory.\n");
X for (i=1; ; i++) {
X if (! (i % lines_per_buf)) /* new block */
X if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
X fatal1("patch: can't write temp file.\n");
X if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
X == Nullch) {
X input_lines = i - 1;
X if (i % lines_per_buf)
X if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
X fatal1("patch: can't write temp file.\n");
X break;
X }
X }
X Fclose(ifp);
X Close(tifd);
X if ((tifd = open(TMPINNAME, 0)) < 0) {
X fatal2("Can't reopen file %s\n", TMPINNAME);
X }
X}
X
X/* Fetch a line from the input file, \n terminated, not necessarily \0. */
X
Xchar *
Xifetch(line,whichbuf)
XReg1 LINENUM line;
Xint whichbuf; /* ignored when file in memory */
X{
X if (line < 1 || line > input_lines)
X return "";
X if (using_plan_a)
X return i_ptr[line];
X else {
X LINENUM offline = line % lines_per_buf;
X LINENUM baseline = line - offline;
X
X if (tiline[0] == baseline)
X whichbuf = 0;
X else if (tiline[1] == baseline)
X whichbuf = 1;
X else {
X tiline[whichbuf] = baseline;
X#ifndef lint /* complains of long accuracy */
X Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
X#endif
X if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
X fatal2("Error reading tmp file %s.\n", TMPINNAME);
X }
X return tibuf[whichbuf] + (tireclen*offline);
X }
X}
X
X/* True if the string argument contains the revision number we want. */
X
Xbool
Xrev_in_string(string)
Xchar *string;
X{
X Reg1 char *s;
X Reg2 int patlen;
X
X if (revision == Nullch)
X return TRUE;
X patlen = strlen(revision);
X if (strnEQ(string,revision,patlen) && isspace(s[patlen]))
X return TRUE;
X for (s = string; *s; s++) {
X if (isspace(*s) && strnEQ(s+1, revision, patlen) &&
X isspace(s[patlen+1] )) {
X return TRUE;
X }
X }
X return FALSE;
X}
X
SHAR_EOF
if test 8134 -ne "`wc -c < 'inp.c'`"
then
echo shar: "error transmitting 'inp.c'" '(should have been 8134 characters)'
fi
fi
echo shar: "extracting 'inp.h'" '(473 characters)'
if test -f 'inp.h'
then
echo shar: "will not over-write existing file 'inp.h'"
else
sed 's/^X//' << \SHAR_EOF > 'inp.h'
X/* $Header: inp.h,v 2.0 86/09/17 15:37:25 lwall Exp $
X *
X * $Log: inp.h,v $
X * Revision 2.0 86/09/17 15:37:25 lwall
X * Baseline for netwide release.
X *
X */
X
XEXT LINENUM input_lines INIT(0); /* how long is input file in lines */
XEXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */
X /* irretractibly output */
X
Xbool rev_in_string();
Xvoid scan_input();
Xbool plan_a(); /* returns false if insufficient memory */
Xvoid plan_b();
Xchar *ifetch();
X
SHAR_EOF
if test 473 -ne "`wc -c < 'inp.h'`"
then
echo shar: "error transmitting 'inp.h'" '(should have been 473 characters)'
fi
fi
echo shar: "extracting 'malloc.c'" '(12262 characters)'
if test -f 'malloc.c'
then
echo shar: "will not over-write existing file 'malloc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'malloc.c'
X/*
X * @(#)nmalloc.c 1 (Caltech) 2/21/82
X *
X * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
X *
X * Nov 1983, Mike at BRL, Added support for 4.1C/4.2 BSD.
X *
X * This is a very fast storage allocator. It allocates blocks of a small
X * number of different sizes, and keeps free lists of each size. Blocks
X * that don't exactly fit are passed up to the next larger size. In this
X * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
X * This is designed for use in a program that uses vast quantities of
X * memory, but bombs when it runs out. To make it a little better, it
X * warns the user when he starts to get near the end.
X *
X * June 84, ACT: modified rcheck code to check the range given to malloc,
X * rather than the range determined by the 2-power used.
X *
X * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
X * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
X * You should call malloc_init to reinitialize after loading dumped Emacs.
X * Call malloc_stats to get info on memory stats if MSTATS turned on.
X * realloc knows how to return same block given, just changing its size,
X * if the power of 2 is correct.
X */
X
X/*
X * nextf[i] is the pointer to the next free block of size 2^(i+3). The
X * smallest allocatable block is 8 bytes. The overhead information will
X * go in the first int of the block, and the returned pointer will point
X * to the second.
X *
X#ifdef MSTATS
X * nmalloc[i] is the difference between the number of mallocs and frees
X * for a given block size.
X#endif /* MSTATS */
X */
X
X#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */
X#define ISFREE ((char) 0x54) /* magic byte that implies free block */
X /* this is for error checking only */
X
Xextern char etext;
X
X/* end of the program; can be changed by calling init_malloc */
Xstatic char *endofpure = &etext;
X
X#ifdef MSTATS
Xstatic int nmalloc[30];
Xstatic int nmal, nfre;
X#endif /* MSTATS */
X
X/* If range checking is not turned on, all we have is a flag indicating
X whether memory is allocated, an index in nextf[], and a size field; to
X realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
X on whether the former can hold the exact size (given the value of
X 'index'). If range checking is on, we always need to know how much space
X is allocated, so the 'size' field is never used. */
X
Xstruct mhead {
X char mh_alloc; /* ISALLOC or ISFREE */
X char mh_index; /* index in nextf[] */
X/* Remainder are valid only when block is allocated */
X unsigned short mh_size; /* size, if < 0x10000 */
X#ifdef rcheck
X unsigned mh_nbytes; /* number of bytes allocated */
X int mh_magic4; /* should be == MAGIC4 */
X#endif /* rcheck */
X };
X
X/* Access free-list pointer of a block.
X It is stored at block + 4.
X This is not a field in the mhead structure
X because we want sizeof (struct mhead)
X to describe the overhead for when the block is in use,
X and we do not want the free-list pointer to count in that. */
X
X#define CHAIN(a) \
X (*(struct mhead **) (sizeof (char *) + (char *) (a)))
X
X#ifdef rcheck
X
X/* To implement range checking, we write magic values in at the beginning and
X end of each allocated block, and make sure they are undisturbed whenever a
X free or a realloc occurs. */
X/* Written in each of the 4 bytes following the block's real space */
X#define MAGIC1 0x55
X/* Written in the 4 bytes before the block's real space */
X#define MAGIC4 0x55555555
X#define ASSERT(p) if (!(p)) botch("p"); else
Xstatic
Xbotch(s)
X char *s;
X{
X
X printf("assertion botched: %s\n", s);
X abort();
X}
X#define EXTRA 4 /* 4 bytes extra for MAGIC1s */
X#else
X#define ASSERT(p)
X#define EXTRA 0
X#endif /* rcheck */
X
X/* nextf[i] is free list of blocks of size 2**(i + 3) */
X
Xstatic struct mhead *nextf[30];
X
X#ifdef M_WARN
X/* Number of bytes of writable memory we can expect to be able to get */
Xstatic int lim_data;
X/* Level number of warnings already issued.
X 0 -- no warnings issued.
X 1 -- 75% warning already issued.
X 2 -- 85% warning already issued.
X*/
Xstatic int warnlevel;
X#endif /* M_WARN */
X
X/* nonzero once initial bunch of free blocks made */
Xstatic int gotpool;
X
X/* Cause reinitialization based on job parameters;
X also declare where the end of pure storage is. */
Xmalloc_init (end)
X char *end; {
X endofpure = end;
X#ifdef M_WARN
X lim_data = 0;
X warnlevel = 0;
X#endif /* M_WARN */
X }
X
Xstatic
Xmorecore (nu) /* ask system for more memory */
X register int nu; { /* size index to get more of */
X char *sbrk ();
X register char *cp;
X register int nblks;
X register int siz;
X
X#ifdef M_WARN
X#ifndef BSD42
X#ifdef USG
X extern long ulimit ();
X if (lim_data == 0) /* find out how much we can get */
X lim_data = ulimit (3, 0) - TEXT_START;
X#else /*HMS: was endif */
X if (lim_data == 0) /* find out how much we can get */
X lim_data = vlimit (LIM_DATA, -1);
X#endif /* USG */ /HMS:* was not here */
X#else
X if (lim_data == 0) {
X struct rlimit XXrlimit;
X
X getrlimit (RLIMIT_DATA, &XXrlimit);
X lim_data = XXrlimit.rlim_cur;} /* soft limit */
X#endif /* BSD42 */
X#endif /* M_WARN */
X
X /* On initial startup, get two blocks of each size up to 1k bytes */
X if (!gotpool)
X getpool (), getpool (), gotpool = 1;
X
X /* Find current end of memory and issue warning if getting near max */
X
X cp = sbrk (0);
X siz = cp - endofpure;
X#ifdef M_WARN
X switch (warnlevel) {
X case 0:
X if (siz > (lim_data / 4) * 3) {
X warnlevel++;
X malloc_warning ("Warning: past 75% of memory limit");}
X break;
X case 1:
X if (siz > (lim_data / 20) * 17) {
X warnlevel++;
X malloc_warning ("Warning: past 85% of memory limit");}
X break;
X case 2:
X if (siz > (lim_data / 20) * 19) {
X warnlevel++;
X malloc_warning ("Warning: past 95% of memory limit");}
X break;}
X#endif /* M_WARN */
X
X if ((int) cp & 0x3ff) /* land on 1K boundaries */
X sbrk (1024 - ((int) cp & 0x3ff));
X
X /* Take at least 2k, and figure out how many blocks of the desired size we're about to get */
X nblks = 1;
X if ((siz = nu) < 8)
X nblks = 1 << ((siz = 8) - nu);
X
X if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
X return; /* no more room! */
X if ((int) cp & 7) { /* shouldn't happen, but just in case */
X cp = (char *) (((int) cp + 8) & ~7);
X nblks--;}
X
X /* save new header and link the nblks blocks together */
X nextf[nu] = (struct mhead *) cp;
X siz = 1 << (nu + 3);
X while (1) {
X ((struct mhead *) cp) -> mh_alloc = ISFREE;
X ((struct mhead *) cp) -> mh_index = nu;
X if (--nblks <= 0) break;
X CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
X cp += siz;}
X/* CHAIN ((struct mhead *) cp) = 0; /* since sbrk() returns cleared core, this is already set */
X }
X
Xstatic
Xgetpool () {
X register int nu;
X register char *cp = sbrk (0);
X
X if ((int) cp & 0x3ff) /* land on 1K boundaries */
X sbrk (1024 - ((int) cp & 0x3ff));
X
X /* Get 2k of storage */
X
X cp = sbrk (04000);
X if (cp == (char *) -1)
X return;
X
X /* Divide it into an initial 8-word block
X plus one block of size 2**nu for nu = 3 ... 10. */
X
X CHAIN (cp) = nextf[0];
X nextf[0] = (struct mhead *) cp;
X ((struct mhead *) cp) -> mh_alloc = ISFREE;
X ((struct mhead *) cp) -> mh_index = 0;
X cp += 8;
X
X for (nu = 0; nu < 7; nu++) {
X CHAIN (cp) = nextf[nu];
X nextf[nu] = (struct mhead *) cp;
X ((struct mhead *) cp) -> mh_alloc = ISFREE;
X ((struct mhead *) cp) -> mh_index = nu;
X cp += 8 << nu;}}
X
Xchar *
Xmalloc (n) /* get a block */
X unsigned n; {
X register struct mhead *p;
X register unsigned int nbytes;
X register int nunits = 0;
X
X /* Figure out how many bytes are required, rounding up to the nearest
X multiple of 4, then figure out which nextf[] area to use */
X nbytes = (n + sizeof *p + EXTRA + 3) & ~3;
X {
X register unsigned int shiftr = (nbytes - 1) >> 2;
X
X while (shiftr >>= 1)
X nunits++;
X }
X
X /* If there are no blocks of the appropriate size, go get some */
X /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
X if (nextf[nunits] == 0)
X morecore (nunits);
X
X /* Get one block off the list, and set the new list head */
X if ((p = nextf[nunits]) == 0)
X return 0;
X nextf[nunits] = CHAIN (p);
X
X /* Check for free block clobbered */
X /* If not for this check, we would gobble a clobbered free chain ptr */
X /* and bomb out on the NEXT allocate of this size block */
X if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
X#ifdef rcheck
X botch ("block on free list clobbered");
X#else
X abort ();
X#endif /* rcheck */
X
X /* Fill in the info, and if range checking, set up the magic numbers */
X p -> mh_alloc = ISALLOC;
X#ifdef rcheck
X p -> mh_nbytes = n;
X p -> mh_magic4 = MAGIC4;
X {
X register char *m = (char *) (p + 1) + n;
X
X *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
X }
X#else
X p -> mh_size = n;
X#endif /* rcheck */
X#ifdef MSTATS
X nmalloc[nunits]++;
X nmal++;
X#endif /* MSTATS */
X return (char *) (p + 1);}
X
Xfree (mem)
X char *mem; {
X register struct mhead *p;
X {
X register char *ap = mem;
X
X ASSERT (ap != 0);
X p = (struct mhead *) ap - 1;
X ASSERT (p -> mh_alloc == ISALLOC);
X#ifdef rcheck
X ASSERT (p -> mh_magic4 == MAGIC4);
X ap += p -> mh_nbytes;
X ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
X ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1);
X#endif /* rcheck */
X }
X {
X register int nunits = p -> mh_index;
X
X ASSERT (nunits <= 29);
X p -> mh_alloc = ISFREE;
X CHAIN (p) = nextf[nunits];
X nextf[nunits] = p;
X#ifdef MSTATS
X nmalloc[nunits]--;
X nfre++;
X#endif /* MSTATS */
X }
X }
X
Xchar *
Xrealloc (mem, n)
X char *mem;
X register unsigned n; {
X register struct mhead *p;
X register unsigned int tocopy;
X register int nbytes;
X register int nunits;
X
X if ((p = (struct mhead *) mem) == 0)
X return malloc (n);
X p--;
X nunits = p -> mh_index;
X ASSERT (p -> mh_alloc == ISALLOC);
X#ifdef rcheck
X ASSERT (p -> mh_magic4 == MAGIC4);
X {
X register char *m = mem + (tocopy = p -> mh_nbytes);
X ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
X ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1);
X }
X#else
X if (p -> mh_index >= 13)
X tocopy = (1 << (p -> mh_index + 3)) - sizeof *p;
X else
X tocopy = p -> mh_size;
X#endif /* rcheck */
X
X /* See if desired size rounds to same power of 2 as actual size. */
X nbytes = (n + sizeof *p + EXTRA + 7) & ~7;
X
X /* If ok, use the same block, just marking its size as changed. */
X if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) {
X#ifdef rcheck
X register char *m = mem + tocopy;
X *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0;
X p-> mh_nbytes = n;
X m = mem + n;
X *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1;
X#else
X p -> mh_size = n;
X#endif /* rcheck */
X return mem;}
X
X if (n < tocopy)
X tocopy = n;
X {
X register char *new;
X void bcopy(); /*HMS: here? */
X
X if ((new = malloc (n)) == 0)
X return 0;
X bcopy (mem, new, tocopy);
X free (mem);
X return new;
X }
X }
X
X#ifdef MSTATS
X/* Return statistics describing allocation of blocks of size 2**n. */
X
Xstruct mstats_value {
X int blocksize;
X int nfree;
X int nused;
X };
X
Xstruct mstats_value
Xmalloc_stats (size)
X int size; {
X struct mstats_value v;
X register int i;
X register struct mhead *p;
X
X v.nfree = 0;
X
X if (size < 0 || size >= 30) {
X v.blocksize = 0;
X v.nused = 0;
X return v;}
X
X v.blocksize = 1 << (size + 3);
X v.nused = nmalloc[size];
X
X for (p = nextf[size]; p; p = CHAIN (p))
X v.nfree++;
X
X return v;}
X#endif
X
X/* how much space is available? */
X
Xunsigned freespace() {
X register int i, j;
X register struct mhead *p;
X register unsigned space = 0;
X int local; /* address only is used */
X
X space = (char *)&local - sbrk(0); /* stack space */
X
X for (i = 0; i < 30; i++) {
X for (j = 0, p = nextf[i]; p; p = CHAIN (p), j++) ;
X space += j * (1 << (i + 3));}
X
X return(space);}
X
X/* How big is this cell? */
X
Xunsigned mc_size(cp)
X char *cp;{
X register struct mhead *p;
X
X if ((p = (struct mhead *) cp) == 0) {
X /*HMS? */
X }
X p--;
X#ifdef rcheck
X return p -> mh_nbytes;
X#else
X return (1 << (p -> mh_index + 3)) - sizeof *p;
X/**/
X/* if (p -> mh_index >= 13)
X/* return (1 << (p -> mh_index + 3)) - sizeof *p;
X/* else
X/* return p -> mh_size;
X/**/
X#endif /* rcheck */
X }
X
X/*HMS: Really should use memcpy, if available... */
X
Xvoid bcopy(source, dest, len)
X register char *source, *dest;
X register len; {
X register i;
X
X for (i = 0; i < len; i++)
X *dest++ = *source++;}
SHAR_EOF
if test 12262 -ne "`wc -c < 'malloc.c'`"
then
echo shar: "error transmitting 'malloc.c'" '(should have been 12262 characters)'
fi
fi
echo shar: "extracting 'patch.c'" '(18908 characters)'
if test -f 'patch.c'
then
echo shar: "will not over-write existing file 'patch.c'"
else
sed 's/^X//' << \SHAR_EOF > 'patch.c'
Xchar rcsid[] =
X "$Header: patch.c,v 2.0.1.5 88/06/03 15:09:37 lwall Locked $";
X
X/* patch - a program to apply diffs to original files
X *
X * Copyright 1986, Larry Wall
X *
X * This program may be copied as long as you don't try to make any
X * money off of it, or pretend that you wrote it.
X *
X * $Log: patch.c,v $
X * Revision 2.0.1.5 88/06/03 15:09:37 lwall
X * patch10: exit code improved.
X * patch10: better support for non-flexfilenames.
X *
X * Revision 2.0.1.4 87/02/16 14:00:04 lwall
X * Short replacement caused spurious "Out of sync" message.
X *
X * Revision 2.0.1.3 87/01/30 22:45:50 lwall
X * Improved diagnostic on sync error.
X * Moved do_ed_script() to pch.c.
X *
X * Revision 2.0.1.2 86/11/21 09:39:15 lwall
X * Fuzz factor caused offset of installed lines.
X *
X * Revision 2.0.1.1 86/10/29 13:10:22 lwall
X * Backwards search could terminate prematurely.
X *
X * Revision 2.0 86/09/17 15:37:32 lwall
X * Baseline for netwide release.
X *
X * Revision 1.5 86/08/01 20:53:24 lwall
X * Changed some %d's to %ld's.
X * Linted.
X *
X * Revision 1.4 86/08/01 19:17:29 lwall
X * Fixes for machines that can't vararg.
X * Added fuzz factor.
X * Generalized -p.
X * General cleanup.
X *
X * 85/08/15 van%ucbmonet at berkeley
X * Changes for 4.3bsd diff -c.
X *
X * Revision 1.3 85/03/26 15:07:43 lwall
X * Frozen.
X *
X * Revision 1.2.1.9 85/03/12 17:03:35 lwall
X * Changed pfp->_file to fileno(pfp).
X *
X * Revision 1.2.1.8 85/03/12 16:30:43 lwall
X * Check i_ptr and i_womp to make sure they aren't null before freeing.
X * Also allow ed output to be suppressed.
X *
X * Revision 1.2.1.7 85/03/12 15:56:13 lwall
X * Added -p option from jromine at uci-750a.
X *
X * Revision 1.2.1.6 85/03/12 12:12:51 lwall
X * Now checks for normalness of file to patch.
X *
X * Revision 1.2.1.5 85/03/12 11:52:12 lwall
X * Added -D (#ifdef) option from joe at fluke.
X *
X * Revision 1.2.1.4 84/12/06 11:14:15 lwall
X * Made smarter about SCCS subdirectories.
X *
X * Revision 1.2.1.3 84/12/05 11:18:43 lwall
X * Added -l switch to do loose string comparison.
X *
X * Revision 1.2.1.2 84/12/04 09:47:13 lwall
X * Failed hunk count not reset on multiple patch file.
X *
X * Revision 1.2.1.1 84/12/04 09:42:37 lwall
X * Branch for sdcrdcf changes.
X *
X * Revision 1.2 84/11/29 13:29:51 lwall
X * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed
X * multiple calls to mktemp(). Will now work on machines that can only
X * read 32767 chars. Added -R option for diffs with new and old swapped.
X * Various cosmetic changes.
X *
X * Revision 1.1 84/11/09 17:03:58 lwall
X * Initial revision
X *
X */
X
X#include "INTERN.h"
X#include "common.h"
X#include "EXTERN.h"
X#include "version.h"
X#include "util.h"
X#include "pch.h"
X#include "inp.h"
X
X/* procedures */
X
Xvoid reinitialize_almost_everything();
Xvoid get_some_switches();
XLINENUM locate_hunk();
Xvoid abort_hunk();
Xvoid apply_hunk();
Xvoid init_output();
Xvoid init_reject();
Xvoid copy_till();
Xvoid spew_output();
Xvoid dump_line();
Xbool patch_match();
Xbool similar();
Xvoid re_input();
Xvoid my_exit();
X
X/* Apply a set of diffs as appropriate. */
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X LINENUM where;
X LINENUM newwhere;
X LINENUM fuzz;
X LINENUM mymaxfuzz;
X int hunk = 0;
X int failed = 0;
X int failtotal = 0;
X int i;
X
X setbuf(stderr, serrbuf);
X for (i = 0; i<MAXFILEC; i++)
X filearg[i] = Nullch;
X Mktemp(TMPOUTNAME);
X Mktemp(TMPINNAME);
X Mktemp(TMPREJNAME);
X Mktemp(TMPPATNAME);
X
X /* parse switches */
X Argc = argc;
X Argv = argv;
X get_some_switches();
X
X /* make sure we clean up /tmp in case of disaster */
X set_signals(0);
X
X for (
X open_patch_file(filearg[1]);
X there_is_another_patch();
X reinitialize_almost_everything()
X ) { /* for each patch in patch file */
X
X if (outname == Nullch)
X outname = savestr(filearg[0]);
X
X /* initialize the patched file */
X if (!skip_rest_of_patch)
X init_output(TMPOUTNAME);
X
X /* for ed script just up and do it and exit */
X if (diff_type == ED_DIFF) {
X do_ed_script();
X continue;
X }
X
X /* initialize reject file */
X init_reject(TMPREJNAME);
X
X /* find out where all the lines are */
X if (!skip_rest_of_patch)
X scan_input(filearg[0]);
X
X /* from here on, open no standard i/o files, because malloc */
X /* might misfire and we can't catch it easily */
X
X /* apply each hunk of patch */
X hunk = 0;
X failed = 0;
X out_of_mem = FALSE;
X while (another_hunk()) {
X hunk++;
X fuzz = Nulline;
X mymaxfuzz = pch_context();
X if (maxfuzz < mymaxfuzz)
X mymaxfuzz = maxfuzz;
X if (!skip_rest_of_patch) {
X do {
X where = locate_hunk(fuzz);
X if (hunk == 1 && where == Nulline && !force) {
X /* dwim for reversed patch? */
X if (!pch_swap()) {
X if (fuzz == Nulline)
X say1(
X"Not enough memory to try swapped hunk! Assuming unswapped.\n");
X continue;
X }
X reverse = !reverse;
X where = locate_hunk(fuzz); /* try again */
X if (where == Nulline) { /* didn't find it swapped */
X if (!pch_swap()) /* put it back to normal */
X fatal1("Lost hunk on alloc error!\n");
X reverse = !reverse;
X }
X else if (noreverse) {
X if (!pch_swap()) /* put it back to normal */
X fatal1("Lost hunk on alloc error!\n");
X reverse = !reverse;
X say1(
X"Ignoring previously applied (or reversed) patch.\n");
X skip_rest_of_patch = TRUE;
X }
X else {
X ask3(
X"%seversed (or previously applied) patch detected! %s -R? [y] ",
X reverse ? "R" : "Unr",
X reverse ? "Assume" : "Ignore");
X if (*buf == 'n') {
X ask1("Apply anyway? [n] ");
X if (*buf != 'y')
X skip_rest_of_patch = TRUE;
X where = Nulline;
X reverse = !reverse;
X if (!pch_swap()) /* put it back to normal */
X fatal1("Lost hunk on alloc error!\n");
X }
X }
X }
X } while (!skip_rest_of_patch && where == Nulline &&
X ++fuzz <= mymaxfuzz);
X
X if (skip_rest_of_patch) { /* just got decided */
X Fclose(ofp);
X ofp = Nullfp;
X }
X }
X
X newwhere = pch_newfirst() + last_offset;
X if (skip_rest_of_patch) {
X abort_hunk();
X failed++;
X if (verbose)
X say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
X }
X else if (where == Nulline) {
X abort_hunk();
X failed++;
X if (verbose)
X say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
X }
X else {
X apply_hunk(where);
X if (verbose) {
X say3("Hunk #%d succeeded at %ld", hunk, newwhere);
X if (fuzz)
X say2(" with fuzz %ld", fuzz);
X if (last_offset)
X say3(" (offset %ld line%s)",
X last_offset, last_offset==1L?"":"s");
X say1(".\n");
X }
X }
X }
X
X if (out_of_mem && using_plan_a) {
X Argc = Argc_last;
X Argv = Argv_last;
X say1("\n\nRan out of memory using Plan A--trying again...\n\n");
X continue;
X }
X
X assert(hunk);
X
X /* finish spewing out the new file */
X if (!skip_rest_of_patch)
X spew_output();
X
X /* and put the output where desired */
X ignore_signals();
X if (!skip_rest_of_patch) {
X if (move_file(TMPOUTNAME, outname) < 0) {
X toutkeep = TRUE;
X chmod(TMPOUTNAME, filemode);
X }
X else
X chmod(outname, filemode);
X }
X Fclose(rejfp);
X rejfp = Nullfp;
X if (failed) {
X failtotal += failed;
X if (!*rejname) {
X Strcpy(rejname, outname);
X#ifndef FLEXFILENAMES
X {
X char *s = rindex(rejname,'/');
X
X if (!s)
X s = rejname;
X if (strlen(s) > 13)
X if (s[12] == '.') /* try to preserve difference */
X s[12] = s[13]; /* between .h, .c, .y, etc. */
X s[13] = '\0';
X }
X#endif
X Strcat(rejname, REJEXT);
X }
X if (skip_rest_of_patch) {
X say4("%d out of %d hunks ignored--saving rejects to %s\n",
X failed, hunk, rejname);
X }
X else {
X say4("%d out of %d hunks failed--saving rejects to %s\n",
X failed, hunk, rejname);
X }
X if (move_file(TMPREJNAME, rejname) < 0)
X trejkeep = TRUE;
X }
X set_signals(1);
X }
X my_exit(failtotal);
X}
X
X/* Prepare to find the next patch to do in the patch file. */
X
Xvoid
Xreinitialize_almost_everything()
X{
X re_patch();
X re_input();
X
X input_lines = 0;
X last_frozen_line = 0;
X
X filec = 0;
X if (filearg[0] != Nullch && !out_of_mem) {
X free(filearg[0]);
X filearg[0] = Nullch;
X }
X
X if (outname != Nullch) {
X free(outname);
X outname = Nullch;
X }
X
X last_offset = 0;
X
X diff_type = 0;
X
X if (revision != Nullch) {
X free(revision);
X revision = Nullch;
X }
X
X reverse = FALSE;
X skip_rest_of_patch = FALSE;
X
X get_some_switches();
X
X if (filec >= 2)
X fatal1("You may not change to a different patch file.\n");
X}
X
X/* Process switches and filenames up to next '+' or end of list. */
X
Xvoid
Xget_some_switches()
X{
X Reg1 char *s;
X
X rejname[0] = '\0';
X Argc_last = Argc;
X Argv_last = Argv;
X if (!Argc)
X return;
X for (Argc--,Argv++; Argc; Argc--,Argv++) {
X s = Argv[0];
X if (strEQ(s, "+")) {
X return; /* + will be skipped by for loop */
X }
X if (*s != '-' || !s[1]) {
X if (filec == MAXFILEC)
X fatal1("Too many file arguments.\n");
X filearg[filec++] = savestr(s);
X }
X else {
X switch (*++s) {
X case 'b':
X origext = savestr(Argv[1]);
X Argc--,Argv++;
X break;
X case 'B':
X origprae = savestr(Argv[1]);
X Argc--,Argv++;
X break;
X case 'c':
X diff_type = CONTEXT_DIFF;
X break;
X case 'd':
X if (!*++s) {
X Argc--,Argv++;
X s = Argv[0];
X }
X if (chdir(s) < 0)
X fatal2("Can't cd to %s.\n", s);
X break;
X case 'D':
X do_defines = TRUE;
X if (!*++s) {
X Argc--,Argv++;
X s = Argv[0];
X }
X if (!isalpha(*s))
X fatal1("Argument to -D not an identifier.\n");
X Sprintf(if_defined, "#ifdef %s\n", s);
X Sprintf(not_defined, "#ifndef %s\n", s);
X Sprintf(end_defined, "#endif /* %s */\n", s);
X break;
X case 'e':
X diff_type = ED_DIFF;
X break;
X case 'f':
X force = TRUE;
X break;
X case 'F':
X if (*++s == '=')
X s++;
X maxfuzz = atoi(s);
X break;
X case 'l':
X canonicalize = TRUE;
X break;
X case 'n':
X diff_type = NORMAL_DIFF;
X break;
X case 'N':
X noreverse = TRUE;
X break;
X case 'o':
X outname = savestr(Argv[1]);
X Argc--,Argv++;
X break;
X case 'p':
X if (*++s == '=')
X s++;
X strippath = atoi(s);
X break;
X case 'r':
X Strcpy(rejname, Argv[1]);
X Argc--,Argv++;
X break;
X case 'R':
X reverse = TRUE;
X break;
X case 's':
X verbose = FALSE;
X break;
X case 'S':
X skip_rest_of_patch = TRUE;
X break;
X case 'v':
X version();
X break;
X#ifdef DEBUGGING
X case 'x':
X debug = atoi(s+1);
X break;
X#endif
X default:
X fatal2("Unrecognized switch: %s\n", Argv[0]);
X }
X }
X }
X}
X
X/* Attempt to find the right place to apply this hunk of patch. */
X
XLINENUM
Xlocate_hunk(fuzz)
XLINENUM fuzz;
X{
X Reg1 LINENUM first_guess = pch_first() + last_offset;
X Reg2 LINENUM offset;
X LINENUM pat_lines = pch_ptrn_lines();
X Reg3 LINENUM max_pos_offset = input_lines - first_guess
X - pat_lines + 1;
X Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1
X + pch_context();
X
X if (!pat_lines) /* null range matches always */
X return first_guess;
X if (max_neg_offset >= first_guess) /* do not try lines < 0 */
X max_neg_offset = first_guess - 1;
X if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz))
X return first_guess;
X for (offset = 1; ; offset++) {
X Reg5 bool check_after = (offset <= max_pos_offset);
X Reg6 bool check_before = (offset <= max_neg_offset);
X
X if (check_after && patch_match(first_guess, offset, fuzz)) {
X#ifdef DEBUGGING
X if (debug & 1)
X say3("Offset changing from %ld to %ld\n", last_offset, offset);
X#endif
X last_offset = offset;
X return first_guess+offset;
X }
X else if (check_before && patch_match(first_guess, -offset, fuzz)) {
X#ifdef DEBUGGING
X if (debug & 1)
X say3("Offset changing from %ld to %ld\n", last_offset, -offset);
X#endif
X last_offset = -offset;
X return first_guess-offset;
X }
X else if (!check_before && !check_after)
X return Nulline;
X }
X}
X
X/* We did not find the pattern, dump out the hunk so they can handle it. */
X
Xvoid
Xabort_hunk()
X{
X Reg1 LINENUM i;
X Reg2 LINENUM pat_end = pch_end();
X /* add in last_offset to guess the same as the previous successful hunk */
X LINENUM oldfirst = pch_first() + last_offset;
X LINENUM newfirst = pch_newfirst() + last_offset;
X LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
X LINENUM newlast = newfirst + pch_repl_lines() - 1;
X char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : "");
X char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----");
X
X fprintf(rejfp, "***************\n");
X for (i=0; i<=pat_end; i++) {
X switch (pch_char(i)) {
X case '*':
X if (oldlast < oldfirst)
X fprintf(rejfp, "*** 0%s\n", stars);
X else if (oldlast == oldfirst)
X fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
X else
X fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
X break;
X case '=':
X if (newlast < newfirst)
X fprintf(rejfp, "--- 0%s\n", minuses);
X else if (newlast == newfirst)
X fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
X else
X fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
X break;
X case '\n':
X fprintf(rejfp, "%s", pfetch(i));
X break;
X case ' ': case '-': case '+': case '!':
X fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
X break;
X default:
X say1("Fatal internal error in abort_hunk().\n");
X abort();
X }
X }
X}
X
X/* We found where to apply it (we hope), so do it. */
X
Xvoid
Xapply_hunk(where)
XLINENUM where;
X{
X Reg1 LINENUM old = 1;
X Reg2 LINENUM lastline = pch_ptrn_lines();
X Reg3 LINENUM new = lastline+1;
X#define OUTSIDE 0
X#define IN_IFNDEF 1
X#define IN_IFDEF 2
X#define IN_ELSE 3
X Reg4 int def_state = OUTSIDE;
X Reg5 bool R_do_defines = do_defines;
X Reg6 LINENUM pat_end = pch_end();
X
X where--;
X while (pch_char(new) == '=' || pch_char(new) == '\n')
X new++;
X
X while (old <= lastline) {
X if (pch_char(old) == '-') {
X copy_till(where + old - 1);
X if (R_do_defines) {
X if (def_state == OUTSIDE) {
X fputs(not_defined, ofp);
X def_state = IN_IFNDEF;
X }
X else if (def_state == IN_IFDEF) {
X fputs(else_defined, ofp);
X def_state = IN_ELSE;
X }
X fputs(pfetch(old), ofp);
X }
X last_frozen_line++;
X old++;
X }
X else if (new > pat_end)
X break;
X else if (pch_char(new) == '+') {
X copy_till(where + old - 1);
X if (R_do_defines) {
X if (def_state == IN_IFNDEF) {
X fputs(else_defined, ofp);
X def_state = IN_ELSE;
X }
X else if (def_state == OUTSIDE) {
X fputs(if_defined, ofp);
X def_state = IN_IFDEF;
X }
X }
X fputs(pfetch(new), ofp);
X new++;
X }
X else {
X if (pch_char(new) != pch_char(old)) {
X say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
X pch_hunk_beg() + old,
X pch_hunk_beg() + new);
X#ifdef DEBUGGING
X say3("oldchar = '%c', newchar = '%c'\n",
X pch_char(old), pch_char(new));
X#endif
X my_exit(1);
X }
X if (pch_char(new) == '!') {
X copy_till(where + old - 1);
X if (R_do_defines) {
X fputs(not_defined, ofp);
X def_state = IN_IFNDEF;
X }
X while (pch_char(old) == '!') {
X if (R_do_defines) {
X fputs(pfetch(old), ofp);
X }
X last_frozen_line++;
X old++;
X }
X if (R_do_defines) {
X fputs(else_defined, ofp);
X def_state = IN_ELSE;
X }
X while (pch_char(new) == '!') {
X fputs(pfetch(new), ofp);
X new++;
X }
X if (R_do_defines) {
X fputs(end_defined, ofp);
X def_state = OUTSIDE;
X }
X }
X else {
X assert(pch_char(new) == ' ');
X old++;
X new++;
X }
X }
X }
X if (new <= pat_end && pch_char(new) == '+') {
X copy_till(where + old - 1);
X if (R_do_defines) {
X if (def_state == OUTSIDE) {
X fputs(if_defined, ofp);
X def_state = IN_IFDEF;
X }
X else if (def_state == IN_IFNDEF) {
X fputs(else_defined, ofp);
X def_state = IN_ELSE;
X }
X }
X while (new <= pat_end && pch_char(new) == '+') {
X fputs(pfetch(new), ofp);
X new++;
X }
X }
X if (R_do_defines && def_state != OUTSIDE) {
X fputs(end_defined, ofp);
X }
X}
X
X/* Open the new file. */
X
Xvoid
Xinit_output(name)
Xchar *name;
X{
X ofp = fopen(name, "w");
X if (ofp == Nullfp)
X fatal2("patch: can't create %s.\n", name);
X}
X
X/* Open a file to put hunks we can't locate. */
X
Xvoid
Xinit_reject(name)
Xchar *name;
X{
X rejfp = fopen(name, "w");
X if (rejfp == Nullfp)
X fatal2("patch: can't create %s.\n", name);
X}
X
X/* Copy input file to output, up to wherever hunk is to be applied. */
X
Xvoid
Xcopy_till(lastline)
XReg1 LINENUM lastline;
X{
X Reg2 LINENUM R_last_frozen_line = last_frozen_line;
X
X if (R_last_frozen_line > lastline)
X say1("patch: misordered hunks! output will be garbled.\n");
X while (R_last_frozen_line < lastline) {
X dump_line(++R_last_frozen_line);
X }
X last_frozen_line = R_last_frozen_line;
X}
X
X/* Finish copying the input file to the output file. */
X
Xvoid
Xspew_output()
X{
X#ifdef DEBUGGING
X if (debug & 256)
X say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);
X#endif
X if (input_lines)
X copy_till(input_lines); /* dump remainder of file */
X Fclose(ofp);
X ofp = Nullfp;
X}
X
X/* Copy one line from input to output. */
X
Xvoid
Xdump_line(line)
XLINENUM line;
X{
X Reg1 char *s;
X Reg2 char R_newline = '\n';
X
X /* Note: string is not null terminated. */
X for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;
X}
X
X/* Does the patch pattern match at line base+offset? */
X
Xbool
Xpatch_match(base, offset, fuzz)
XLINENUM base;
XLINENUM offset;
XLINENUM fuzz;
X{
X Reg1 LINENUM pline = 1 + fuzz;
X Reg2 LINENUM iline;
X Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
X
X for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) {
X if (canonicalize) {
X if (!similar(ifetch(iline, (offset >= 0)),
X pfetch(pline),
X pch_line_len(pline) ))
X return FALSE;
X }
X else if (strnNE(ifetch(iline, (offset >= 0)),
X pfetch(pline),
X pch_line_len(pline) ))
X return FALSE;
X }
X return TRUE;
X}
X
X/* Do two lines match with canonicalized white space? */
X
Xbool
Xsimilar(a,b,len)
XReg1 char *a;
XReg2 char *b;
XReg3 int len;
X{
X while (len) {
X if (isspace(*b)) { /* whitespace (or \n) to match? */
X if (!isspace(*a)) /* no corresponding whitespace? */
X return FALSE;
X while (len && isspace(*b) && *b != '\n')
X b++,len--; /* skip pattern whitespace */
X while (isspace(*a) && *a != '\n')
X a++; /* skip target whitespace */
X if (*a == '\n' || *b == '\n')
X return (*a == *b); /* should end in sync */
X }
X else if (*a++ != *b++) /* match non-whitespace chars */
X return FALSE;
X else
X len--; /* probably not necessary */
X }
X return TRUE; /* actually, this is not reached */
X /* since there is always a \n */
X}
X
X/* Exit with cleanup. */
X
Xvoid
Xmy_exit(status)
Xint status;
X{
X Unlink(TMPINNAME);
X if (!toutkeep) {
X Unlink(TMPOUTNAME);
X }
X if (!trejkeep) {
X Unlink(TMPREJNAME);
X }
X Unlink(TMPPATNAME);
X exit(status);
X}
SHAR_EOF
if test 18908 -ne "`wc -c < 'patch.c'`"
then
echo shar: "error transmitting 'patch.c'" '(should have been 18908 characters)'
fi
fi
echo shar: "extracting 'util.h'" '(1972 characters)'
if test -f 'util.h'
then
echo shar: "will not over-write existing file 'util.h'"
else
sed 's/^X//' << \SHAR_EOF > 'util.h'
X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $
X *
X * $Log: util.h,v $
X * Revision 2.0 86/09/17 15:40:06 lwall
X * Baseline for netwide release.
X *
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]; /* 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();
SHAR_EOF
if test 1972 -ne "`wc -c < 'util.h'`"
then
echo shar: "error transmitting 'util.h'" '(should have been 1972 characters)'
fi
fi
echo shar: "extracting 'version.c'" '(489 characters)'
if test -f 'version.c'
then
echo shar: "will not over-write existing file 'version.c'"
else
sed 's/^X//' << \SHAR_EOF > 'version.c'
X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $
X *
X * $Log: version.c,v $
X * Revision 2.0 86/09/17 15:40:11 lwall
X * Baseline for netwide release.
X *
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{
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}
SHAR_EOF
if test 489 -ne "`wc -c < 'version.c'`"
then
echo shar: "error transmitting 'version.c'" '(should have been 489 characters)'
fi
fi
echo shar: "extracting 'version.h'" '(185 characters)'
if test -f 'version.h'
then
echo shar: "will not over-write existing file 'version.h'"
else
sed 's/^X//' << \SHAR_EOF > 'version.h'
X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $
X *
X * $Log: version.h,v $
X * Revision 2.0 86/09/17 15:40:14 lwall
X * Baseline for netwide release.
X *
X */
X
Xvoid version();
SHAR_EOF
if test 185 -ne "`wc -c < 'version.h'`"
then
echo shar: "error transmitting 'version.h'" '(should have been 185 characters)'
fi
fi
exit 0
# End of shell archive
More information about the Unix-pc.sources
mailing list