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

📄 n4.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * troff4.c * * number registers, conversion, arithmetic */#include "tdef.h"#include "fns.h"#include "ext.h"int	regcnt = NNAMES;int	falsef	= 0;	/* on if inside false branch of if */#define	NHASHSIZE	128	/* must be 2**n */#define	NHASH(i)	((i>>6)^i) & (NHASHSIZE-1)Numtab	*nhash[NHASHSIZE];Numtab *numtabp = NULL;#define NDELTA 400int ncnt = 0;void setn(void){	int i, j, f;	Tchar ii;	Uchar *p;	char buf[NTM];		/* for \n(.S */	f = nform = 0;	if ((i = cbits(ii = getach())) == '+')		f = 1;	else if (i == '-')		f = -1;	else if (ii)	/* don't put it back if it's already back (thanks to jaap) */		ch = ii;	if (falsef)		f = 0;	if ((i = getsn()) == 0)		return;	p = unpair(i);	if (p[0] == '.')		switch (p[1]) {		case 's':			i = pts;			break;		case 'v':			i = lss;			break;		case 'f':			i = font;			break;		case 'p':			i = pl;			break;		case 't':			i = findt1();			break;		case 'o':			i = po;			break;		case 'l':			i = ll;			break;		case 'i':			i = in;			break;		case '$':			i = frame->nargs;			break;		case 'A':			i = ascii;			break;		case 'c':			i = numtabp[CD].val;			break;		case 'n':			i = lastl;			break;		case 'a':			i = ralss;			break;		case 'h':			i = dip->hnl;			break;		case 'd':			if (dip != d)				i = dip->dnl;			else				i = numtabp[NL].val;			break;		case 'u':			i = fi;			break;		case 'j':			i = ad + 2 * admod;			break;		case 'w':			i = widthp;			break;		case 'x':			i = nel;			break;		case 'y':			i = un;			break;		case 'T':			i = dotT;			break;	 /* -Tterm used in nroff */		case 'V':			i = VERT;			break;		case 'H':			i = HOR;			break;		case 'k':			i = ne;			break;		case 'P':			i = print;			break;		case 'L':			i = ls;			break;		case 'R':	/* maximal # of regs that can be addressed */			i = 255*256 - regcnt; 			break;		case 'z':			p = unpair(dip->curd);			*pbp++ = p[1];	/* watch order */			*pbp++ = p[0];			return;		case 'b':			i = bdtab[font];			break;		case 'F':			cpushback(cfname[ifi]);			return; 		case 'S': 			buf[0] = j = 0;	 			for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { 				if (i > 0) 					buf[j++] = ' '; 				sprintf(&buf[j], "%d", tabtab[i] & TABMASK); 				j = strlen(buf); 				if ( tabtab[i] & RTAB) 					sprintf(&buf[j], "uR"); 				else if (tabtab[i] & CTAB) 					sprintf(&buf[j], "uC"); 				else 					sprintf(&buf[j], "uL"); 				j += 2; 			} 			cpushback(buf); 			return;		default:			goto s0;		}	else {s0:		if ((j = findr(i)) == -1)			i = 0;		else {			i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f;			nform = numtabp[j].fmt;		}	}	setn1(i, nform, (Tchar) 0);}Tchar	numbuf[25];Tchar	*numbufp;int wrc(Tchar i){	if (numbufp >= &numbuf[24])		return(0);	*numbufp++ = i;	return(1);}/* insert into input number i, in format form, with size-font bits bits */void setn1(int i, int form, Tchar bits){	numbufp = numbuf;	nrbits = bits;	nform = form;	fnumb(i, wrc);	*numbufp = 0;	pushback(numbuf);}void prnumtab(Numtab *p){	int i;	for (i = 0; i < ncnt; i++)		if (p)			if (p[i].r != 0)				fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val);			else				fprintf(stderr, "slot %d empty\n", i);		else			fprintf(stderr, "slot %d empty\n", i);}void nnspace(void){	ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA;	numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab));	if (numtabp == NULL) {		ERROR "not enough memory for registers (%d)", ncnt WARN;		exit(1);	}	numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab,							sizeof(numtab));	if (numtabp == NULL) {		ERROR "Cannot initialize registers" WARN;		exit(1);	}}void grownumtab(void){	ncnt += NDELTA;	numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab));	if (numtabp == NULL) {		ERROR "Too many number registers (%d)", ncnt WARN;		done2(04);	} else {		memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab),						0, NDELTA * sizeof(Numtab));		nrehash();	}}void nrehash(void){	Numtab *p;	int i;	for (i=0; i<NHASHSIZE; i++)		nhash[i] = 0;	for (p=numtabp; p < &numtabp[ncnt]; p++)		p->link = 0;	for (p=numtabp; p < &numtabp[ncnt]; p++) {		if (p->r == 0)			continue;		i = NHASH(p->r);		p->link = nhash[i];		nhash[i] = p;	}}void nunhash(Numtab *rp){	Numtab *p;	Numtab **lp;	if (rp->r == 0)		return;	lp = &nhash[NHASH(rp->r)];	p = *lp;	while (p) {		if (p == rp) {			*lp = p->link;			p->link = 0;			return;		}		lp = &p->link;		p = p->link;	}}int findr(int i){	Numtab *p;	int h = NHASH(i);	if (i == 0)		return(-1);a0:	for (p = nhash[h]; p; p = p->link)		if (i == p->r)			return(p - numtabp);	for (p = numtabp; p < &numtabp[ncnt]; p++) {		if (p->r == 0) {			p->r = i;			p->link = nhash[h];			nhash[h] = p;			regcnt++;			return(p - numtabp);		}	}	grownumtab();	goto a0;}int usedr(int i)	/* returns -1 if nr i has never been used */{	Numtab *p;	if (i == 0)		return(-1);	for (p = nhash[NHASH(i)]; p; p = p->link)		if (i == p->r)			return(p - numtabp);	return -1;}int fnumb(int i, int (*f)(Tchar)){	int j;	j = 0;	if (i < 0) {		j = (*f)('-' | nrbits);		i = -i;	}	switch (nform) {	default:	case '1':	case 0:		return decml(i, f) + j;	case 'i':	case 'I':		return roman(i, f) + j;	case 'a':	case 'A':		return abc(i, f) + j;	}}int decml(int i, int (*f)(Tchar)){	int j, k;	k = 0;	nform--;	if ((j = i / 10) || (nform > 0))		k = decml(j, f);	return(k + (*f)((i % 10 + '0') | nrbits));}int roman(int i, int (*f)(Tchar)){	if (!i)		return((*f)('0' | nrbits));	if (nform == 'i')		return(roman0(i, f, "ixcmz", "vldw"));	else		return(roman0(i, f, "IXCMZ", "VLDW"));}int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp){	int q, rem, k;	if (!i)		return(0);	k = roman0(i / 10, f, onesp + 1, fivesp + 1);	q = (i = i % 10) / 5;	rem = i % 5;	if (rem == 4) {		k += (*f)(*onesp | nrbits);		if (q)			i = *(onesp + 1);		else			i = *fivesp;		return(k += (*f)(i | nrbits));	}	if (q)		k += (*f)(*fivesp | nrbits);	while (--rem >= 0)		k += (*f)(*onesp | nrbits);	return(k);}int abc(int i, int (*f)(Tchar)){	if (!i)		return((*f)('0' | nrbits));	else		return(abc0(i - 1, f));}int abc0(int i, int (*f)(Tchar)){	int j, k;	k = 0;	if (j = i / 26)		k = abc0(j - 1, f);	return(k + (*f)((i % 26 + nform) | nrbits));}long atoi0(void){	int c, k, cnt;	Tchar ii;	long i, acc;	acc = 0;	nonumb = 0;	cnt = -1;a0:	cnt++;	ii = getch();	c = cbits(ii);	switch (c) {	default:		ch = ii;		if (cnt)			break;	case '+':		i = ckph();		if (nonumb)			break;		acc += i;		goto a0;	case '-':		i = ckph();		if (nonumb)			break;		acc -= i;		goto a0;	case '*':		i = ckph();		if (nonumb)			break;		acc *= i;		goto a0;	case '/':		i = ckph();		if (nonumb)			break;		if (i == 0) {			flusho();			ERROR "divide by zero." WARN;			acc = 0;		} else			acc /= i;		goto a0;	case '%':		i = ckph();		if (nonumb)			break;		acc %= i;		goto a0;	case '&':	/*and*/		i = ckph();		if (nonumb)			break;		if ((acc > 0) && (i > 0))			acc = 1;		else			acc = 0;		goto a0;	case ':':	/*or*/		i = ckph();		if (nonumb)			break;		if ((acc > 0) || (i > 0))			acc = 1;		else			acc = 0;		goto a0;	case '=':		if (cbits(ii = getch()) != '=')			ch = ii;		i = ckph();		if (nonumb) {			acc = 0;			break;		}		if (i == acc)			acc = 1;		else			acc = 0;		goto a0;	case '>':		k = 0;		if (cbits(ii = getch()) == '=')			k++;		else			ch = ii;		i = ckph();		if (nonumb) {			acc = 0;			break;		}		if (acc > (i - k))			acc = 1;		else			acc = 0;		goto a0;	case '<':		k = 0;		if (cbits(ii = getch()) == '=')			k++;		else			ch = ii;		i = ckph();		if (nonumb) {			acc = 0;			break;		}		if (acc < (i + k))			acc = 1;		else			acc = 0;		goto a0;	case ')':		break;	case '(':		acc = atoi0();		goto a0;	}	return(acc);}long ckph(void){	Tchar i;	long j;	if (cbits(i = getch()) == '(')		j = atoi0();	else {		j = atoi1(i);	}	return(j);}/* * print error about illegal numeric argument; */void prnumerr(void){	char err_buf[40];	static char warn[] = "Numeric argument expected";	int savcd = numtabp[CD].val;	if (numerr.type == RQERR)		sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc),						unpair(numerr.req), warn);	else		sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg,									warn);	if (frame != stk)	/* uncertainty correction */		numtabp[CD].val--;	ERROR err_buf WARN;	numtabp[CD].val = savcd;}long atoi1(Tchar ii){	int i, j, digits;	double acc;	/* this is the only double in troff! */	int neg, abs, field, decpnt;	extern int ifnum;	neg = abs = field = decpnt = digits = 0;	acc = 0;	for (;;) {		i = cbits(ii);		switch (i) {		default:			break;		case '+':			ii = getch();			continue;		case '-':			neg = 1;			ii = getch();			continue;		case '|':			abs = 1 + neg;			neg = 0;			ii = getch();			continue;		}		break;	}a1:	while (i >= '0' && i <= '9') {		field++;		digits++;		acc = 10 * acc + i - '0';		ii = getch();		i = cbits(ii);	}	if (i == '.' && !decpnt++) {		field++;		digits = 0;		ii = getch();		i = cbits(ii);		goto a1;	}	if (!field) {		ch = ii;		goto a2;	}	switch (i) {	case 'u':		i = j = 1;	/* should this be related to HOR?? */		break;	case 'v':	/*VSs - vert spacing*/		j = lss;		i = 1;		break;	case 'm':	/*Ems*/		j = EM;		i = 1;		break;	case 'n':	/*Ens*/		j = EM;		if (TROFF)			i = 2;		else			i = 1;	/*Same as Ems in NROFF*/		break;	case 'p':	/*Points*/		j = INCH;		i = 72;		break;	case 'i':	/*Inches*/		j = INCH;		i = 1;		break;	case 'c':	/*Centimeters*/		/* if INCH is too big, this will overflow */		j = INCH * 50;		i = 127;		break;	case 'P':	/*Picas*/		j = INCH;		i = 6;		break;	default:		j = dfact;		ch = ii;		i = dfactd;	}	if (neg)		acc = -acc;	if (!noscale) {		acc = (acc * j) / i;	}	if (field != digits && digits > 0)		while (digits--)			acc /= 10;	if (abs) {		if (dip != d)			j = dip->dnl;		else			j = numtabp[NL].val;		if (!vflag) {			j = numtabp[HP].val;		}		if (abs == 2)			j = -j;		acc -= j;	}a2:	nonumb = (!field || field == decpnt);	if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) {		if (cbits(ii) != RIGHT ) /* Too painful to do right */			prnumerr();	}	return(acc);}void caserr(void){	int i, j;	Numtab *p;	lgf++;	while (!skip() && (i = getrq()) ) {		j = usedr(i);		if (j < 0)			continue;		p = &numtabp[j];		nunhash(p);		p->r = p->val = p->inc = p->fmt = 0;		regcnt--;	}}/* * .nr request; if tracing, don't check optional * 2nd argument because tbl generates .in 1.5n */void casenr(void){	int i, j;	int savtr = trace;	lgf++;	skip();	if ((i = findr(getrq())) == -1)		goto rtn;	skip();	j = inumb(&numtabp[i].val);	if (nonumb)		goto rtn;	numtabp[i].val = j;	skip();	trace = 0;	j = atoi0();		/* BUG??? */	trace = savtr;	if (nonumb)		goto rtn;	numtabp[i].inc = j;rtn:	return;}void caseaf(void){	int i, k;	Tchar j;	lgf++;	if (skip() || !(i = getrq()) || skip())		return;	k = 0;	j = getch();	if (!isalpha(cbits(j))) {		ch = j;		while ((j = cbits(getch())) >= '0' &&  j <= '9')			k++;	}	if (!k)		k = j;	numtabp[findr(i)].fmt = k;	/* was k & BYTEMASK */}void setaf(void)	/* return format of number register */{	int i, j;	i = usedr(getsn());	if (i == -1)		return;	if (numtabp[i].fmt > 20)	/* it was probably a, A, i or I */		*pbp++ = numtabp[i].fmt;	else		for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--)			*pbp++ = '0';}int vnumb(int *i){	vflag++;	dfact = lss;	res = VERT;	return(inumb(i));}int hnumb(int *i){	dfact = EM;	res = HOR;	return(inumb(i));}int inumb(int *n){	int i, j, f;	Tchar ii;	f = 0;	if (n) {		if ((j = cbits(ii = getch())) == '+')			f = 1;		else if (j == '-')			f = -1;		else			ch = ii;	}	i = atoi0();	if (n && f)		i = *n + f * i;	i = quant(i, res);	vflag = 0;	res = dfactd = dfact = 1;	if (nonumb)		i = 0;	return(i);}int quant(int n, int m){	int i, neg;	neg = 0;	if (n < 0) {		neg++;		n = -n;	}	/* better as i = ((n + m/2)/m)*m */	i = n / m;	if (n - m * i > m / 2)		i += 1;	i *= m;	if (neg)		i = -i;	return(i);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -