plan 9 kernel history: overview | file list | diff list

1995/0804/port/print.c (diff list | history)

port/print.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
 
1992/1024    
enum 
{ 
	SIZE	= 1024, 
	IDIGIT	= 30, 
	MAXCONV	= 40, 
	FDIGIT	= 30, 
	FDEFLT	= 6, 
	NONE	= -1000, 
	MAXFMT	= 512, 
 
	FPLUS	= (1<<0), 
	FMINUS	= (1<<1), 
	FSHARP	= (1<<2), 
	FLONG	= (1<<3), 
	FSHORT	= (1<<4), 
	FUNSIGN	= (1<<5), 
	FVLONG	= (1<<6), 
}; 
 
1990/0227    
#define	PTR	sizeof(char*) 
#define	SHORT	sizeof(int) 
#define	INT	sizeof(int) 
#define	LONG	sizeof(long) 
1992/1024    
#define	VLONG	sizeof(vlong) 
1990/0227    
 
1992/1024    
int	printcol; 
1990/0227    
 
1992/1024    
static	int	convcount; 
static	char	fmtindex[MAXFMT]; 
1990/0227    
 
1992/1024    
static	int	noconv(void*, Fconv*); 
static	int	flags(void*, Fconv*); 
1990/0227    
 
1992/1024    
static	int	cconv(void*, Fconv*); 
static	int	sconv(void*, Fconv*); 
static	int	percent(void*, Fconv*); 
 
int	numbconv(void*, Fconv*); 
 
1990/0227    
static 
1992/1024    
int	(*fmtconv[MAXCONV])(void*, Fconv*) = 
1990/0227    
{ 
1992/1024    
	noconv 
1990/0227    
}; 
1992/1024    
 
1990/0227    
static 
1992/1024    
void 
initfmt(void) 
1990/0227    
{ 
1992/1024    
	int cc; 
1990/0227    
 
1992/1024    
	cc = 0; 
	fmtconv[cc] = noconv; 
	cc++; 
 
	fmtconv[cc] = flags; 
	fmtindex['+'] = cc; 
	fmtindex['-'] = cc; 
	fmtindex['#'] = cc; 
	fmtindex['h'] = cc; 
	fmtindex['l'] = cc; 
	fmtindex['u'] = cc; 
	cc++; 
 
	fmtconv[cc] = numbconv; 
	fmtindex['d'] = cc; 
	fmtindex['o'] = cc; 
	fmtindex['x'] = cc; 
	fmtindex['X'] = cc; 
	cc++; 
 
	fmtconv[cc] = cconv; 
	fmtindex['c'] = cc; 
	fmtindex['C'] = cc; 
	cc++; 
 
	fmtconv[cc] = sconv; 
	fmtindex['s'] = cc; 
	fmtindex['S'] = cc; 
	cc++; 
 
	fmtconv[cc] = percent; 
	fmtindex['%'] = cc; 
	cc++; 
 
	convcount = cc; 
} 
 
1990/0227    
int 
1992/1024    
fmtinstall(int c, int (*f)(void*, Fconv*)) 
1990/0227    
{ 
 
1992/1024    
	if(convcount == 0) 
		initfmt(); 
	if(c < 0 || c >= MAXFMT) 
		return 1; 
	if(convcount >= MAXCONV) 
		return 1; 
	fmtconv[convcount] = f; 
	fmtindex[c] = convcount; 
	convcount++; 
1990/0227    
	return 0; 
} 
 
char* 
1992/1024    
doprint(char *s, char *es, char *fmt, void *argp) 
1990/0227    
{ 
1992/1024    
	int n, c; 
	Rune rune; 
	Fconv local; 
1990/0227    
 
1992/1024    
	local.out = s; 
	local.eout = es-4;		/* room for multi-byte character and 0 */ 
1990/0227    
 
loop: 
1992/1024    
	c = *fmt & 0xff; 
	if(c >= Runeself) { 
		n = chartorune(&rune, fmt); 
		fmt += n; 
		c = rune; 
	} else 
		fmt++; 
	switch(c) { 
	case 0: 
		*local.out = 0; 
		return local.out; 
	 
	default: 
		printcol++; 
		goto common; 
 
	case '\n': 
		printcol = 0; 
		goto common; 
 
	case '\t': 
		printcol = (printcol+8) & ~7; 
		goto common; 
 
	common: 
		if(local.out < local.eout) 
			if(c >= Runeself) { 
				rune = c; 
				n = runetochar(local.out, &rune);	/* BUG */ 
				local.out += n; 
			} else 
				*local.out++ = c; 
1990/0227    
		goto loop; 
1992/1024    
 
	case '%': 
		break; 
1990/0227    
	} 
1992/1024    
	local.f1 = NONE; 
	local.f2 = NONE; 
	local.f3 = 0; 
 
	/* 
	 * read one of the following 
	 *	1. number, => f1, f2 in order. 
	 *	2. '*' same as number (from args) 
	 *	3. '.' ignored (separates numbers) 
	 *	4. flag => f3 
	 *	5. verb and terminate 
	 */ 
l0: 
	c = *fmt & 0xff; 
	if(c >= Runeself) { 
		n = chartorune(&rune, fmt); 
		fmt += n; 
		c = rune; 
	} else 
		fmt++; 
 
l1: 
	if(c == 0) { 
		fmt--; 
		goto loop; 
1990/0227    
	} 
1992/1024    
	if(c == '.') { 
		if(local.f1 == NONE) 
			local.f1 = 0; 
		local.f2 = 0; 
		goto l0; 
1990/0227    
	} 
1992/1024    
	if((c >= '1' && c <= '9') || 
	   (c == '0' && local.f1 != NONE)) {	/* '0' is a digit for f2 */ 
		n = 0; 
		while(c >= '0' && c <= '9') { 
			n = n*10 + c-'0'; 
			c = *fmt++; 
		} 
		if(local.f1 == NONE) 
			local.f1 = n; 
		else 
			local.f2 = n; 
1990/0227    
		goto l1; 
	} 
1992/1024    
	if(c == '*') { 
		n = *(int*)argp; 
		argp = (char*)argp + INT; 
		if(local.f1 == NONE) 
			local.f1 = n; 
		else 
			local.f2 = n; 
		goto l0; 
1990/0227    
	} 
1992/1024    
	n = 0; 
	if(c >= 0 && c < MAXFMT) 
		n = fmtindex[c]; 
	local.chr = c; 
	n = (*fmtconv[n])(argp, &local); 
	if(n < 0) { 
		local.f3 |= -n; 
		goto l0; 
	} 
	argp = (char*)argp + n; 
1990/0227    
	goto loop; 
} 
 
int 
1992/1024    
numbconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[IDIGIT]; 
	int i, f, n, r, b, ucase; 
1990/0227    
	short h; 
1992/1024    
	long v; 
	vlong vl; 
1990/0227    
 
1992/1024    
	SET(v); 
	SET(vl); 
 
	ucase = 0; 
	b = fp->chr; 
	switch(fp->chr) { 
	case 'u': 
		fp->f3 |= FUNSIGN; 
	case 'd': 
		b = 10; 
		break; 
 
	case 'o': 
		b = 8; 
		break; 
 
	case 'X': 
		ucase = 1; 
	case 'x': 
		b = 16; 
		break; 
	} 
 
1990/0227    
	f = 0; 
1992/1024    
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 
	case FVLONG|FLONG: 
		vl = *(vlong*)o; 
		r = VLONG; 
		break; 
 
1990/0227    
	case FLONG: 
1992/1024    
		v = *(long*)o; 
1990/0227    
		r = LONG; 
		break; 
 
	case FUNSIGN|FLONG: 
1992/1024    
		v = *(ulong*)o; 
1990/0227    
		r = LONG; 
		break; 
 
	case FSHORT: 
1992/1024    
		h = *(int*)o; 
1990/0227    
		v = h; 
		r = SHORT; 
		break; 
 
	case FUNSIGN|FSHORT: 
1992/1024    
		h = *(int*)o; 
		v = (ushort)h; 
1990/0227    
		r = SHORT; 
		break; 
 
	default: 
1992/1024    
		v = *(int*)o; 
1990/0227    
		r = INT; 
		break; 
 
	case FUNSIGN: 
1992/1024    
		v = *(unsigned*)o; 
1990/0227    
		r = INT; 
		break; 
	} 
1992/1024    
	if(!(fp->f3 & FUNSIGN) && v < 0) { 
1990/0227    
		v = -v; 
		f = 1; 
	} 
1992/1024    
	s[IDIGIT-1] = 0; 
1990/0227    
	for(i = IDIGIT-2;; i--) { 
1992/1024    
		if(fp->f3 & FVLONG) 
			n = vl % b; 
		else 
			n = (ulong)v % b; 
1990/0227    
		n += '0'; 
1992/1024    
		if(n > '9') { 
1990/0227    
			n += 'a' - ('9'+1); 
1992/1024    
			if(ucase) 
				n += 'A'-'a'; 
		} 
		s[i] = n; 
1990/0227    
		if(i < 2) 
			break; 
1992/1024    
		if(fp->f3 & FVLONG) 
			vl = vl / b; 
		else 
			v = (ulong)v / b; 
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2) 
1990/0227    
			continue; 
1992/1024    
		if(fp->f3 & FVLONG) 
			if(vl <= 0) 
				break; 
1990/0227    
		if(v <= 0) 
			break; 
	} 
1992/1024    
	if(fp->f3 & FSHARP) 
	if(s[i] != '0') { 
		if(b == 8) 
			s[--i] = '0'; 
		else 
		if(b == 16) { 
			if(ucase) 
				s[--i] = 'X'; 
			else 
				s[--i] = 'x'; 
			s[--i] = '0'; 
		} 
	} 
1990/0227    
	if(f) 
1992/1024    
		s[--i] = '-'; 
	fp->f2 = NONE; 
	strconv(s+i, fp); 
1990/0227    
	return r; 
} 
 
void 
1992/1024    
Strconv(Rune *s, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n, c, i; 
	Rune rune; 
1990/0227    
 
1992/1024    
	if(fp->f3 & FMINUS) 
		fp->f1 = -fp->f1; 
	n = 0; 
	if(fp->f1 != NONE && fp->f1 >= 0) { 
		for(; s[n]; n++) 
			; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
			printcol++; 
1990/0227    
			n++; 
		} 
1992/1024    
	} 
	for(;;) { 
		c = *s++; 
		if(c == 0) 
			break; 
		n++; 
		if(fp->f2 == NONE || fp->f2 > 0) { 
			if(fp->out < fp->eout) 
				if(c >= Runeself) { 
					rune = c; 
					i = runetochar(fp->out, &rune); 
					fp->out += i; 
				} else 
					*fp->out++ = c; 
			if(fp->f2 != NONE) 
				fp->f2--; 
			switch(c) { 
			default: 
				printcol++; 
				break; 
			case '\n': 
				printcol = 0; 
				break; 
			case '\t': 
				printcol = (printcol+8) & ~7; 
				break; 
			} 
1990/0227    
		} 
1992/1024    
	} 
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
			printcol++; 
1990/0227    
			n++; 
		} 
	} 
} 
 
1992/1024    
void 
strconv(char *s, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n, c, i; 
	Rune rune; 
1990/0227    
 
1992/1024    
	if(fp->f3 & FMINUS) 
		fp->f1 = -fp->f1; 
	n = 0; 
	if(fp->f1 != NONE && fp->f1 >= 0) { 
		n = utflen(s); 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
			printcol++; 
			n++; 
		} 
	} 
	for(;;) { 
		c = *s & 0xff; 
		if(c >= Runeself) { 
			i = chartorune(&rune, s); 
			s += i; 
			c = rune; 
		} else 
			s++; 
		if(c == 0) 
			break; 
		n++; 
		if(fp->f2 == NONE || fp->f2 > 0) { 
			if(fp->out < fp->eout) 
				if(c >= Runeself) { 
					rune = c; 
					i = runetochar(fp->out, &rune); 
					fp->out += i; 
				} else 
					*fp->out++ = c; 
			if(fp->f2 != NONE) 
				fp->f2--; 
			switch(c) { 
			default: 
				printcol++; 
				break; 
			case '\n': 
				printcol = 0; 
				break; 
			case '\t': 
				printcol = (printcol+8) & ~7; 
				break; 
			} 
		} 
	} 
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
			printcol++; 
			n++; 
		} 
	} 
1990/0227    
} 
 
1992/1024    
static 
int 
noconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n; 
	char s[10]; 
1990/0227    
 
1992/1024    
	if(convcount == 0) { 
		initfmt(); 
		n = 0; 
		if(fp->chr >= 0 && fp->chr < MAXFMT) 
			n = fmtindex[fp->chr]; 
		return (*fmtconv[n])(o, fp); 
	} 
	sprint(s, "*%c*", fp->chr); 
	fp->f1 = 0; 
	fp->f2 = NONE; 
	fp->f3 = 0; 
	strconv(s, fp); 
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
cconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
	Rune rune; 
1990/0227    
 
1992/1024    
	rune = *(int*)o; 
	if(fp->chr == 'c') 
		rune &= 0xff; 
	s[runetochar(s, &rune)] = 0; 
1990/0227    
 
1992/1024    
	fp->f2 = NONE; 
	strconv(s, fp); 
	return INT; 
1990/0227    
} 
 
1992/1024    
static 
int 
sconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char *s; 
	Rune *r; 
1990/0227    
 
1992/1024    
	if(fp->chr == 's') { 
		s = *(char**)o; 
		if(s == 0) 
			s = "<null>"; 
		strconv(s, fp); 
	} else { 
		r = *(Rune**)o; 
		if(r == 0) 
			r = L"<null>"; 
		Strconv(r, fp); 
	} 
	return PTR; 
1990/0227    
} 
 
1992/1024    
static 
int 
1995/0804    
percent(void*, Fconv *fp) 
1990/0227    
{ 
 
1992/1024    
	if(fp->out < fp->eout) 
		*fp->out++ = '%'; 
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1995/0804    
flags(void*, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int f; 
1990/0227    
 
1992/1024    
	f = 0; 
	switch(fp->chr) { 
	case '+': 
		f = FPLUS; 
		break; 
1991/1115    
 
1992/1024    
	case '-': 
		f = FMINUS; 
		break; 
1990/0227    
 
1992/1024    
	case '#': 
		f = FSHARP; 
		break; 
1990/0227    
 
1992/1024    
	case 'h': 
		f = FSHORT; 
		break; 
1990/0227    
 
1992/1024    
	case 'l': 
		f = FLONG; 
		if(fp->f3 & FLONG) 
			f = FVLONG; 
		break; 
1990/0227    
 
1992/1024    
	case 'u': 
		f = FUNSIGN; 
		break; 
	} 
	return -f; 
1990/0227    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)