⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 n3.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -