📄 n3.c
字号:
/* * troff3.c * * macro and string routines, storage allocation */#include "tdef.h"#include "fns.h"#include "ext.h"Tchar *argtop;int pagech = '%';int strflg;#define MHASHSIZE 128 /* must be 2**n */#define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1)Contab *mhash[MHASHSIZE];Blockp *blist; /* allocated blocks for macros and strings */int nblist; /* how many there are */int bfree = -1; /* first (possible) free block in the list */Contab *contabp = NULL;#define MDELTA 500int nm = 0;int savname; /* name of macro/string being defined */int savslot; /* place in Contab of savname */int freeslot = -1; /* first (possible) free slot in contab */void prcontab(Contab *p){ int i; for (i = 0; i < nm; i++) if (p) if (p[i].rq != 0) fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq)); else fprintf(stderr, "slot %d empty\n", i); else fprintf(stderr, "slot %d empty\n", i);}void blockinit(void){ blist = (Blockp *) calloc(NBLIST, sizeof(Blockp)); if (blist == NULL) { ERROR "not enough room for %d blocks", NBLIST WARN; done2(1); } nblist = NBLIST; blist[0].nextoff = blist[1].nextoff = -1; blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); /* -1 prevents blist[0] from being used; temporary fix */ /* for a design botch: offset==0 is overloaded. */ /* blist[1] reserved for .rd indicator -- also unused. */ /* but someone unwittingly looks at these, so allocate something */ bfree = 2;}char *grow(char *ptr, int num, int size) /* make array bigger */{ char *p, new; if (ptr == NULL) p = (char *) calloc(num, size); else p = (char *) realloc(ptr, num * size); return p;}void mnspace(void){ nm = sizeof(contab)/sizeof(Contab) + MDELTA; freeslot = sizeof(contab)/sizeof(Contab) + 1; contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab)); if (contabp == NULL) { ERROR "not enough memory for namespace of %d marcos", nm WARN; exit(1); } contabp = (Contab *) memcpy((char *) contabp, (char *)contab, sizeof(contab)); if (contabp == NULL) { ERROR "Cannot reinitialize macro/request name list" WARN; exit(1); }}void caseig(void){ int i; Offset oldoff = offset; offset = 0; i = copyb(); offset = oldoff; if (i != '.') control(i, 1);}void casern(void){ int i, j, k; lgf++; skip(); if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0) return; skip(); clrmn(findmn(j = getrq())); if (j) { munhash(&contabp[oldmn]); contabp[oldmn].rq = j; maddhash(&contabp[oldmn]); if (dip != d ) for (k = dilev; k; k--) if (d[k].curd == i) d[k].curd = j; }}void maddhash(Contab *rp){ Contab **hp; if (rp->rq == 0) return; hp = &mhash[MHASH(rp->rq)]; rp->link = *hp; *hp = rp;}void munhash(Contab *mp){ Contab *p; Contab **lp; if (mp->rq == 0) return; lp = &mhash[MHASH(mp->rq)]; p = *lp; while (p) { if (p == mp) { *lp = p->link; p->link = 0; return; } lp = &p->link; p = p->link; }}void mrehash(void){ Contab *p; int i; for (i=0; i < MHASHSIZE; i++) mhash[i] = 0; for (p=contabp; p < &contabp[nm]; p++) p->link = 0; for (p=contabp; p < &contabp[nm]; p++) { if (p->rq == 0) continue; i = MHASH(p->rq); p->link = mhash[i]; mhash[i] = p; }}void caserm(void){ int j; int k = 0; lgf++;g0: while (!skip() && (j = getrq()) != 0) { if (dip != d) for (k = dilev; k; k--) if (d[k].curd == j) { ERROR "cannot remove diversion %s during definition", unpair(j) WARN; goto g0; } clrmn(findmn(j)); } lgf--;}void caseas(void){ app++; caseds();}void caseds(void){ ds++; casede();}void caseam(void){ app++; casede();}void casede(void){ int i, req; Offset savoff; req = '.'; lgf++; skip(); if ((i = getrq()) == 0) goto de1; if ((offset = finds(i)) == 0) goto de1; if (newmn) savslot = newmn; else savslot = findmn(i); savname = i; if (ds) copys(); else req = copyb(); clrmn(oldmn); if (newmn) { if (contabp[newmn].rq) munhash(&contabp[newmn]); contabp[newmn].rq = i; maddhash(&contabp[newmn]); } if (apptr) { savoff = offset; offset = apptr; wbf((Tchar) IMP); offset = savoff; } offset = dip->op; if (req != '.') control(req, 1);de1: ds = app = 0;}int findmn(int i){ Contab *p; for (p = mhash[MHASH(i)]; p; p = p->link) if (i == p->rq) return(p - contabp); return(-1);}void clrmn(int i){ if (i >= 0) { if (contabp[i].mx) ffree(contabp[i].mx); munhash(&contabp[i]); contabp[i].rq = 0; contabp[i].mx = 0; contabp[i].emx = 0; contabp[i].f = 0; if (contabp[i].divsiz != NULL) { free(contabp[i].divsiz); contabp[i].divsiz = NULL; } if (freeslot > i) freeslot = i; }}void growcontab(void){ nm += MDELTA; contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab)); if (contabp == NULL) { ERROR "Too many (%d) string/macro names", nm WARN; done2(02); } else { memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab), 0, MDELTA * sizeof(Contab)); mrehash(); }}Offset finds(int mn){ int i; Tchar j = IMP; Offset savip; oldmn = findmn(mn); newmn = 0; apptr = 0; if (app && oldmn >= 0 && contabp[oldmn].mx) { savip = ip; ip = contabp[oldmn].emx; oldmn = -1; apptr = ip; if (!diflg) ip = incoff(ip); nextb = ip; ip = savip; } else { for (i = freeslot; i < nm; i++) { if (contabp[i].rq == 0) break; } if (i == nm) growcontab(); freeslot = i + 1; if ((nextb = alloc()) == -1) { app = 0; if (macerr++ > 1) done2(02); if (nextb == 0) ERROR "Not enough space for string/macro names" WARN; edone(04); return(offset = 0); } contabp[i].mx = nextb; if (!diflg) { newmn = i; if (oldmn == -1) contabp[i].rq = -1; } else { contabp[i].rq = mn; maddhash(&contabp[i]); } } app = 0; return(offset = nextb);}int skip(void){ Tchar i; while (cbits(i = getch()) == ' ' || ismot(i)) ; ch = i; return(nlflg);}int copyb(void){ int i, j, state; Tchar ii; int req, k; Offset savoff; Uchar *p; if (skip() || !(j = getrq())) j = '.'; req = j; p = unpair(j); /* was: k = j >> BYTE; j &= BYTEMASK; */ j = p[0]; k = p[1]; copyf++; flushi(); nlflg = 0; state = 1;/* state 0 eat up * state 1 look for . * state 2 look for first char of end macro * state 3 look for second char of end macro */ while (1) { i = cbits(ii = getch()); if (state == 3) { if (i == k) break; if (!k) { ch = ii; i = getach(); ch = ii; if (!i) break; } state = 0; goto c0; } if (i == '\n') { state = 1; nlflg = 0; goto c0; } if (state == 1 && i == '.') { state++; savoff = offset; goto c0; } if (state == 2 && i == j) { state++; goto c0; } state = 0;c0: if (offset) wbf(ii); } if (offset) { offset = savoff; wbf((Tchar)0); } copyf--; return(req);}void copys(void){ Tchar i; copyf++; if (skip()) goto c0; if (cbits(i = getch()) != '"') wbf(i); while (cbits(i = getch()) != '\n') wbf(i);c0: wbf((Tchar)0); copyf--;}Offset alloc(void) /* return free Offset in nextb */{ int i, j; for (i = bfree; i < nblist; i++) if (blist[i].nextoff == 0) break; if (i == nblist) { blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp)); if (blist == NULL) { ERROR "can't grow blist for string/macro defns" WARN; done2(2); } nblist *= 2; for (j = i; j < nblist; j++) { blist[j].nextoff = 0; blist[j].bp = 0; } } blist[i].nextoff = -1; /* this block is the end */ bfree = i + 1; if (blist[i].bp == 0) blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); if (blist[i].bp == NULL) { ERROR "can't allocate memory for string/macro definitions" WARN; done2(2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -