[comp.unix.xenix] Patches to get large memory model

wietse@eurifb.UUCP (Wietse Venema) (09/09/87)

The following patches are required to run large-memory model (di)troff on 80286 
machines. We needed this for complicated mathematical typesetting with lots of
macros etcetera. The nontrivial changes have to do with troff's particular way
of memory management (both ram and disk). The mods have been verified to work
with Microport System-V/AT 2.2 but should be good for 80286 Xenix as well.

If you have Larry Wall's program execute the command: 

	patch -d troff/src/text/roff.d <thismessage

Otherwise, you will have to apply the modifications by hand.

		W.Z. Venema	(uucp:	..!mcvax!eutrc3!wswietse
				bitnet:	wswietse@heithe5)



Brief descriptions of the modifications:

1) Use a memory allocation scheme based on malloc() instead of sbrk().
   The original source makes some assumptions about contiguous memory
   which grows upwards, which is not valid for large memory models
   on a 80286 machine.
   These changes #ifdef-ed with NOBRK.
2) Portability problems (sizeof(int) != sizeof(char *)).
   These changes #ifdef-ed with PORTABLE.
3) Portability problems (sizeof(int) != sizeof(long)) when temp files 
   larger than > 4*64kb are used. These changes #ifdef-ed with PORTABLE,
   but ineffective when SMALLER is #define-d.

The diffs apply to the following set of ditroff sources:

	ext.h	2.8
	hytab.c	2.3
	n1.c	2.13
	n2.c	2.6
	n3.c	2.13
	n4.c	2.5
	n5.c	2.9
	n7.c	2.8
	n8.c	2.5
	n9.c	2.6
	ni.c	2.7
	nii.c	2.7
	suftab.c	2.4
	tdef.h	2.13
	troff.d/dev.h	2.4
	troff.d/draw.c	2.3
	troff.d/hc.c	2.4
	troff.d/makedev.c	2.5
	troff.d/t10.c	2.7
	troff.d/t6.c	2.9
	troff.d/ta.c	2.5
	troff.d/tc.c	2.5

*** n1.c.orig	Thu Sep  3 16:48:04 1987
--- n1.c	Wed Sep  9 12:17:23 1987
***************
*** 294,300 ****
--- 294,305 ----
  	cpushback(ibuf);
  	ibufp = ibuf;
  	nx = mflg;
+ #ifdef	NOBRK		/* setbrk() versus malloc() */
+ #define	STKSIZE 20000
+ 	enda = (char *)(frame = stk = (struct s *)setbrk(STKSIZE))+STKSIZE;
+ #else
  	frame = stk = (struct s *)setbrk(DELTA);
+ #endif
  	dip = &d[0];
  	nxf = frame + 1;
  #ifdef INCORE
***************
*** 437,443 ****
--- 442,452 ----
  			putchar('\\');
  		putchar(*adx & 0177);
  	} else if (c == 's') {
+ #ifdef	PORTABLE	/* needed if sizeof(int) != sizeof(char *) */
+ 		s = (char *) * (char **) adx;
+ #else
  		s = (char *) * adx;
+ #endif
  		while (c = *s++)
  			putchar(c);
  	} else if (c == 'D') {
***************
*** 509,515 ****
--- 518,528 ----
  			*str++ = '\\';
  		*str++ = *adx & 0177;
  	} else if (c == 's') {
+ #ifdef	PORTABLE	/* needed if sizeof(int) != sizeof(char *) */
+ 		s = (char *) * (char **) adx;
+ #else
  		s = (char *) * adx;
+ #endif
  		while (c = *s++)
  			*str++ = c;
  	} else if (c == 'D') {
***************
*** 543,548 ****
--- 556,564 ----
  }
  
  
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ filep
+ #endif
  control(a, b)
  register int	a, b;
  {
*** n3.c.orig	Thu Sep  3 16:48:08 1987
--- n3.c	Wed Sep  9 12:47:45 1987
***************
*** 248,254 ****
--- 248,258 ----
  			edone(04);
  			return(offset = 0);
  		}
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 		contab[i].mx = nextb;
+ #else
  		contab[i].mx = (unsigned) nextb;
+ #endif
  		if (!diflg) {
  			newmn = i;
  			if (oldmn == -1)
***************
*** 396,402 ****
--- 400,410 ----
  {
  	register j;
  
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 	while (blist[j = blisti(i)] != (filep) ~0) {
+ #else
  	while (blist[j = blisti(i)] != (unsigned) ~0) {
+ #endif
  		i = (filep) blist[j];
  		blist[j] = 0;
  	}
***************
*** 433,444 ****
--- 441,460 ----
  			errprint("Out of temp file space");
  			done2(01);
  		}
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 		if (blist[j] == (filep) ~0) {
+ #else
  		if (blist[j] == (unsigned) ~0) {
+ #endif
  			if (alloc() == 0) {
  				errprint("Out of temp file space");
  				done2(01);
  			}
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 			blist[j] = (nextb);
+ #else
  			blist[j] = (unsigned)(nextb);
+ #endif
  		}
  		offset = ((filep)blist[j]);
  	}
***************
*** 497,503 ****
--- 513,523 ----
  	/* this is an inline expansion of incoff: also dirty */
  	p = ++ip;
  	if ((p & (BLK - 1)) == 0) {
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 		if ((ip = blist[blisti(p-1)]) == (filep) ~0) {
+ #else
  		if ((ip = blist[blisti(p-1)]) == (unsigned) ~0) {
+ #endif
  			errprint("Bad storage allocation");
  			ip = 0;
  			done2(-5);
***************
*** 539,545 ****
--- 559,569 ----
  {
  	p++;
  	if ((p & (BLK - 1)) == 0) {
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 		if ((p = blist[blisti(p-1)]) == (filep) ~0) {
+ #else
  		if ((p = blist[blisti(p-1)]) == (unsigned) ~0) {
+ #endif
  			errprint("Bad storage allocation");
  			done2(-5);
  		}
***************
*** 569,576 ****
   *	test that the end of the allocation is above a certain location
   *	in memory
   */
! #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
  
  pushi(newip, mname)
  filep newip;
  int mname;
--- 593,607 ----
   *	test that the end of the allocation is above a certain location
   *	in memory
   */
! #ifdef	NOBRK		/* setbrk() versus malloc() */
! # define SPACETEST(base, size) if ((enda - (size)) <= (char *)(base)) {nomem();}
! #else
! # define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
! #endif
  
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ filep
+ #endif
  pushi(newip, mname)
  filep newip;
  int mname;
***************
*** 596,603 ****
--- 627,691 ----
  	return(ip = newip);
  }
  
+ #ifdef	NOBRK		/* sbrk() versus malloc() */
  
+ /* 
+ **	Explanation of the NOBRK modifications 
+ **	W.Z. Venema (..!mcvax!eutrc3!wswietse)
+ **	Thu Sep  3 22:14:12 MED 1987
+ **
+ **	In the original design, the stack for macro processing
+ **	is located at the end of the data segment. Software 
+ **	assumes that this stack is a contiguous region of space 
+ **	which can be extended upwards when more memory is needed
+ **	(using the sbrk() system call).
+ **	This assumption is not valid for the large memory model
+ **	of 8086, 80286 processors.
+ **
+ **	To overcome this problem we must allocate sufficient memory 
+ **	for the stack with a single malloc() call. The stack cannot be
+ **	extended (via realloc()) since this memory region contains
+ **	pointers to itself; realloc() might move the stack, thus
+ **	invalidating the pointers.
+ **
+ **	In order to make as little changes to the sources as possible
+ **	we have changed the semantics of some variables and data:
+ **
+ **	char *setbrk()	extend the data segment	| allocate an amount
+ **	(file n3.c)	and set enda to the end	| of memory (using
+ **			of the allocation + 1.	| malloc()).
+ **
+ **	char *enda	first memory location 	| first memory location
+ **	(file n1.c)	beyond allocated memory	| beyond the end of memory
+ **						| for macro processing
+ */
+ 
+ /* nomem - handle out-of-memory problems */
+ 
+ static nomem()
+ {
+ 	errprint("Core limit reached");
+ 	edone(0100);
+ }
+ 
+ /* setbrk - only the name is the same as the original */
+ 
  char	*setbrk(x)
+ unsigned x;
+ {
+ 	register char *p;
+ 	char *malloc();
+ 
+ 	/* malloc() automatically takes care of memory alignment */
+ 
+ 	if ((p = malloc(x)) == 0)
+ 		    nomem();
+ 	return(p);
+ }
+ 
+ #else
+ 
+ char	*setbrk(x)
  int	x;
  {
  	register char	*i, *k;
***************
*** 625,630 ****
--- 713,719 ----
  	return(i);
  }
  
+ #endif	/* NOBRK */
  
  getsn()
  {
***************
*** 639,644 ****
--- 728,736 ----
  }
  
  
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ filep
+ #endif
  setstr()
  {
  	register i, j;
***************
*** 908,914 ****
--- 1000,1010 ----
  		p = pmline;
  		j = (filep) contab[i].mx;
  		k = 1;
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 		while ((j = blist[blisti(j)]) != (filep) ~0) {
+ #else
  		while ((j = blist[blisti(j)]) != (unsigned) ~0) {
+ #endif
  			k++; 
  		}
  		cnt++;
*** n5.c.orig	Thu Sep  3 16:48:11 1987
--- n5.c	Sat Sep  5 16:37:39 1987
***************
*** 729,735 ****
--- 729,739 ----
  	}
  	collect();
  	tty++;
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 	pushi((filep)NBLIST*BLK, PAIR('r','d'));
+ #else
  	pushi(NBLIST*BLK, PAIR('r','d'));
+ #endif
  }
  
  
*** tdef.h.orig	Thu Sep  3 16:48:16 1987
--- tdef.h	Wed Sep  9 12:48:00 1987
***************
*** 237,244 ****
   * BLK must be a power of 2
   */
  
! typedef unsigned int filep;	/* this is good for 32 bit machines */
  
  #define	BLK	128	/* alloc block in tchars */
  
  #ifdef SMALLER
--- 237,250 ----
   * BLK must be a power of 2
   */
  
! /* on 16 bit machines 'int filep' requires an NBLIST of 512 */
  
+ #ifdef SMALLER
+ typedef unsigned int filep;	/* this is good for 16 bit machines */
+ #else
+ typedef unsigned long filep;	/* this is good for 16 and 32 bit machines */
+ #endif
+ 
  #define	BLK	128	/* alloc block in tchars */
  
  #ifdef SMALLER
***************
*** 248,253 ****
--- 254,265 ----
  				/* machines with paging can use 2048 */
  #endif
  
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ extern	filep	pushi();
+ extern	filep	setstr();
+ extern	filep	control();
+ #endif
+ 
  /* Other things are stored in the temp file or corebuf:
   *	a single block for .rd input, at offset RD_OFFSET
   *	NEV copies of the environment block, at offset ENV_OFFSET
***************
*** 344,350 ****
--- 356,366 ----
  	unsigned short	rq;
  	struct	contab *link;
  	int	(*f)();
+ #ifdef	PORTABLE	/* needed if sizeof(filep) != sizeof(int) */
+ 	filep	mx;
+ #else
  	unsigned mx;
+ #endif
  } contab[NM];
  
  extern struct numtab {
*** troff.d/t6.c.orig	Thu Sep  3 16:47:47 1987
--- troff.d/t6.c	Sat Sep  5 19:01:28 1987
***************
*** 420,426 ****
--- 420,430 ----
  	if (i == 'S' || i == '0')
  		return;
  	if ((j = findft(i)) == -1)
+ #ifdef	PORTABLE	/* needed if sizeof(char *) != sizeof(int) */
+ 		if ((j = setfp(0, i, (char *) 0)) == -1)	/* try to put it in position 0 */
+ #else
  		if ((j = setfp(0, i, 0)) == -1)	/* try to put it in position 0 */
+ #endif
  			return;
  s0:
  	font1 = font;
***************
*** 605,611 ****
--- 609,619 ----
  	else if (skip() || !(j = getrq()))
  		errprint("fp: no font name"); 
  	else if (skip() || !getname())
+ #ifdef	PORTABLE	/* needed if sizeof(char *) != sizeof(int) */
+ 		setfp(i, j, (char *) 0);
+ #else
  		setfp(i, j, 0);
+ #endif
  	else		/* 3rd argument = filename */
  		setfp(i, j, nextf);
  }