123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 |
- /*
- * 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 500
- int 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);
- }
- nextb = (Offset) i * BLK;
- return nextb;
- }
- void ffree(Offset i) /* free list of blocks starting at blist(o) */
- { /* (doesn't actually free the blocks, just the pointers) */
- int j;
- for ( ; blist[j = bindex(i)].nextoff != -1; ) {
- if (bfree > j)
- bfree = j;
- i = blist[j].nextoff;
- blist[j].nextoff = 0;
- }
- blist[j].nextoff = 0;
- }
- void wbf(Tchar i) /* store i into offset, get ready for next one */
- {
- int j, off;
- if (!offset)
- return;
- j = bindex(offset);
- if (i == 0)
- contabp[savslot].emx = offset;
- off = boffset(offset);
- blist[j].bp[off++] = i;
- offset++;
- if (pastend(offset)) { /* off the end of this block */
- if (blist[j].nextoff == -1) {
- if ((nextb = alloc()) == -1) {
- ERROR "Out of temp file space" WARN;
- done2(01);
- }
- blist[j].nextoff = nextb;
- }
- offset = blist[j].nextoff;
- }
- }
- Tchar rbf(void) /* return next char from blist[] block */
- {
- Tchar i, j;
- if (ip == RD_OFFSET) { /* for rdtty */
- if (j = rdtty())
- return(j);
- else
- return(popi());
- }
-
- i = rbf0(ip);
- if (i == 0) {
- if (!app)
- i = popi();
- return(i);
- }
- ip = incoff(ip);
- return(i);
- }
- Offset xxxincoff(Offset p) /* get next blist[] block */
- {
- p++;
- if (pastend(p)) { /* off the end of this block */
- if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */
- ERROR "Bad storage allocation" WARN;
- done2(-5);
- }
- }
- return(p);
- }
- Tchar popi(void)
- {
- Stack *p;
- if (frame == stk)
- return(0);
- if (strflg)
- strflg--;
- p = nxf = frame;
- p->nargs = 0;
- frame = p->pframe;
- ip = p->pip;
- pendt = p->ppendt;
- lastpbp = p->lastpbp;
- return(p->pch);
- }
- /*
- * test that the end of the allocation is above a certain location
- * in memory
- */
- #define SPACETEST(base, size) \
- if ((char*)base + size >= (char*)stk+STACKSIZE) \
- ERROR "Stacksize overflow in n3" WARN
- Offset pushi(Offset newip, int mname)
- {
- Stack *p;
- SPACETEST(nxf, sizeof(Stack));
- p = nxf;
- p->pframe = frame;
- p->pip = ip;
- p->ppendt = pendt;
- p->pch = ch;
- p->lastpbp = lastpbp;
- p->mname = mname;
- lastpbp = pbp;
- pendt = ch = 0;
- frame = nxf;
- if (nxf->nargs == 0)
- nxf += 1;
- else
- nxf = (Stack *)argtop;
- return(ip = newip);
- }
- void *setbrk(int x)
- {
- char *i;
- if ((i = (char *) calloc(x, 1)) == 0) {
- ERROR "Core limit reached" WARN;
- edone(0100);
- }
- return(i);
- }
- int getsn(void)
- {
- int i;
- if ((i = getach()) == 0)
- return(0);
- if (i == '(')
- return(getrq());
- else
- return(i);
- }
- Offset setstr(void)
- {
- int i, j;
- lgf++;
- if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) {
- lgf--;
- return(0);
- } else {
- SPACETEST(nxf, sizeof(Stack));
- nxf->nargs = 0;
- strflg++;
- lgf--;
- return pushi(contabp[j].mx, i);
- }
- }
- void collect(void)
- {
- int j;
- Tchar i, *strp, *lim, **argpp, **argppend;
- int quote;
- Stack *savnxf;
- copyf++;
- nxf->nargs = 0;
- savnxf = nxf;
- if (skip())
- goto rtn;
- {
- char *memp;
- memp = (char *)savnxf;
- /*
- * 1 s structure for the macro descriptor
- * APERMAC Tchar *'s for pointers into the strings
- * space for the Tchar's themselves
- */
- memp += sizeof(Stack);
- /*
- * CPERMAC = the total # of characters for ALL arguments
- */
- #define CPERMAC 200
- #define APERMAC 9
- memp += APERMAC * sizeof(Tchar *);
- memp += CPERMAC * sizeof(Tchar);
- nxf = (Stack *)memp;
- }
- lim = (Tchar *)nxf;
- 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++)
- argpp[j] = 0;
- /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
- * savnxf, nxf, argpp, strp, lim WARN;
- */
- strflg = 0;
- while (argpp != argppend && !skip()) {
- *argpp++ = strp;
- quote = 0;
- if (cbits(i = getch()) == '"')
- quote++;
- else
- ch = i;
- while (1) {
- i = getch();
- /* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
- if (nlflg || (!quote && argpp != argppend && cbits(i) == ' '))
- break; /* collects rest into $9 */
- if ( quote
- && cbits(i) == '"'
- && cbits(i = getch()) != '"') {
- ch = i;
- break;
- }
- *strp++ = i;
- if (strflg && strp >= lim) {
- /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
- ERROR "Macro argument too long" WARN;
- copyf--;
- edone(004);
- }
- SPACETEST(strp, 3 * sizeof(Tchar));
- }
- *strp++ = 0;
- }
- nxf = savnxf;
- nxf->nargs = argpp - (Tchar **)(savnxf + 1);
- argtop = strp;
- rtn:
- copyf--;
- }
- void seta(void)
- {
- int i;
- i = cbits(getch()) - '0';
- if (i > 0 && i <= APERMAC && i <= frame->nargs)
- pushback(*(((Tchar **)(frame + 1)) + i - 1));
- }
- void caseda(void)
- {
- app++;
- casedi();
- }
- void casegd(void)
- {
- int i, j;
- skip();
- if ((i = getrq()) == 0)
- return;
- if ((j = findmn(i)) >= 0) {
- if (contabp[j].divsiz != NULL) {
- numtabp[DN].val = contabp[j].divsiz->dix;
- numtabp[DL].val = contabp[j].divsiz->diy;
- }
- }
- }
- #define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \
- ERROR "lost diversion %s", unpair(dip->curd) WARN
- void casedi(void)
- {
- int i, j, *k;
- lgf++;
- if (skip() || (i = getrq()) == 0) {
- if (dip != d) {
- FINDDIV(savslot);
- wbf((Tchar)0);
- }
- if (dilev > 0) {
- numtabp[DN].val = dip->dnl;
- numtabp[DL].val = dip->maxl;
- FINDDIV(j);
- if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) {
- ERROR "Cannot alloc diversion size" WARN;
- done2(1);
- } else {
- contabp[j].divsiz->dix = numtabp[DN].val;
- contabp[j].divsiz->diy = numtabp[DL].val;
- }
- dip = &d[--dilev];
- offset = dip->op;
- }
- goto rtn;
- }
- if (++dilev == NDI) {
- --dilev;
- ERROR "Diversions nested too deep" WARN;
- edone(02);
- }
- if (dip != d) {
- FINDDIV(j);
- savslot = j;
- wbf((Tchar)0);
- }
- diflg++;
- dip = &d[dilev];
- dip->op = finds(i);
- dip->curd = i;
- clrmn(oldmn);
- k = (int *) & dip->dnl;
- for (j = 0; j < 10; j++)
- k[j] = 0; /*not op and curd*/
- rtn:
- app = 0;
- diflg = 0;
- }
- void casedt(void)
- {
- lgf++;
- dip->dimac = dip->ditrap = dip->ditf = 0;
- skip();
- dip->ditrap = vnumb((int *)0);
- if (nonumb)
- return;
- skip();
- dip->dimac = getrq();
- }
- #define LNSIZE 4000
- void casetl(void)
- {
- int j;
- int w[3];
- Tchar buf[LNSIZE];
- Tchar *tp;
- Tchar i, delim;
- /*
- * bug fix
- *
- * 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 && numtabp[NL].val == -1)
- newline(1);
- dip->nls = 0;
- skip();
- if (ismot(delim = getch())) {
- ch = delim;
- delim = '\'';
- } else
- delim = cbits(delim);
- tp = buf;
- numtabp[HP].val = 0;
- w[0] = w[1] = w[2] = 0;
- j = 0;
- while (cbits(i = getch()) != '\n') {
- if (cbits(i) == cbits(delim)) {
- if (j < 3)
- w[j] = numtabp[HP].val;
- numtabp[HP].val = 0;
- if (w[j] != 0)
- *tp++ = WORDSP;
- j++;
- *tp++ = 0;
- } else {
- if (cbits(i) == pagech) {
- setn1(numtabp[PN].val, numtabp[findr('%')].fmt,
- i&SFMASK);
- continue;
- }
- numtabp[HP].val += width(i);
- if (tp < &buf[LNSIZE-10]) {
- if (cbits(i) == ' ' && *tp != WORDSP)
- *tp++ = WORDSP;
- *tp++ = i;
- } else {
- ERROR "Overflow in casetl" WARN;
- }
- }
- }
- if (j<3)
- w[j] = numtabp[HP].val;
- *tp++ = 0;
- *tp++ = 0;
- *tp = 0;
- tp = buf;
- if (NROFF)
- horiz(po);
- while (i = *tp++)
- pchar(i);
- if (w[1] || w[2])
- horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
- while (i = *tp++)
- pchar(i);
- if (w[2]) {
- horiz(lt - w[0] - w[1] - w[2] - j);
- while (i = *tp++)
- pchar(i);
- }
- newline(0);
- if (dip != d) {
- if (dip->dnl > dip->hnl)
- dip->hnl = dip->dnl;
- } else {
- if (numtabp[NL].val > dip->hnl)
- dip->hnl = numtabp[NL].val;
- }
- }
- void casepc(void)
- {
- pagech = chget(IMP);
- }
- void casepm(void)
- {
- int i, k;
- int xx, cnt, tcnt, kk, tot;
- Offset j;
- kk = cnt = tcnt = 0;
- tot = !skip();
- stackdump();
- for (i = 0; i < nm; i++) {
- if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0)
- continue;
- tcnt++;
- j = contabp[i].mx;
- for (k = 1; (j = blist[bindex(j)].nextoff) != -1; )
- k++;
- cnt++;
- kk += k;
- if (!tot)
- fprintf(stderr, "%-2.2s %d\n", unpair(xx), k);
- }
- fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
- }
- void stackdump(void) /* dumps stack of macros in process */
- {
- Stack *p;
- if (frame != stk) {
- fprintf(stderr, "stack: ");
- for (p = frame; p != stk; p = p->pframe)
- fprintf(stderr, "%s ", unpair(p->mname));
- fprintf(stderr, "\n");
- }
- }
|