static char sccsid
[] = "@(#)n3.c 2.3 (CWI) 86/11/27";
* macro and string routines, storage allocation
#define MHASH(x) ((x>>6)^x)&0177
struct contab
*mhash
[128]; /* 128 == the 0177 on line above */
#define blisti(i) (((i)-NEV*(int)sizeof(env))/BLK)
tchar corebuf
[NEV
*sizeof(env
)/sizeof(tchar
) + NBLIST
*BLK
+ 1];
if ((i
= copyb()) != '.')
if ((i
= getrq()) == 0 || (oldmn
= findmn(i
)) < 0)
clrmn(findmn(j
= getrq()));
maddhash(&contab
[oldmn
]);
register struct contab
*rp
;
register struct contab
**hp
;
hp
= &mhash
[MHASH(rp
->rq
)];
register struct contab
*mp
;
register struct contab
*p
;
register struct contab
**lp
;
lp
= &mhash
[MHASH(mp
->rq
)];
register struct contab
*p
;
for (p
=contab
; p
< &contab
[NM
]; p
++)
for (p
=contab
; p
< &contab
[NM
]; p
++) {
while (!skip() && (j
= getrq()) != 0)
if ((offset
= finds(i
)) == 0)
maddhash(&contab
[newmn
]);
register struct contab
*p
;
for (p
= mhash
[MHASH(i
)]; p
; p
= p
->link
)
ffree((filep
)contab
[i
].mx
);
if (app
&& oldmn
>= 0 && contab
[oldmn
].mx
) {
ip
= (filep
)contab
[oldmn
].mx
;
for (i
= 0; i
< NM
; i
++) {
if (i
== NM
|| (nextb
= alloc()) == 0) {
errprint("Too many (%d) string/macro names", NM
);
contab
[i
].mx
= (unsigned) nextb
;
while (cbits(i
= getch()) == ' ')
if (skip() || !(j
= getrq()))
if (state
== 1 && i
== '.') {
if ((state
== 2) && (i
== j
)) {
if (cbits(i
= getch()) != '"')
while (cbits(i
= getch()) != '\n')
for (i
= 0; i
< NBLIST
; i
++) {
if ((j
= ((filep
)i
* BLK
+ NEV
*(int)sizeof(env
))) < NEV
*(int)sizeof(env
))
while (blist
[j
= blisti(i
)] != (unsigned) ~0) {
wbuf
= &corebuf
[woff
]; /* INCORE only */
if (!((++offset
) & (BLK
- 1))) {
if (j
< 0 || j
>= NBLIST
) {
errprint("Out of temp file space");
if (blist
[j
] == (unsigned) ~0) {
errprint("Out of temp file space");
blist
[j
] = (unsigned)(nextb
);
offset
= ((filep
)blist
[j
]);
lseek(ibf
, ((long)woff
) * sizeof(tchar
), 0);
write(ibf
, (char *)wbuf
, wbfi
* sizeof(tchar
));
if ((woff
& (~(BLK
- 1))) == (roff
& (~(BLK
- 1))))
if (ip
== NBLIST
*BLK
) { /* for rdtty */
/* this is an inline expansion of rbf0: dirty! */
lseek(ibf
, (long)j
* sizeof(tchar
), 0);
if (read(ibf
, (char *)rbuf
, BLK
* sizeof(tchar
)) <= 0)
/* this is an inline expansion of incoff: also dirty */
if ((p
& (BLK
- 1)) == 0) {
if ((ip
= blist
[blisti(p
-1)]) == (unsigned) ~0) {
errprint("Bad storage allocation");
/* this was meant to protect against people removing
/* the macro they were standing on, but it's too
/* sensitive to block boundaries.
/* errprint("Block removed while in use");
if ((i
= p
& ~(BLK
- 1)) != roff
) {
lseek(ibf
, (long)roff
* sizeof(tchar
), 0);
if (read(ibf
, (char *)rbuf
, BLK
* sizeof(tchar
)) == 0)
return(rbuf
[p
& (BLK
-1)]);
if ((p
& (BLK
- 1)) == 0) {
if ((p
= blist
[blisti(p
-1)]) == (unsigned) ~0) {
errprint("Bad storage allocation");
* test that the end of the allocation is above a certain location
#define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
SPACETEST(nxf
, sizeof(struct s
));
nxf
= (struct s
*)argtop
;
if (j
= x
% sizeof(int)) /*allocate only whole words for 3B*/
if ((i
= sbrk(x
)) == (char *) -1) {
errprint("Core limit reached");
if ((unsigned)i
% sizeof(int)) { /*check alignment for 3B*/
errprint("alignment problem");
if ((i
= getsn()) == 0 || (j
= findmn(i
)) == -1 || !contab
[j
].mx
) {
SPACETEST(nxf
, sizeof(struct s
));
return pushi((filep
)contab
[j
].mx
, i
);
tchar
* *argpp
, **argppend
;
* 1 s structure for the macro descriptor
* APERMAC tchar *'s for pointers into the strings
* space for the tchar's themselves
memp
+= sizeof(struct s
);
* CPERMAC (the total # of characters for ALL arguments)
* to a macros, has been carefully chosen
* so that the distance between stack frames is < DELTA
memp
+= APERMAC
* sizeof(tchar
*);
memp
+= CPERMAC
* sizeof(tchar
);
argpp
= (tchar
**)(savnxf
+ 1);
argppend
= &argpp
[APERMAC
];
SPACETEST(argppend
, sizeof(tchar
*));
strp
= (tchar
*)argppend
;
* Zero out all the string pointers before filling them in.
for (j
= 0; j
< APERMAC
; j
++){
errprint("savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x",
savnxf
, nxf
, argpp
, strp
, lim
, enda
);
while ((argpp
!= argppend
) && (!skip())) {
if (cbits(i
= getch()) == '"')
if (nlflg
|| (!quote
&& cbits(i
) == ' '))
&& (cbits(i
= getch()) != '"')) {
if (strflg
&& strp
>= lim
) {
errprint("strp=0x%x, lim = 0x%x",
errprint("Macro argument too long");
SPACETEST(strp
, 3 * sizeof(tchar
));
nxf
->nargs
= argpp
- (tchar
**)(savnxf
+ 1);
i
= cbits(getch()) - '0';
if (i
> 0 && i
<= APERMAC
&& i
<= frame
->nargs
)
pushback(*(((tchar
**)(frame
+ 1)) + i
- 1));
if (skip() || (i
= getrq()) == 0) {
numtab
[DN
].val
= dip
->dnl
;
numtab
[DL
].val
= dip
->maxl
;
errprint("Diversions nested too deep");
k
[j
] = 0; /*not op and curd*/
dip
->dimac
= dip
->ditrap
= dip
->ditf
= 0;
dip
->ditrap
= vnumb((int *)0);
* if .tl is the first thing in the file, the p1
* doesn't come out, also the pagenumber will be 0
* tends too confuse the device filter (and the user as well)
if( dip
== d
&& numtab
[NL
].val
== -1)
if (ismot(delim
= getch())) {
while (cbits(i
= getch()) != '\n') {
if (cbits(i
) == cbits(delim
)) {
if (cbits(i
) == pagech
) {
setn1(numtab
[PN
].val
, numtab
[findr('%')].fmt
,
numtab
[HP
].val
+= width(i
);
if (tp
< &buf
[LNSIZE
-10])
horiz(j
= quant((lt
- w
[1]) / 2 - w
[0], HOR
));
horiz(lt
- w
[0] - w
[1] - w
[2] - j
);
if (numtab
[NL
].val
> dip
->hnl
)
dip
->hnl
= numtab
[NL
].val
;
int xx
, cnt
, tcnt
, kk
, tot
;
for (i
= 0; i
< NM
; i
++) {
if ((xx
= contab
[i
].rq
) == 0 || contab
[i
].mx
== 0)
j
= (filep
) contab
[i
].mx
;
while ((j
= blist
[blisti(j
)]) != (unsigned) ~0) {
if (!(*p
++ = (xx
>> BYTE
) & 0177))
fdprintf(stderr
, "%s %d\n", pmline
, k
);
fdprintf(stderr
, "pm: total %d, macros %d, space %d\n", tcnt
, cnt
, kk
);
stackdump() /* dumps stack of macros in process */
for (p
= frame
; p
!= stk
; p
= p
->pframe
)
fdprintf(stderr
, "%c%c ", p
->mname
&0177, (p
->mname
>>BYTE
)&0177);