4
* macro and string routines, storage allocation
15
#define MHASHSIZE 128 /* must be 2**n */
16
#define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1)
17
Contab *mhash[MHASHSIZE];
20
Blockp *blist; /* allocated blocks for macros and strings */
21
int nblist; /* how many there are */
22
int bfree = -1; /* first (possible) free block in the list */
24
Contab *contabp = NULL;
28
int savname; /* name of macro/string being defined */
29
int savslot; /* place in Contab of savname */
30
int freeslot = -1; /* first (possible) free slot in contab */
32
void prcontab(Contab *p)
35
for (i = 0; i < nm; i++)
38
fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq));
40
fprintf(stderr, "slot %d empty\n", i);
42
fprintf(stderr, "slot %d empty\n", i);
48
blist = (Blockp *) calloc(NBLIST, sizeof(Blockp));
50
ERROR "not enough room for %d blocks", NBLIST WARN;
54
blist[0].nextoff = blist[1].nextoff = -1;
55
blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
56
blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
57
/* -1 prevents blist[0] from being used; temporary fix */
58
/* for a design botch: offset==0 is overloaded. */
59
/* blist[1] reserved for .rd indicator -- also unused. */
60
/* but someone unwittingly looks at these, so allocate something */
65
char *grow(char *ptr, int num, int size) /* make array bigger */
70
p = (char *) calloc(num, size);
72
p = (char *) realloc(ptr, num * size);
78
nm = sizeof(contab)/sizeof(Contab) + MDELTA;
79
freeslot = sizeof(contab)/sizeof(Contab) + 1;
80
contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab));
81
if (contabp == NULL) {
82
ERROR "not enough memory for namespace of %d marcos", nm WARN;
85
contabp = (Contab *) memcpy((char *) contabp, (char *)contab,
87
if (contabp == NULL) {
88
ERROR "Cannot reinitialize macro/request name list" WARN;
97
Offset oldoff = offset;
113
if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0)
116
clrmn(findmn(j = getrq()));
118
munhash(&contabp[oldmn]);
119
contabp[oldmn].rq = j;
120
maddhash(&contabp[oldmn]);
122
for (k = dilev; k; k--)
128
void maddhash(Contab *rp)
134
hp = &mhash[MHASH(rp->rq)];
139
void munhash(Contab *mp)
146
lp = &mhash[MHASH(mp->rq)];
164
for (i=0; i < MHASHSIZE; i++)
166
for (p=contabp; p < &contabp[nm]; p++)
168
for (p=contabp; p < &contabp[nm]; p++) {
184
while (!skip() && (j = getrq()) != 0) {
186
for (k = dilev; k; k--)
187
if (d[k].curd == j) {
188
ERROR "cannot remove diversion %s during definition",
227
if ((i = getrq()) == 0)
229
if ((offset = finds(i)) == 0)
242
if (contabp[newmn].rq)
243
munhash(&contabp[newmn]);
244
contabp[newmn].rq = i;
245
maddhash(&contabp[newmn]);
266
for (p = mhash[MHASH(i)]; p; p = p->link)
277
ffree(contabp[i].mx);
278
munhash(&contabp[i]);
283
if (contabp[i].divsiz != NULL) {
284
free(contabp[i].divsiz);
285
contabp[i].divsiz = NULL;
292
void growcontab(void)
295
contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab));
296
if (contabp == NULL) {
297
ERROR "Too many (%d) string/macro names", nm WARN;
300
memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab),
301
0, MDELTA * sizeof(Contab));
315
if (app && oldmn >= 0 && contabp[oldmn].mx) {
317
ip = contabp[oldmn].emx;
325
for (i = freeslot; i < nm; i++) {
326
if (contabp[i].rq == 0)
332
if ((nextb = alloc()) == -1) {
337
ERROR "Not enough space for string/macro names" WARN;
341
contabp[i].mx = nextb;
348
maddhash(&contabp[i]);
352
return(offset = nextb);
359
while (cbits(i = getch()) == ' ' || ismot(i))
375
if (skip() || !(j = getrq()))
379
/* was: k = j >> BYTE; j &= BYTEMASK; */
389
* state 2 look for first char of end macro
390
* state 3 look for second char of end macro
394
i = cbits(ii = getch());
413
if (state == 1 && i == '.') {
418
if (state == 2 && i == j) {
443
if (cbits(i = getch()) != '"')
445
while (cbits(i = getch()) != '\n')
453
Offset alloc(void) /* return free Offset in nextb */
457
for (i = bfree; i < nblist; i++)
458
if (blist[i].nextoff == 0)
461
blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp));
463
ERROR "can't grow blist for string/macro defns" WARN;
467
for (j = i; j < nblist; j++) {
468
blist[j].nextoff = 0;
472
blist[i].nextoff = -1; /* this block is the end */
474
if (blist[i].bp == 0)
475
blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
476
if (blist[i].bp == NULL) {
477
ERROR "can't allocate memory for string/macro definitions" WARN;
480
nextb = (Offset) i * BLK;
485
void ffree(Offset i) /* free list of blocks starting at blist(o) */
486
{ /* (doesn't actually free the blocks, just the pointers) */
489
for ( ; blist[j = bindex(i)].nextoff != -1; ) {
492
i = blist[j].nextoff;
493
blist[j].nextoff = 0;
495
blist[j].nextoff = 0;
499
void wbf(Tchar i) /* store i into offset, get ready for next one */
507
contabp[savslot].emx = offset;
508
off = boffset(offset);
509
blist[j].bp[off++] = i;
511
if (pastend(offset)) { /* off the end of this block */
512
if (blist[j].nextoff == -1) {
513
if ((nextb = alloc()) == -1) {
514
ERROR "Out of temp file space" WARN;
517
blist[j].nextoff = nextb;
519
offset = blist[j].nextoff;
524
Tchar rbf(void) /* return next char from blist[] block */
528
if (ip == RD_OFFSET) { /* for rdtty */
546
Offset xxxincoff(Offset p) /* get next blist[] block */
549
if (pastend(p)) { /* off the end of this block */
550
if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */
551
ERROR "Bad storage allocation" WARN;
572
lastpbp = p->lastpbp;
577
* test that the end of the allocation is above a certain location
580
#define SPACETEST(base, size) \
581
if ((char*)base + size >= (char*)stk+STACKSIZE) \
582
ERROR "Stacksize overflow in n3" WARN
584
Offset pushi(Offset newip, int mname)
588
SPACETEST(nxf, sizeof(Stack));
594
p->lastpbp = lastpbp;
602
nxf = (Stack *)argtop;
611
if ((i = (char *) calloc(x, 1)) == 0) {
612
ERROR "Core limit reached" WARN;
623
if ((i = getach()) == 0)
637
if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) {
641
SPACETEST(nxf, sizeof(Stack));
645
return pushi(contabp[j].mx, i);
654
Tchar i, *strp, *lim, **argpp, **argppend;
666
memp = (char *)savnxf;
668
* 1 s structure for the macro descriptor
669
* APERMAC Tchar *'s for pointers into the strings
670
* space for the Tchar's themselves
672
memp += sizeof(Stack);
674
* CPERMAC = the total # of characters for ALL arguments
678
memp += APERMAC * sizeof(Tchar *);
679
memp += CPERMAC * sizeof(Tchar);
683
argpp = (Tchar **)(savnxf + 1);
684
argppend = &argpp[APERMAC];
685
SPACETEST(argppend, sizeof(Tchar *));
686
strp = (Tchar *)argppend;
688
* Zero out all the string pointers before filling them in.
690
for (j = 0; j < APERMAC; j++)
692
/* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
693
* savnxf, nxf, argpp, strp, lim WARN;
696
while (argpp != argppend && !skip()) {
699
if (cbits(i = getch()) == '"')
705
/* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
706
if (nlflg || (!quote && argpp != argppend && cbits(i) == ' '))
707
break; /* collects rest into $9 */
710
&& cbits(i = getch()) != '"') {
715
if (strflg && strp >= lim) {
716
/* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
717
ERROR "Macro argument too long" WARN;
721
SPACETEST(strp, 3 * sizeof(Tchar));
726
nxf->nargs = argpp - (Tchar **)(savnxf + 1);
737
i = cbits(getch()) - '0';
738
if (i > 0 && i <= APERMAC && i <= frame->nargs)
739
pushback(*(((Tchar **)(frame + 1)) + i - 1));
754
if ((i = getrq()) == 0)
756
if ((j = findmn(i)) >= 0) {
757
if (contabp[j].divsiz != NULL) {
758
numtabp[DN].val = contabp[j].divsiz->dix;
759
numtabp[DL].val = contabp[j].divsiz->diy;
764
#define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \
765
ERROR "lost diversion %s", unpair(dip->curd) WARN
772
if (skip() || (i = getrq()) == 0) {
778
numtabp[DN].val = dip->dnl;
779
numtabp[DL].val = dip->maxl;
781
if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) {
782
ERROR "Cannot alloc diversion size" WARN;
785
contabp[j].divsiz->dix = numtabp[DN].val;
786
contabp[j].divsiz->diy = numtabp[DL].val;
793
if (++dilev == NDI) {
795
ERROR "Diversions nested too deep" WARN;
808
k = (int *) & dip->dnl;
809
for (j = 0; j < 10; j++)
810
k[j] = 0; /*not op and curd*/
820
dip->dimac = dip->ditrap = dip->ditf = 0;
822
dip->ditrap = vnumb((int *)0);
826
dip->dimac = getrq();
841
* if .tl is the first thing in the file, the p1
842
* doesn't come out, also the pagenumber will be 0
844
* tends too confuse the device filter (and the user as well)
846
if (dip == d && numtabp[NL].val == -1)
850
if (ismot(delim = getch())) {
854
delim = cbits(delim);
857
w[0] = w[1] = w[2] = 0;
859
while (cbits(i = getch()) != '\n') {
860
if (cbits(i) == cbits(delim)) {
862
w[j] = numtabp[HP].val;
869
if (cbits(i) == pagech) {
870
setn1(numtabp[PN].val, numtabp[findr('%')].fmt,
874
numtabp[HP].val += width(i);
875
if (tp < &buf[LNSIZE-10]) {
876
if (cbits(i) == ' ' && *tp != WORDSP)
880
ERROR "Overflow in casetl" WARN;
885
w[j] = numtabp[HP].val;
895
horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
899
horiz(lt - w[0] - w[1] - w[2] - j);
905
if (dip->dnl > dip->hnl)
908
if (numtabp[NL].val > dip->hnl)
909
dip->hnl = numtabp[NL].val;
923
int xx, cnt, tcnt, kk, tot;
929
for (i = 0; i < nm; i++) {
930
if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0)
934
for (k = 1; (j = blist[bindex(j)].nextoff) != -1; )
939
fprintf(stderr, "%-2.2s %d\n", unpair(xx), k);
941
fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
944
void stackdump(void) /* dumps stack of macros in process */
949
fprintf(stderr, "stack: ");
950
for (p = frame; p != stk; p = p->pframe)
951
fprintf(stderr, "%s ", unpair(p->mname));
952
fprintf(stderr, "\n");