+-+-+-+ Beginning of part 4 +-+-+-+ Xstruct mhead `123 X`009char mh_alloc;`009/* ISALLOC or ISFREE */ X`009char mh_index;`009/* index in nextf[] */ X/* Remainder are valid only when block is allocated */ X`009unsigned short mh_size;`009/* size, if < 0x10000 */ X#ifdef rcheck X`009unsigned mh_nbytes;`009/* number of bytes allocated */ X`009int mh_magic4;`009/* should be == MAGIC4 */ X#endif /* rcheck */ X`009`125; 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`009char *s; X`123 X X`009printf("assertion botched: %s\n", s); X`009abort(); X`125 X#define EXTRA 4`009`009/* 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`009M_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; `123 X`009endofpure = end; X#ifdef`009M_WARN X`009lim_data = 0; X`009warnlevel = 0; X#endif /* M_WARN */ X`009`125 X`012 Xstatic Xmorecore (nu)`009`009`009/* ask system for more memory */ X register int nu; `123`009`009/* size index to get more of */ X`009char *sbrk (); X`009register char *cp; X`009register int nblks; X`009register int siz; X X#ifdef`009M_WARN X#ifndef BSD42 X#ifdef USG X`009extern long ulimit (); X`009if (lim_data == 0)`009`009/* find out how much we can get */ X`009 lim_data = ulimit (3, 0) - TEXT_START; X#else`009/*HMS: was endif */ X`009if (lim_data == 0)`009`009/* find out how much we can get */ X`009 lim_data = vlimit (LIM_DATA, -1); X#endif /* USG */`009/HMS:* was not here */ X#else X`009if (lim_data == 0) `123 X`009`009struct rlimit XXrlimit; X X`009`009getrlimit (RLIMIT_DATA, &XXrlimit); X`009`009lim_data = XXrlimit.rlim_cur;`125`009/* soft limit */ X#endif /* BSD42 */ X#endif /* M_WARN */ X X`009/* On initial startup, get two blocks of each size up to 1k bytes */ X`009if (!gotpool) X`009 getpool (), getpool (), gotpool = 1; X X`009/* Find current end of memory and issue warning if getting near max */ X X`009cp = sbrk (0); X`009siz = cp - endofpure; X#ifdef`009M_WARN X`009switch (warnlevel) `123 X`009 case 0: X`009`009if (siz > (lim_data / 4) * 3) `123 X`009`009`009warnlevel++; X`009`009`009malloc_warning ("Warning: past 75% of memory limit");`125 X`009`009break; X`009 case 1: X`009`009if (siz > (lim_data / 20) * 17) `123 X`009`009`009warnlevel++; X`009`009`009malloc_warning ("Warning: past 85% of memory limit");`125 X`009`009break; X`009 case 2: X`009`009if (siz > (lim_data / 20) * 19) `123 X`009`009`009warnlevel++; X`009`009`009malloc_warning ("Warning: past 95% of memory limit");`125 X`009`009break;`125 X#endif /* M_WARN */ X X`009if ((int) cp & 0x3ff)`009/* land on 1K boundaries */ X`009 sbrk (1024 - ((int) cp & 0x3ff)); X V`009/* Take at least 2k, and figure out how many blocks of the desired size w Xe're about to get */ X`009nblks = 1; X`009if ((siz = nu) < 8) X`009 nblks = 1 << ((siz = 8) - nu); X X`009if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) X`009 return;`009`009`009/* no more room! */ X`009if ((int) cp & 7) `123`009`009/* shouldn't happen, but just in case */ X`009`009cp = (char *) (((int) cp + 8) & `1267); X`009`009nblks--;`125 X X`009/* save new header and link the nblks blocks together */ X`009nextf[nu] = (struct mhead *) cp; X`009siz = 1 << (nu + 3); X`009while (1) `123 X`009`009((struct mhead *) cp) -> mh_alloc = ISFREE; X`009`009((struct mhead *) cp) -> mh_index = nu; X`009`009if (--nblks <= 0) break; X`009`009CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); X`009`009cp += siz;`125 V/*`009CHAIN ((struct mhead *) cp) = 0;`009/* since sbrk() returns cleared cor Xe, this is already set */ X`009`125 X Xstatic Xgetpool () `123 X`009register int nu; X`009register char *cp = sbrk (0); X X`009if ((int) cp & 0x3ff)`009/* land on 1K boundaries */ X`009 sbrk (1024 - ((int) cp & 0x3ff)); X X`009/* Get 2k of storage */ X X`009cp = sbrk (04000); X`009if (cp == (char *) -1) X`009 return; X X`009/* Divide it into an initial 8-word block X`009plus one block of size 2**nu for nu = 3 ... 10. */ X X`009CHAIN (cp) = nextf[0]; X`009nextf[0] = (struct mhead *) cp; X`009((struct mhead *) cp) -> mh_alloc = ISFREE; X`009((struct mhead *) cp) -> mh_index = 0; X`009cp += 8; X X`009for (nu = 0; nu < 7; nu++) `123 X`009`009CHAIN (cp) = nextf[nu]; X`009`009nextf[nu] = (struct mhead *) cp; X`009`009((struct mhead *) cp) -> mh_alloc = ISFREE; X`009`009((struct mhead *) cp) -> mh_index = nu; X`009`009cp += 8 << nu;`125`125 X`012 Xchar * Xmalloc (n)`009`009/* get a block */ X unsigned n; `123 X`009register struct mhead *p; X`009register unsigned int nbytes; X`009register int nunits = 0; X X`009/* Figure out how many bytes are required, rounding up to the nearest X`009multiple of 4, then figure out which nextf[] area to use */ X`009nbytes = (n + sizeof *p + EXTRA + 3) & `1263; X`009`009`123 X`009`009register unsigned int shiftr = (nbytes - 1) >> 2; X X`009`009while (shiftr >>= 1) X`009`009 nunits++; X`009`009`125 X X`009/* If there are no blocks of the appropriate size, go get some */ X`009/* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ X`009if (nextf[nunits] == 0) X`009 morecore (nunits); X X`009/* Get one block off the list, and set the new list head */ X`009if ((p = nextf[nunits]) == 0) X`009 return 0; X`009nextf[nunits] = CHAIN (p); X X`009/* Check for free block clobbered */ X`009/* If not for this check, we would gobble a clobbered free chain ptr */ X`009/* and bomb out on the NEXT allocate of this size block */ X`009if (p -> mh_alloc != ISFREE `124`124 p -> mh_index != nunits) X#ifdef rcheck X`009 botch ("block on free list clobbered"); X#else X`009 abort (); X#endif /* rcheck */ X X`009/* Fill in the info, and if range checking, set up the magic numbers */ X`009p -> mh_alloc = ISALLOC; X#ifdef rcheck X`009p -> mh_nbytes = n; X`009p -> mh_magic4 = MAGIC4; X`009`009`123 X`009`009register char *m = (char *) (p + 1) + n; X X`009`009*m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; X`009`009`125 X#else X`009p -> mh_size = n; X#endif /* rcheck */ X#ifdef MSTATS X`009nmalloc[nunits]++; X`009nmal++; X#endif /* MSTATS */ X`009return (char *) (p + 1);`125 X Xfree (mem) X char *mem; `123 X`009register struct mhead *p; X`009`009`123 X`009`009register char *ap = mem; X X`009`009ASSERT (ap != 0); X`009`009p = (struct mhead *) ap - 1; X`009`009ASSERT (p -> mh_alloc == ISALLOC); X#ifdef rcheck X`009`009ASSERT (p -> mh_magic4 == MAGIC4); X`009`009ap += p -> mh_nbytes; X`009`009ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); X`009`009ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); X#endif /* rcheck */ X`009`009`125 X`009`009`123 X`009`009register int nunits = p -> mh_index; X X`009`009ASSERT (nunits <= 29); X`009`009p -> mh_alloc = ISFREE; X`009`009CHAIN (p) = nextf[nunits]; X`009`009nextf[nunits] = p; X#ifdef MSTATS X`009`009nmalloc[nunits]--; X`009`009nfre++; X#endif /* MSTATS */ X`009`009`125 X`009`125 X Xchar * Xrealloc (mem, n) X char *mem; X register unsigned n; `123 X`009register struct mhead *p; X`009register unsigned int tocopy; X`009register int nbytes; X`009register int nunits; X X`009if ((p = (struct mhead *) mem) == 0) X`009 return malloc (n); X`009p--; X`009nunits = p -> mh_index; X`009ASSERT (p -> mh_alloc == ISALLOC); X#ifdef rcheck X`009ASSERT (p -> mh_magic4 == MAGIC4); X`009`009`123 X`009`009register char *m = mem + (tocopy = p -> mh_nbytes); X`009`009ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); X`009`009ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); X`009`009`125 X#else X`009if (p -> mh_index >= 13) X`009 tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; X`009else X`009 tocopy = p -> mh_size; X#endif /* rcheck */ X X`009/* See if desired size rounds to same power of 2 as actual size. */ X`009nbytes = (n + sizeof *p + EXTRA + 7) & `1267; X X`009/* If ok, use the same block, just marking its size as changed. */ X`009if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) `123 X#ifdef rcheck X`009`009register char *m = mem + tocopy; X`009`009*m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; X`009`009p-> mh_nbytes = n; X`009`009m = mem + n; X`009`009*m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; X#else X`009`009p -> mh_size = n; X#endif /* rcheck */ X`009`009return mem;`125 X X`009if (n < tocopy) X`009 tocopy = n; X`009`009`123 X`009`009register char *new; X`009`009void bcopy();`009/*HMS: here? */ X X`009`009if ((new = malloc (n)) == 0) X`009`009 return 0; X`009`009bcopy (mem, new, tocopy); X`009`009free (mem); X`009`009return new; X`009`009`125 X`009`125 X`012 X#ifdef MSTATS X/* Return statistics describing allocation of blocks of size 2**n. */ X Xstruct mstats_value `123 X`009int blocksize; X`009int nfree; X`009int nused; X`009`125; X Xstruct mstats_value Xmalloc_stats (size) X int size; `123 X`009struct mstats_value v; X`009register int i; X`009register struct mhead *p; X X`009v.nfree = 0; X X`009if (size < 0 `124`124 size >= 30) `123 X`009`009v.blocksize = 0; X`009`009v.nused = 0; X`009`009return v;`125 X X`009v.blocksize = 1 << (size + 3); X`009v.nused = nmalloc[size]; X X`009for (p = nextf[size]; p; p = CHAIN (p)) X`009 v.nfree++; X X`009return v;`125 X#endif X X/* how much space is available? */ X Xunsigned freespace() `123 X `009register int i, j; X `009register struct mhead *p; X `009register unsigned space = 0; X`009int local;`009/* address only is used */ X X`009space = (char *)&local - sbrk(0);`009/* stack space */ X X `009for (i = 0; i < 30; i++) `123 X `009`009for (j = 0, p = nextf[i]; p; p = CHAIN (p), j++) ; X `009`009space += j * (1 << (i + 3));`125 X X`009return(space);`125 X X/* How big is this cell? */ X Xunsigned mc_size(cp) X char *cp;`123 X`009register struct mhead *p; X X`009if ((p = (struct mhead *) cp) == 0) `123 X`009`009/*HMS? */ X`009`009`125 X`009p--; X#ifdef rcheck X`009return p -> mh_nbytes; X#else X`009return (1 << (p -> mh_index + 3)) - sizeof *p; X/**/ X/*`009if (p -> mh_index >= 13) X/*`009 return (1 << (p -> mh_index + 3)) - sizeof *p; X/*`009else X/*`009 return p -> mh_size; X/**/ X#endif /* rcheck */ X`009`125 X X/*HMS: Really should use memcpy, if available... */ X Xvoid bcopy(source, dest, len) X register char *source, *dest; X register len; `123 X`009register i; X`009 X`009for (i = 0; i < len; i++) X`009 *dest++ = *source++;`125 $ GOSUB UNPACK_FILE $ FILE_IS = "MANIFEST." $ CHECKSUM_IS = 1497379782 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY XAfter all the patch kits are run you should have the following files: X XFilename`009`009Kit Description X--------`009`009--- ----------- VConfigure 1 A shell script that installs everything system dep Xendent. XEXTERN.h 4 Toggle .h files to look foreign. XINTERN.h 4 Toggle .h files to look domestic. XMANIFEST 2 This list of files. XMakefile.SH 2 The makefile. XREADME 1 Installation instructions. Xcommon.h 3 Common definitions. Xconfig.H 4 Sample config.h, in case Configure won't run. Xconfig.h.SH 3 Produces config.h. Xinp.c 3 Input file abstract data type routines. Xinp.h 3 Public defs for above. Xmalloc.c 1 An optional malloc package. Xpatch.c 3 The patch program. Xpatch.man 2 Manual page for patch. Xpatchlevel.h 4 The patch level of the patch program. Xpch.c 2 Patch abstract data type routines. Xpch.h 3 Public defs for above. Xutil.c 3 Utility routines. Xutil.h 3 Public defs for above. Xversion.c 1 Version number routine. Xversion.h 4 Public defs for above. $ GOSUB UNPACK_FILE $ FILE_IS = "PATCH.C" $ CHECKSUM_IS = 1231581509 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY Xchar rcsid[] = X`009"$Header: patch.c,v 2.0.1.6 88/06/22 20:46:39 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:`009patch.c,v $ X * Revision 2.0.1.6 88/06/22 20:46:39 lwall X * patch12: rindex() wasn't declared X * 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@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@uci-750a. X * -+-+-+-+-+ End of part 4 +-+-+-+-+-