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));
316 if (app && oldmn >= 0 && contabp[oldmn].mx) {
318 ip = contabp[oldmn].emx;
326 for (i = freeslot; i < nm; i++) {
327 if (contabp[i].rq == 0)
333 if ((nextb = alloc()) == -1) {
338 ERROR "Not enough space for string/macro names" WARN;
342 contabp[i].mx = nextb;
349 maddhash(&contabp[i]);
353 return(offset = nextb);
360 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");