837 lines · 12.4 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * 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()) == '=')

Lines 1–500 of 837.