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); }