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 */
68 return calloc(num
, size
);
70 return realloc(ptr
, num
* size
);
75 nm
= sizeof(contab
)/sizeof(Contab
) + MDELTA
;
76 freeslot
= sizeof(contab
)/sizeof(Contab
) + 1;
77 contabp
= (Contab
*) grow((char *) contabp
, nm
, sizeof(Contab
));
78 if (contabp
== NULL
) {
79 ERROR
"not enough memory for namespace of %d marcos", nm WARN
;
82 contabp
= (Contab
*) memcpy((char *) contabp
, (char *)contab
,
84 if (contabp
== NULL
) {
85 ERROR
"Cannot reinitialize macro/request name list" WARN
;
94 Offset oldoff
= offset
;
110 if ((i
= getrq()) == 0 || (oldmn
= findmn(i
)) < 0)
113 clrmn(findmn(j
= getrq()));
115 munhash(&contabp
[oldmn
]);
116 contabp
[oldmn
].rq
= j
;
117 maddhash(&contabp
[oldmn
]);
119 for (k
= dilev
; k
; k
--)
125 void maddhash(Contab
*rp
)
131 hp
= &mhash
[MHASH(rp
->rq
)];
136 void munhash(Contab
*mp
)
143 lp
= &mhash
[MHASH(mp
->rq
)];
161 for (i
=0; i
< MHASHSIZE
; i
++)
163 for (p
=contabp
; p
< &contabp
[nm
]; p
++)
165 for (p
=contabp
; p
< &contabp
[nm
]; p
++) {
181 while (!skip() && (j
= getrq()) != 0) {
183 for (k
= dilev
; k
; k
--)
184 if (d
[k
].curd
== j
) {
185 ERROR
"cannot remove diversion %s during definition",
224 if ((i
= getrq()) == 0)
226 if ((offset
= finds(i
)) == 0)
239 if (contabp
[newmn
].rq
)
240 munhash(&contabp
[newmn
]);
241 contabp
[newmn
].rq
= i
;
242 maddhash(&contabp
[newmn
]);
263 for (p
= mhash
[MHASH(i
)]; p
; p
= p
->link
)
274 ffree(contabp
[i
].mx
);
275 munhash(&contabp
[i
]);
280 if (contabp
[i
].divsiz
!= NULL
) {
281 free(contabp
[i
].divsiz
);
282 contabp
[i
].divsiz
= NULL
;
289 void growcontab(void)
292 contabp
= (Contab
*) grow((char *) contabp
, nm
, sizeof(Contab
));
293 if (contabp
== NULL
) {
294 ERROR
"Too many (%d) string/macro names", nm WARN
;
297 memset((char *)(contabp
) + (nm
- MDELTA
) * sizeof(Contab
),
298 0, MDELTA
* sizeof(Contab
));
312 if (app
&& oldmn
>= 0 && contabp
[oldmn
].mx
) {
314 ip
= contabp
[oldmn
].emx
;
322 for (i
= freeslot
; i
< nm
; i
++) {
323 if (contabp
[i
].rq
== 0)
329 if ((nextb
= alloc()) == -1) {
334 ERROR
"Not enough space for string/macro names" WARN
;
338 contabp
[i
].mx
= nextb
;
345 maddhash(&contabp
[i
]);
349 return(offset
= nextb
);
356 while (cbits(i
= getch()) == ' ' || ismot(i
))
371 if (skip() || !(j
= getrq()))
375 /* was: k = j >> BYTE; j &= BYTEMASK; */
385 * state 2 look for first char of end macro
386 * state 3 look for second char of end macro
390 i
= cbits(ii
= getch());
409 if (state
== 1 && i
== '.') {
414 if (state
== 2 && i
== j
) {
439 if (cbits(i
= getch()) != '"')
441 while (cbits(i
= getch()) != '\n')
449 Offset
alloc(void) /* return free Offset in nextb */
453 for (i
= bfree
; i
< nblist
; i
++)
454 if (blist
[i
].nextoff
== 0)
457 blist
= (Blockp
*) realloc((char *) blist
, 2 * nblist
* sizeof(Blockp
));
459 ERROR
"can't grow blist for string/macro defns" WARN
;
463 for (j
= i
; j
< nblist
; j
++) {
464 blist
[j
].nextoff
= 0;
468 blist
[i
].nextoff
= -1; /* this block is the end */
470 if (blist
[i
].bp
== 0)
471 blist
[i
].bp
= (Tchar
*) calloc(BLK
, sizeof(Tchar
));
472 if (blist
[i
].bp
== NULL
) {
473 ERROR
"can't allocate memory for string/macro definitions" WARN
;
476 nextb
= (Offset
) i
* BLK
;
481 void ffree(Offset i
) /* free list of blocks starting at blist(o) */
482 { /* (doesn't actually free the blocks, just the pointers) */
485 for ( ; blist
[j
= bindex(i
)].nextoff
!= -1; ) {
488 i
= blist
[j
].nextoff
;
489 blist
[j
].nextoff
= 0;
491 blist
[j
].nextoff
= 0;
495 void wbf(Tchar i
) /* store i into offset, get ready for next one */
503 contabp
[savslot
].emx
= offset
;
504 off
= boffset(offset
);
505 blist
[j
].bp
[off
++] = i
;
507 if (pastend(offset
)) { /* off the end of this block */
508 if (blist
[j
].nextoff
== -1) {
509 if ((nextb
= alloc()) == -1) {
510 ERROR
"Out of temp file space" WARN
;
513 blist
[j
].nextoff
= nextb
;
515 offset
= blist
[j
].nextoff
;
520 Tchar
rbf(void) /* return next char from blist[] block */
524 if (ip
== RD_OFFSET
) { /* for rdtty */
542 Offset
xxxincoff(Offset p
) /* get next blist[] block */
545 if (pastend(p
)) { /* off the end of this block */
546 if ((p
= blist
[bindex(p
-1)].nextoff
) == -1) { /* and nothing was allocated after it */
547 ERROR
"Bad storage allocation" WARN
;
568 lastpbp
= p
->lastpbp
;
573 * test that the end of the allocation is above a certain location
576 #define SPACETEST(base, size) \
577 if ((char*)base + size >= (char*)stk+STACKSIZE) \
578 ERROR "Stacksize overflow in n3" WARN
580 Offset
pushi(Offset newip
, int mname
)
584 SPACETEST(nxf
, sizeof(Stack
));
590 p
->lastpbp
= lastpbp
;
598 nxf
= (Stack
*)argtop
;
607 if ((i
= (char *) calloc(x
, 1)) == 0) {
608 ERROR
"Core limit reached" WARN
;
619 if ((i
= getach()) == 0)
633 if ((i
= getsn()) == 0 || (j
= findmn(i
)) == -1 || !contabp
[j
].mx
) {
637 SPACETEST(nxf
, sizeof(Stack
));
641 return pushi(contabp
[j
].mx
, i
);
650 Tchar i
, *strp
, *lim
, **argpp
, **argppend
;
662 memp
= (char *)savnxf
;
664 * 1 s structure for the macro descriptor
665 * APERMAC Tchar *'s for pointers into the strings
666 * space for the Tchar's themselves
668 memp
+= sizeof(Stack
);
670 * CPERMAC = the total # of characters for ALL arguments
674 memp
+= APERMAC
* sizeof(Tchar
*);
675 memp
+= CPERMAC
* sizeof(Tchar
);
679 argpp
= (Tchar
**)(savnxf
+ 1);
680 argppend
= &argpp
[APERMAC
];
681 SPACETEST(argppend
, sizeof(Tchar
*));
682 strp
= (Tchar
*)argppend
;
684 * Zero out all the string pointers before filling them in.
686 for (j
= 0; j
< APERMAC
; j
++)
688 /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
689 * savnxf, nxf, argpp, strp, lim WARN;
692 while (argpp
!= argppend
&& !skip()) {
695 if (cbits(i
= getch()) == '"')
701 /* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
702 if (nlflg
|| (!quote
&& argpp
!= argppend
&& cbits(i
) == ' '))
703 break; /* collects rest into $9 */
706 && cbits(i
= getch()) != '"') {
711 if (strflg
&& strp
>= lim
) {
712 /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
713 ERROR
"Macro argument too long" WARN
;
717 SPACETEST(strp
, 3 * sizeof(Tchar
));
722 nxf
->nargs
= argpp
- (Tchar
**)(savnxf
+ 1);
733 i
= cbits(getch()) - '0';
734 if (i
> 0 && i
<= APERMAC
&& i
<= frame
->nargs
)
735 pushback(*(((Tchar
**)(frame
+ 1)) + i
- 1));
750 if ((i
= getrq()) == 0)
752 if ((j
= findmn(i
)) >= 0) {
753 if (contabp
[j
].divsiz
!= NULL
) {
754 numtabp
[DN
].val
= contabp
[j
].divsiz
->dix
;
755 numtabp
[DL
].val
= contabp
[j
].divsiz
->diy
;
760 #define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \
761 ERROR "lost diversion %s", unpair(dip->curd) WARN
768 if (skip() || (i
= getrq()) == 0) {
774 numtabp
[DN
].val
= dip
->dnl
;
775 numtabp
[DL
].val
= dip
->maxl
;
777 if ((contabp
[j
].divsiz
= (Divsiz
*) malloc(sizeof(Divsiz
))) == NULL
) {
778 ERROR
"Cannot alloc diversion size" WARN
;
781 contabp
[j
].divsiz
->dix
= numtabp
[DN
].val
;
782 contabp
[j
].divsiz
->diy
= numtabp
[DL
].val
;
789 if (++dilev
== NDI
) {
791 ERROR
"Diversions nested too deep" WARN
;
804 k
= (int *) & dip
->dnl
;
805 for (j
= 0; j
< 10; j
++)
806 k
[j
] = 0; /*not op and curd*/
816 dip
->dimac
= dip
->ditrap
= dip
->ditf
= 0;
818 dip
->ditrap
= vnumb((int *)0);
822 dip
->dimac
= getrq();
837 * if .tl is the first thing in the file, the p1
838 * doesn't come out, also the pagenumber will be 0
840 * tends too confuse the device filter (and the user as well)
842 if (dip
== d
&& numtabp
[NL
].val
== -1)
846 if (ismot(delim
= getch())) {
850 delim
= cbits(delim
);
853 w
[0] = w
[1] = w
[2] = 0;
855 while (cbits(i
= getch()) != '\n') {
856 if (cbits(i
) == cbits(delim
)) {
858 w
[j
] = numtabp
[HP
].val
;
865 if (cbits(i
) == pagech
) {
866 setn1(numtabp
[PN
].val
, numtabp
[findr('%')].fmt
,
870 numtabp
[HP
].val
+= width(i
);
871 if (tp
< &buf
[LNSIZE
-10]) {
872 if (cbits(i
) == ' ' && *tp
!= WORDSP
)
876 ERROR
"Overflow in casetl" WARN
;
881 w
[j
] = numtabp
[HP
].val
;
891 horiz(j
= quant((lt
- w
[1]) / 2 - w
[0], HOR
));
895 horiz(lt
- w
[0] - w
[1] - w
[2] - j
);
901 if (dip
->dnl
> dip
->hnl
)
904 if (numtabp
[NL
].val
> dip
->hnl
)
905 dip
->hnl
= numtabp
[NL
].val
;
919 int xx
, cnt
, tcnt
, kk
, tot
;
925 for (i
= 0; i
< nm
; i
++) {
926 if ((xx
= contabp
[i
].rq
) == 0 || contabp
[i
].mx
== 0)
930 for (k
= 1; (j
= blist
[bindex(j
)].nextoff
) != -1; )
935 fprintf(stderr
, "%-2.2s %d\n", unpair(xx
), k
);
937 fprintf(stderr
, "pm: total %d, macros %d, space %d\n", tcnt
, cnt
, kk
);
940 void stackdump(void) /* dumps stack of macros in process */
945 fprintf(stderr
, "stack: ");
946 for (p
= frame
; p
!= stk
; p
= p
->pframe
)
947 fprintf(stderr
, "%s ", unpair(p
->mname
));
948 fprintf(stderr
, "\n");