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

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

1990/0227/sys/src/9/port/print.c:60,661990/06111/sys/src/9/port/print.c:60,66 (short | long)
1990/0227    
} 
 
char* 
donprint(char *p, char *ep, char *fmt, void *argp) 
1990/06111    
doprint(char *p, char *ep, char *fmt, void *argp) 
1990/0227    
{ 
	int sf1, c; 
	Op o; 
1990/06111/sys/src/9/port/print.c:240,2451991/1115/sys/src/9/port/print.c:240,247 (short | long)
Silence compiler warnings.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
static	int 
hconv(Op *op) 
{ 
1991/1115    
 
	USED(op); 
1990/0227    
	return -FSHORT; 
} 
 
1990/06111/sys/src/9/port/print.c:247,2521991/1115/sys/src/9/port/print.c:249,255
1990/0227    
lconv(Op *op) 
{ 
 
1991/1115    
	USED(op); 
1990/0227    
	return -FLONG; 
} 
 
1990/06111/sys/src/9/port/print.c:268,2731991/1115/sys/src/9/port/print.c:271,278
1990/0227    
static	int 
uconv(Op *op) 
{ 
1991/1115    
 
	USED(op); 
1990/0227    
	return -FUNSIGN; 
} 
 
1991/1115/sys/src/9/port/print.c:1,51992/0321/sys/src/9/port/print.c:1,5 (short | long)
Move lib.h to port.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
 
#define	PTR	sizeof(char*) 
#define	SHORT	sizeof(int) 
1992/0321/sys/src/9/port/print.c:1,2921992/1024/sys/src/9/port/print.c:1,574 (short | long)
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) 
#define	IDIGIT	30 
#define	MAXCON	30 
1992/1024    
#define	VLONG	sizeof(vlong) 
1990/0227    
 
static	int	convcount  = { 10 }; 
1992/1024    
int	printcol; 
1990/0227    
 
#define	PUT(o, c)	if((o)->p < (o)->ep) *(o)->p++ = c 
1992/1024    
static	int	convcount; 
static	char	fmtindex[MAXFMT]; 
1990/0227    
 
static	int	noconv(Op*); 
static	int	cconv(Op*); 
static	int	dconv(Op*); 
static	int	hconv(Op*); 
static	int	lconv(Op*); 
static	int	oconv(Op*); 
static	int	sconv(Op*); 
static	int	uconv(Op*); 
static	int	xconv(Op*); 
static	int	percent(Op*); 
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 
int	(*fmtconv[MAXCON])(Op*) = 
1992/1024    
int	(*fmtconv[MAXCONV])(void*, Fconv*) = 
1990/0227    
{ 
	noconv, 
	cconv, dconv, hconv, lconv, 
	oconv, sconv, uconv, xconv, 
	percent, 
1992/1024    
	noconv 
1990/0227    
}; 
1992/1024    
 
1990/0227    
static 
char	fmtindex[128] = 
1992/1024    
void 
initfmt(void) 
1990/0227    
{ 
	['c'] 1, 
	['d'] 2, 
	['h'] 3, 
	['l'] 4, 
	['o'] 5, 
	['s'] 6, 
	['u'] 7, 
	['x'] 8, 
	['%'] 9, 
}; 
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 
fmtinstall(char c, int (*f)(Op*)) 
1992/1024    
fmtinstall(int c, int (*f)(void*, Fconv*)) 
1990/0227    
{ 
 
	c &= 0177; 
	if(fmtindex[c] == 0) { 
		if(convcount >= MAXCON) 
			return 1; 
		fmtindex[c] = convcount++; 
	} 
	fmtconv[fmtindex[c]] = f; 
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* 
1990/06111    
doprint(char *p, char *ep, char *fmt, void *argp) 
1992/1024    
doprint(char *s, char *es, char *fmt, void *argp) 
1990/0227    
{ 
	int sf1, c; 
	Op o; 
1992/1024    
	int n, c; 
	Rune rune; 
	Fconv local; 
1990/0227    
 
	o.p = p; 
	o.ep = ep; 
	o.argp = argp; 
1992/1024    
	local.out = s; 
	local.eout = es-4;		/* room for multi-byte character and 0 */ 
1990/0227    
 
loop: 
	c = *fmt++; 
	if(c != '%') { 
		if(c == 0) { 
			if(o.p < o.ep) 
				*o.p = 0; 
			return o.p; 
		} 
		PUT(&o, c); 
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    
	} 
	o.f1 = 0; 
	o.f2 = -1; 
	o.f3 = 0; 
	c = *fmt++; 
	sf1 = 0; 
	if(c == '-') { 
		sf1 = 1; 
		c = *fmt++; 
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    
	} 
	while(c >= '0' && c <= '9') { 
		o.f1 = o.f1*10 + c-'0'; 
		c = *fmt++; 
1992/1024    
	if(c == '.') { 
		if(local.f1 == NONE) 
			local.f1 = 0; 
		local.f2 = 0; 
		goto l0; 
1990/0227    
	} 
	if(sf1) 
		o.f1 = -o.f1; 
	if(c != '.') 
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; 
	c = *fmt++; 
	while(c >= '0' && c <= '9') { 
		if(o.f2 < 0) 
			o.f2 = 0; 
		o.f2 = o.f2*10 + c-'0'; 
		c = *fmt++; 
	} 
l1: 
	if(c == 0) 
		fmt--; 
	c = (*fmtconv[fmtindex[c&0177]])(&o); 
	if(c < 0) { 
		o.f3 |= -c; 
		c = *fmt++; 
		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    
	} 
	o.argp = (char*)o.argp + c; 
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 
numbconv(Op *op, int base) 
1992/1024    
numbconv(void *o, Fconv *fp) 
1990/0227    
{ 
	char b[IDIGIT]; 
	int i, f, n, r; 
	long v; 
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; 
	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) { 
1992/1024    
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 
	case FVLONG|FLONG: 
		vl = *(vlong*)o; 
		r = VLONG; 
		break; 
 
1990/0227    
	case FLONG: 
		v = *(long*)op->argp; 
1992/1024    
		v = *(long*)o; 
1990/0227    
		r = LONG; 
		break; 
 
	case FUNSIGN|FLONG: 
		v = *(unsigned long*)op->argp; 
1992/1024    
		v = *(ulong*)o; 
1990/0227    
		r = LONG; 
		break; 
 
	case FSHORT: 
		h = *(int*)op->argp; 
1992/1024    
		h = *(int*)o; 
1990/0227    
		v = h; 
		r = SHORT; 
		break; 
 
	case FUNSIGN|FSHORT: 
		h = *(int*)op->argp; 
		v = (unsigned short)h; 
1992/1024    
		h = *(int*)o; 
		v = (ushort)h; 
1990/0227    
		r = SHORT; 
		break; 
 
	default: 
		v = *(int*)op->argp; 
1992/1024    
		v = *(int*)o; 
1990/0227    
		r = INT; 
		break; 
 
	case FUNSIGN: 
		v = *(unsigned*)op->argp; 
1992/1024    
		v = *(unsigned*)o; 
1990/0227    
		r = INT; 
		break; 
	} 
	if(!(op->f3 & FUNSIGN) && v < 0) { 
1992/1024    
	if(!(fp->f3 & FUNSIGN) && v < 0) { 
1990/0227    
		v = -v; 
		f = 1; 
	} 
	b[IDIGIT-1] = 0; 
1992/1024    
	s[IDIGIT-1] = 0; 
1990/0227    
	for(i = IDIGIT-2;; i--) { 
		n = (unsigned long)v % base; 
1992/1024    
		if(fp->f3 & FVLONG) 
			n = vl % b; 
		else 
			n = (ulong)v % b; 
1990/0227    
		n += '0'; 
		if(n > '9') 
1992/1024    
		if(n > '9') { 
1990/0227    
			n += 'a' - ('9'+1); 
		b[i] = n; 
1992/1024    
			if(ucase) 
				n += 'A'-'a'; 
		} 
		s[i] = n; 
1990/0227    
		if(i < 2) 
			break; 
		v = (unsigned long)v / base; 
		if(op->f2 >= 0 && i >= IDIGIT-op->f2) 
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; 
	} 
sout: 
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) 
		b[--i] = '-'; 
	strconv(b+i, op, op->f1, -1); 
1992/1024    
		s[--i] = '-'; 
	fp->f2 = NONE; 
	strconv(s+i, fp); 
1990/0227    
	return r; 
} 
 
void 
strconv(char *o, Op *op, int f1, int f2) 
1992/1024    
Strconv(Rune *s, Fconv *fp) 
1990/0227    
{ 
	int n, c; 
	char *p; 
1992/1024    
	int n, c, i; 
	Rune rune; 
1990/0227    
 
	n = strlen(o); 
	if(f1 >= 0) 
		while(n < f1) { 
			PUT(op, ' '); 
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++; 
		} 
	for(p=o; c = *p++;) 
		if(f2 != 0) { 
			PUT(op, c); 
			f2--; 
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    
		} 
	if(f1 < 0) { 
		f1 = -f1; 
		while(n < f1) { 
			PUT(op, ' '); 
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++; 
		} 
	} 
} 
 
static	int 
noconv(Op *op) 
1992/1024    
void 
strconv(char *s, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n, c, i; 
	Rune rune; 
1990/0227    
 
	strconv("***", op, 0, -1); 
	return 0; 
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    
} 
 
static	int 
cconv(Op *op) 
1992/1024    
static 
int 
noconv(void *o, Fconv *fp) 
1990/0227    
{ 
	char b[2]; 
1992/1024    
	int n; 
	char s[10]; 
1990/0227    
 
	b[0] = *(int*)op->argp; 
	b[1] = 0; 
	strconv(b, op, op->f1, -1); 
	return INT; 
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    
} 
 
static	int 
dconv(Op *op) 
1992/1024    
static 
int 
cconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
	Rune rune; 
1990/0227    
 
	return numbconv(op, 10); 
} 
1992/1024    
	rune = *(int*)o; 
	if(fp->chr == 'c') 
		rune &= 0xff; 
	s[runetochar(s, &rune)] = 0; 
1990/0227    
 
static	int 
hconv(Op *op) 
{ 
1991/1115    
                 
	USED(op); 
1990/0227    
	return -FSHORT; 
1992/1024    
	fp->f2 = NONE; 
	strconv(s, fp); 
	return INT; 
1990/0227    
} 
 
static	int 
lconv(Op *op) 
1992/1024    
static 
int 
sconv(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char *s; 
	Rune *r; 
1990/0227    
 
1991/1115    
	USED(op); 
1990/0227    
	return -FLONG; 
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    
} 
 
static	int 
oconv(Op *op) 
1992/1024    
static 
int 
percent(void *o, Fconv *fp) 
1990/0227    
{ 
 
	return numbconv(op, 8); 
1992/1024    
	USED(o); 
	if(fp->out < fp->eout) 
		*fp->out++ = '%'; 
	return 0; 
1990/0227    
} 
 
static	int 
sconv(Op *op) 
1992/1024    
static 
int 
flags(void *o, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int f; 
1990/0227    
 
	strconv(*(char**)op->argp, op, op->f1, op->f2); 
	return PTR; 
} 
1992/1024    
	USED(o); 
1990/0227    
 
static	int 
uconv(Op *op) 
{ 
1992/1024    
	f = 0; 
	switch(fp->chr) { 
	case '+': 
		f = FPLUS; 
		break; 
1991/1115    
 
	USED(op); 
1990/0227    
	return -FUNSIGN; 
} 
1992/1024    
	case '-': 
		f = FMINUS; 
		break; 
1990/0227    
 
static	int 
xconv(Op *op) 
{ 
1992/1024    
	case '#': 
		f = FSHARP; 
		break; 
1990/0227    
 
	return numbconv(op, 16); 
} 
1992/1024    
	case 'h': 
		f = FSHORT; 
		break; 
1990/0227    
 
static	int 
percent(Op *op) 
{ 
1992/1024    
	case 'l': 
		f = FLONG; 
		if(fp->f3 & FLONG) 
			f = FVLONG; 
		break; 
1990/0227    
 
	PUT(op, '%'); 
	return 0; 
1992/1024    
	case 'u': 
		f = FUNSIGN; 
		break; 
	} 
	return -f; 
1990/0227    
} 
1992/1024/sys/src/9/port/print.c:525,5341995/0804/sys/src/9/port/print.c:525,533 (short | long)
Anonymize.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
 
1992/1024    
static 
int 
percent(void *o, Fconv *fp) 
1995/0804    
percent(void*, Fconv *fp) 
1990/0227    
{ 
 
1992/1024    
	USED(o); 
	if(fp->out < fp->eout) 
		*fp->out++ = '%'; 
	return 0; 
1992/1024/sys/src/9/port/print.c:536,5461995/0804/sys/src/9/port/print.c:535,543
1990/0227    
 
1992/1024    
static 
int 
flags(void *o, Fconv *fp) 
1995/0804    
flags(void*, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int f; 
1990/0227    
                 
1992/1024    
	USED(o); 
1990/0227    
 
1992/1024    
	f = 0; 
	switch(fp->chr) { 
1995/0804/sys/src/9/port/print.c:11,471996/0214/sys/src/9/port/print.c:11,41 (short | long)
Convert to use va_arg. Format edits. Silence compiler warnings.
rsc Fri Mar 4 12:44:25 2005
1992/1024    
	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), 
1996/0214    
	FPLUS	= 1<<0, 
	FMINUS	= 1<<1, 
	FSHARP	= 1<<2, 
	FLONG	= 1<<3, 
	FSHORT	= 1<<4, 
	FUNSIGN	= 1<<5, 
	FVLONG	= 1<<6, 
1992/1024    
}; 
 
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*); 
1996/0214    
static	int	noconv(va_list*, Fconv*); 
static	int	flags(va_list*, Fconv*); 
1990/0227    
 
1992/1024    
static	int	cconv(void*, Fconv*); 
static	int	sconv(void*, Fconv*); 
static	int	percent(void*, Fconv*); 
1996/0214    
static	int	cconv(va_list*, Fconv*); 
static	int	sconv(va_list*, Fconv*); 
static	int	percent(va_list*, Fconv*); 
1992/1024    
 
int	numbconv(void*, Fconv*); 
1996/0214    
int	numbconv(va_list*, Fconv*); 
1992/1024    
 
1990/0227    
static 
1992/1024    
int	(*fmtconv[MAXCONV])(void*, Fconv*) = 
1996/0214    
int	(*fmtconv[MAXCONV])(va_list*, Fconv*) = 
1990/0227    
{ 
1992/1024    
	noconv 
1990/0227    
}; 
1995/0804/sys/src/9/port/print.c:90,1041996/0214/sys/src/9/port/print.c:84,98
1992/1024    
} 
 
1990/0227    
int 
1992/1024    
fmtinstall(int c, int (*f)(void*, Fconv*)) 
1996/0214    
fmtinstall(int c, int (*f)(va_list*, Fconv*)) 
1990/0227    
{ 
 
1992/1024    
	if(convcount == 0) 
		initfmt(); 
	if(c < 0 || c >= MAXFMT) 
		return 1; 
1996/0214    
		return -1; 
1992/1024    
	if(convcount >= MAXCONV) 
		return 1; 
1996/0214    
		return -1; 
1992/1024    
	fmtconv[convcount] = f; 
	fmtindex[c] = convcount; 
	convcount++; 
1995/0804/sys/src/9/port/print.c:106,1121996/0214/sys/src/9/port/print.c:100,106
1990/0227    
} 
 
char* 
1992/1024    
doprint(char *s, char *es, char *fmt, void *argp) 
1996/0214    
doprint(char *s, char *es, char *fmt, va_list argp) 
1990/0227    
{ 
1992/1024    
	int n, c; 
	Rune rune; 
1995/0804/sys/src/9/port/print.c:113,1191996/0214/sys/src/9/port/print.c:107,113
1992/1024    
	Fconv local; 
1990/0227    
 
1992/1024    
	local.out = s; 
	local.eout = es-4;		/* room for multi-byte character and 0 */ 
1996/0214    
	local.eout = es-UTFmax-1; 
1990/0227    
 
loop: 
1992/1024    
	c = *fmt & 0xff; 
1995/0804/sys/src/9/port/print.c:144,1501996/0214/sys/src/9/port/print.c:138,144
1992/1024    
		if(local.out < local.eout) 
			if(c >= Runeself) { 
				rune = c; 
				n = runetochar(local.out, &rune);	/* BUG */ 
1996/0214    
				n = runetochar(local.out, &rune); 
1992/1024    
				local.out += n; 
			} else 
				*local.out++ = c; 
1995/0804/sys/src/9/port/print.c:199,2061996/0214/sys/src/9/port/print.c:193,199
1990/0227    
		goto l1; 
	} 
1992/1024    
	if(c == '*') { 
		n = *(int*)argp; 
		argp = (char*)argp + INT; 
1996/0214    
		n = va_arg(argp, int); 
1992/1024    
		if(local.f1 == NONE) 
			local.f1 = n; 
		else 
1995/0804/sys/src/9/port/print.c:211,2371996/0214/sys/src/9/port/print.c:204,225
1992/1024    
	if(c >= 0 && c < MAXFMT) 
		n = fmtindex[c]; 
	local.chr = c; 
	n = (*fmtconv[n])(argp, &local); 
1996/0214    
	n = (*fmtconv[n])(&argp, &local); 
1992/1024    
	if(n < 0) { 
		local.f3 |= -n; 
		goto l0; 
	} 
	argp = (char*)argp + n; 
1990/0227    
	goto loop; 
} 
 
int 
1992/1024    
numbconv(void *o, Fconv *fp) 
1996/0214    
numbconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[IDIGIT]; 
	int i, f, n, r, b, ucase; 
1996/0214    
	int i, f, n, 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) { 
1995/0804/sys/src/9/port/print.c:253,2941996/0214/sys/src/9/port/print.c:241,271
1992/1024    
	} 
 
1990/0227    
	f = 0; 
1992/1024    
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 
	case FVLONG|FLONG: 
		vl = *(vlong*)o; 
		r = VLONG; 
		break; 
                 
1996/0214    
	switch(fp->f3 & (FLONG|FSHORT|FUNSIGN)) { 
1990/0227    
	case FLONG: 
1992/1024    
		v = *(long*)o; 
1990/0227    
		r = LONG; 
1996/0214    
		v = va_arg(*arg, long); 
1990/0227    
		break; 
 
	case FUNSIGN|FLONG: 
1992/1024    
		v = *(ulong*)o; 
1990/0227    
		r = LONG; 
1996/0214    
		v = va_arg(*arg, ulong); 
1990/0227    
		break; 
 
	case FSHORT: 
1992/1024    
		h = *(int*)o; 
1996/0214    
		h = va_arg(*arg, int); 
1990/0227    
		v = h; 
		r = SHORT; 
		break; 
 
	case FUNSIGN|FSHORT: 
1992/1024    
		h = *(int*)o; 
1996/0214    
		h = va_arg(*arg, int); 
1992/1024    
		v = (ushort)h; 
1990/0227    
		r = SHORT; 
		break; 
 
	default: 
1992/1024    
		v = *(int*)o; 
1990/0227    
		r = INT; 
1996/0214    
		v = va_arg(*arg, int); 
1990/0227    
		break; 
 
	case FUNSIGN: 
1992/1024    
		v = *(unsigned*)o; 
1990/0227    
		r = INT; 
1996/0214    
		v = va_arg(*arg, unsigned); 
1990/0227    
		break; 
	} 
1992/1024    
	if(!(fp->f3 & FUNSIGN) && v < 0) { 
1995/0804/sys/src/9/port/print.c:297,3061996/0214/sys/src/9/port/print.c:274,280
1990/0227    
	} 
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; 
1996/0214    
		n = (ulong)v % b; 
1990/0227    
		n += '0'; 
1992/1024    
		if(n > '9') { 
1990/0227    
			n += 'a' - ('9'+1); 
1995/0804/sys/src/9/port/print.c:310,3321996/0214/sys/src/9/port/print.c:284,299
1992/1024    
		s[i] = n; 
1990/0227    
		if(i < 2) 
			break; 
1992/1024    
		if(fp->f3 & FVLONG) 
			vl = vl / b; 
		else 
			v = (ulong)v / b; 
1996/0214    
		v = (ulong)v / b; 
1992/1024    
		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) 
1996/0214    
 
	if(fp->f3 & FSHARP) { 
		if(b == 8 && s[i] != '0') 
1992/1024    
			s[--i] = '0'; 
		else 
		if(b == 16) { 
			if(ucase) 
				s[--i] = 'X'; 
1995/0804/sys/src/9/port/print.c:339,3451996/0214/sys/src/9/port/print.c:306,312
1992/1024    
		s[--i] = '-'; 
	fp->f2 = NONE; 
	strconv(s+i, fp); 
1990/0227    
	return r; 
1996/0214    
	return 0; 
1990/0227    
} 
 
void 
1995/0804/sys/src/9/port/print.c:465,4711996/0214/sys/src/9/port/print.c:432,438
1990/0227    
 
1992/1024    
static 
int 
noconv(void *o, Fconv *fp) 
1996/0214    
noconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n; 
	char s[10]; 
1995/0804/sys/src/9/port/print.c:475,4831996/0214/sys/src/9/port/print.c:442,453
1992/1024    
		n = 0; 
		if(fp->chr >= 0 && fp->chr < MAXFMT) 
			n = fmtindex[fp->chr]; 
		return (*fmtconv[n])(o, fp); 
1996/0214    
		return (*fmtconv[n])(arg, fp); 
1992/1024    
	} 
	sprint(s, "*%c*", fp->chr); 
1996/0214    
	s[0] = '*'; 
	s[1] = fp->chr; 
	s[2] = '*'; 
	s[3] = 0; 
1992/1024    
	fp->f1 = 0; 
	fp->f2 = NONE; 
	fp->f3 = 0; 
1995/0804/sys/src/9/port/print.c:487,4981996/0214/sys/src/9/port/print.c:457,468
1990/0227    
 
1992/1024    
static 
int 
cconv(void *o, Fconv *fp) 
1996/0214    
cconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
	Rune rune; 
1990/0227    
 
1992/1024    
	rune = *(int*)o; 
1996/0214    
	rune = va_arg(*arg, int); 
1992/1024    
	if(fp->chr == 'c') 
		rune &= 0xff; 
	s[runetochar(s, &rune)] = 0; 
1995/0804/sys/src/9/port/print.c:499,5431996/0214/sys/src/9/port/print.c:469,517
1990/0227    
 
1992/1024    
	fp->f2 = NONE; 
	strconv(s, fp); 
	return INT; 
1996/0214    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
sconv(void *o, Fconv *fp) 
1996/0214    
sconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char *s; 
	Rune *r; 
1990/0227    
 
1992/1024    
	if(fp->chr == 's') { 
		s = *(char**)o; 
1996/0214    
		s = va_arg(*arg, char*); 
1992/1024    
		if(s == 0) 
			s = "<null>"; 
		strconv(s, fp); 
	} else { 
		r = *(Rune**)o; 
1996/0214    
		r = va_arg(*arg, Rune*); 
1992/1024    
		if(r == 0) 
			r = L"<null>"; 
		Strconv(r, fp); 
	} 
	return PTR; 
1996/0214    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1995/0804    
percent(void*, Fconv *fp) 
1996/0214    
percent(va_list *arg, Fconv *fp) 
1990/0227    
{ 
 
1996/0214    
	USED(arg); 
1992/1024    
	if(fp->out < fp->eout) 
		*fp->out++ = '%'; 
1996/0214    
	printcol++; 
1992/1024    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1995/0804    
flags(void*, Fconv *fp) 
1996/0214    
flags(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int f; 
1996/0214    
 
	USED(arg); 
1990/0227    
 
1992/1024    
	f = 0; 
	switch(fp->chr) { 
1996/0214/sys/src/9/port/print.c:219,2251998/0327/sys/src/9/port/print.c:219,229 (short | long)
Add vlong support to print.
rsc Fri Mar 4 12:44:25 2005
1996/0214    
	int i, f, n, b, ucase; 
1990/0227    
	short h; 
1992/1024    
	long v; 
1998/0327    
	vlong vl; 
1990/0227    
 
1998/0327    
	SET(v); 
	SET(vl); 
 
1992/1024    
	ucase = 0; 
	b = fp->chr; 
	switch(fp->chr) { 
1996/0214/sys/src/9/port/print.c:241,2471998/0327/sys/src/9/port/print.c:245,259
1992/1024    
	} 
 
1990/0227    
	f = 0; 
1996/0214    
	switch(fp->f3 & (FLONG|FSHORT|FUNSIGN)) { 
1998/0327    
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 
	case FVLONG|FLONG: 
		vl = va_arg(*arg, vlong); 
		break; 
 
	case FUNSIGN|FVLONG|FLONG: 
		vl = va_arg(*arg, uvlong); 
		break; 
 
1990/0227    
	case FLONG: 
1996/0214    
		v = va_arg(*arg, long); 
1990/0227    
		break; 
1996/0214/sys/src/9/port/print.c:268,2801998/0327/sys/src/9/port/print.c:280,302
1996/0214    
		v = va_arg(*arg, unsigned); 
1990/0227    
		break; 
	} 
1992/1024    
	if(!(fp->f3 & FUNSIGN) && v < 0) { 
1990/0227    
		v = -v; 
		f = 1; 
1998/0327    
	if(fp->f3 & FVLONG) { 
		if(!(fp->f3 & FUNSIGN) && vl < 0) { 
			vl = -vl; 
			f = 1; 
		} 
	} else { 
		if(!(fp->f3 & FUNSIGN) && v < 0) { 
			v = -v; 
			f = 1; 
		} 
1990/0227    
	} 
1992/1024    
	s[IDIGIT-1] = 0; 
1990/0227    
	for(i = IDIGIT-2;; i--) { 
1996/0214    
		n = (ulong)v % b; 
1998/0327    
		if(fp->f3 & FVLONG) 
			n = (uvlong)vl % b; 
		else 
			n = (ulong)v % b; 
1990/0227    
		n += '0'; 
1992/1024    
		if(n > '9') { 
1990/0227    
			n += 'a' - ('9'+1); 
1996/0214/sys/src/9/port/print.c:284,2921998/0327/sys/src/9/port/print.c:306,322
1992/1024    
		s[i] = n; 
1990/0227    
		if(i < 2) 
			break; 
1996/0214    
		v = (ulong)v / b; 
1998/0327    
		if(fp->f3 & FVLONG) 
			vl = (uvlong)vl / b; 
		else 
			v = (ulong)v / b; 
1992/1024    
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2) 
1990/0227    
			continue; 
1998/0327    
		if(fp->f3 & FVLONG) { 
			if(vl <= 0) 
				break; 
			continue; 
		} 
1990/0227    
		if(v <= 0) 
			break; 
	} 
1998/0327/sys/src/9/port/print.c:121,1271998/0512/sys/src/9/port/print.c:121,127 (short | long)
Whitespace edit.
rsc Fri Mar 4 12:44:25 2005
1992/1024    
	case 0: 
		*local.out = 0; 
		return local.out; 
	                 
1998/0512    
 
1992/1024    
	default: 
		printcol++; 
		goto common; 
1998/0512/sys/src/9/port/print.c:18,231999/0517/sys/src/9/port/print.c:18,24 (short | long)
Add %p.
rsc Fri Mar 4 12:44:25 2005
1996/0214    
	FSHORT	= 1<<4, 
	FUNSIGN	= 1<<5, 
	FVLONG	= 1<<6, 
1999/0517    
	FPOINTER	= 1<<7, 
1992/1024    
}; 
 
int	printcol; 
1998/0512/sys/src/9/port/print.c:64,691999/0517/sys/src/9/port/print.c:65,71
1992/1024    
	fmtindex['o'] = cc; 
	fmtindex['x'] = cc; 
	fmtindex['X'] = cc; 
1999/0517    
	fmtindex['p'] = cc; 
1992/1024    
	cc++; 
 
	fmtconv[cc] = cconv; 
1998/0512/sys/src/9/port/print.c:242,2471999/0517/sys/src/9/port/print.c:244,253
1992/1024    
	case 'x': 
		b = 16; 
		break; 
1999/0517    
	case 'p': 
		fp->f3 |= FPOINTER|FUNSIGN; 
		b = 16; 
		break; 
1992/1024    
	} 
 
1990/0227    
	f = 0; 
1998/0512/sys/src/9/port/print.c:270,2751999/0517/sys/src/9/port/print.c:276,285
1990/0227    
	case FUNSIGN|FSHORT: 
1996/0214    
		h = va_arg(*arg, int); 
1992/1024    
		v = (ushort)h; 
1999/0517    
		break; 
 
	case FUNSIGN|FPOINTER: 
		v = (ulong)va_arg(*arg, void*); 
1990/0227    
		break; 
 
	default: 
1999/0517/sys/src/9/port/print.c:3,91999/0810/sys/src/9/port/print.c:3,8 (short | long)
Remove unused SIZE.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
 
1992/1024    
enum 
{ 
	SIZE	= 1024, 
	IDIGIT	= 30, 
	MAXCONV	= 40, 
	FDIGIT	= 30, 
1999/0810/sys/src/9/port/print.c:1,51999/0819/sys/src/9/port/print.c:1,8 (short | long)
Bug fix: move globals into locked fmtalloc. Call initfmt from fmtinstall, not noconv.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1999/0819    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1990/0227    
 
1992/1024    
enum 
{ 
1999/0810/sys/src/9/port/print.c:14,871999/0819/sys/src/9/port/print.c:17,112
1996/0214    
	FMINUS	= 1<<1, 
	FSHARP	= 1<<2, 
	FLONG	= 1<<3, 
	FSHORT	= 1<<4, 
	FUNSIGN	= 1<<5, 
	FVLONG	= 1<<6, 
1999/0517    
	FPOINTER	= 1<<7, 
1999/0819    
	FPOINTER= 1<<7, 
1992/1024    
}; 
 
int	printcol; 
1990/0227    
 
1992/1024    
static	int	convcount; 
static	char	fmtindex[MAXFMT]; 
1999/0819    
static struct 
{ 
	Lock; 
	int	convcount; 
	char	index[MAXFMT]; 
	int	(*conv[MAXCONV])(va_list*, Fconv*); 
} fmtalloc; 
1990/0227    
 
1996/0214    
static	int	noconv(va_list*, Fconv*); 
static	int	flags(va_list*, Fconv*); 
1990/0227    
 
1996/0214    
static	int	cconv(va_list*, Fconv*); 
1999/0819    
/* static	int	rconv(va_list*, Fconv*); */ 
1996/0214    
static	int	sconv(va_list*, Fconv*); 
static	int	percent(va_list*, Fconv*); 
1999/0819    
/* static	int	column(va_list*, Fconv*); */ 
1992/1024    
 
1996/0214    
int	numbconv(va_list*, Fconv*); 
1999/0819    
extern	int	numbconv(va_list*, Fconv*); 
/* extern	int	fltconv(va_list*, Fconv*); */ 
1992/1024    
 
1990/0227    
static 
1996/0214    
int	(*fmtconv[MAXCONV])(va_list*, Fconv*) = 
1990/0227    
{ 
1992/1024    
	noconv 
1990/0227    
}; 
1992/1024    
 
1990/0227    
static 
1992/1024    
void 
1999/0819    
static	void 
1992/1024    
initfmt(void) 
1990/0227    
{ 
1992/1024    
	int cc; 
1990/0227    
 
1992/1024    
	cc = 0; 
	fmtconv[cc] = noconv; 
1999/0819    
	fmtalloc.conv[cc] = noconv; 
1992/1024    
	cc++; 
 
	fmtconv[cc] = flags; 
	fmtindex['+'] = cc; 
	fmtindex['-'] = cc; 
	fmtindex['#'] = cc; 
	fmtindex['h'] = cc; 
	fmtindex['l'] = cc; 
	fmtindex['u'] = cc; 
1999/0819    
	fmtalloc.conv[cc] = flags; 
	fmtalloc.index['+'] = cc; 
	fmtalloc.index['-'] = cc; 
	fmtalloc.index['#'] = cc; 
	fmtalloc.index['l'] = cc; 
	fmtalloc.index['u'] = cc; 
1992/1024    
	cc++; 
 
	fmtconv[cc] = numbconv; 
	fmtindex['d'] = cc; 
	fmtindex['o'] = cc; 
	fmtindex['x'] = cc; 
	fmtindex['X'] = cc; 
1999/0517    
	fmtindex['p'] = cc; 
1999/0819    
	fmtalloc.conv[cc] = numbconv; 
	fmtalloc.index['d'] = cc; 
	fmtalloc.index['o'] = cc; 
	fmtalloc.index['x'] = cc; 
	fmtalloc.index['X'] = cc; 
	fmtalloc.index['p'] = cc; 
1992/1024    
	cc++; 
 
	fmtconv[cc] = cconv; 
	fmtindex['c'] = cc; 
	fmtindex['C'] = cc; 
1999/0819    
/* 
	fmtalloc.conv[cc] = fltconv; 
	fmtalloc.index['e'] = cc; 
	fmtalloc.index['f'] = cc; 
	fmtalloc.index['g'] = cc; 
	fmtalloc.index['E'] = cc; 
	fmtalloc.index['G'] = cc; 
1992/1024    
	cc++; 
1999/0819    
*/ 
1992/1024    
 
	fmtconv[cc] = sconv; 
	fmtindex['s'] = cc; 
	fmtindex['S'] = cc; 
1999/0819    
	fmtalloc.conv[cc] = cconv; 
	fmtalloc.index['c'] = cc; 
	fmtalloc.index['C'] = cc; 
1992/1024    
	cc++; 
 
	fmtconv[cc] = percent; 
	fmtindex['%'] = cc; 
1999/0819    
/* 
	fmtalloc.conv[cc] = rconv; 
	fmtalloc.index['r'] = cc; 
1992/1024    
	cc++; 
1999/0819    
*/ 
1992/1024    
 
	convcount = cc; 
1999/0819    
	fmtalloc.conv[cc] = sconv; 
	fmtalloc.index['s'] = cc; 
	fmtalloc.index['S'] = cc; 
	cc++; 
 
	fmtalloc.conv[cc] = percent; 
	fmtalloc.index['%'] = cc; 
	cc++; 
 
/* 
	fmtalloc.conv[cc] = column; 
	fmtalloc.index['|'] = cc; 
	cc++; 
*/ 
 
	fmtalloc.convcount = cc; 
1992/1024    
} 
 
1990/0227    
int 
1999/0810/sys/src/9/port/print.c:88,1051999/0819/sys/src/9/port/print.c:113,158
1996/0214    
fmtinstall(int c, int (*f)(va_list*, Fconv*)) 
1990/0227    
{ 
 
1992/1024    
	if(convcount == 0) 
1999/0819    
	lock(&fmtalloc); 
 
	if(fmtalloc.convcount <= 0) 
1992/1024    
		initfmt(); 
	if(c < 0 || c >= MAXFMT) 
1999/0819    
	if(c < 0 || c >= MAXFMT){ 
		unlock(&fmtalloc); 
1996/0214    
		return -1; 
1992/1024    
	if(convcount >= MAXCONV) 
1999/0819    
	} 
	if(fmtalloc.convcount >= MAXCONV){ 
		unlock(&fmtalloc); 
1996/0214    
		return -1; 
1992/1024    
	fmtconv[convcount] = f; 
	fmtindex[c] = convcount; 
	convcount++; 
1999/0819    
	} 
	fmtalloc.conv[fmtalloc.convcount] = f; 
	fmtalloc.index[c] = fmtalloc.convcount; 
	fmtalloc.convcount++; 
 
	unlock(&fmtalloc); 
1990/0227    
	return 0; 
} 
 
1999/0819    
static	void 
pchar(Rune c, Fconv *fp) 
{ 
	int n; 
 
	n = fp->eout - fp->out; 
	if(n > 0) { 
		if(c < Runeself) { 
			*fp->out++ = c; 
			return; 
		} 
		if(n >= UTFmax || n >= runelen(c)) { 
			n = runetochar(fp->out, &c); 
			fp->out += n; 
			return; 
		} 
		fp->eout = fp->out; 
	} 
} 
 
1990/0227    
char* 
1996/0214    
doprint(char *s, char *es, char *fmt, va_list argp) 
1990/0227    
{ 
1999/0810/sys/src/9/port/print.c:107,1141999/0819/sys/src/9/port/print.c:160,172
1992/1024    
	Rune rune; 
	Fconv local; 
1990/0227    
 
1999/0819    
	if(fmtalloc.convcount <= 0) 
		initfmt(); 
 
	if(s >= es) 
		return s; 
1992/1024    
	local.out = s; 
1996/0214    
	local.eout = es-UTFmax-1; 
1999/0819    
	local.eout = es-1; 
1990/0227    
 
loop: 
1992/1024    
	c = *fmt & 0xff; 
1999/0810/sys/src/9/port/print.c:122,1281999/0819/sys/src/9/port/print.c:180,186
1992/1024    
	case 0: 
		*local.out = 0; 
		return local.out; 
1998/0512    
                 
1999/0819    
	 
1992/1024    
	default: 
		printcol++; 
		goto common; 
1999/0810/sys/src/9/port/print.c:136,1481999/0819/sys/src/9/port/print.c:194,200
1992/1024    
		goto common; 
 
	common: 
		if(local.out < local.eout) 
			if(c >= Runeself) { 
				rune = c; 
1996/0214    
				n = runetochar(local.out, &rune); 
1992/1024    
				local.out += n; 
			} else 
				*local.out++ = c; 
1999/0819    
		pchar(c, &local); 
1990/0227    
		goto loop; 
1992/1024    
 
	case '%': 
1999/0810/sys/src/9/port/print.c:203,2111999/0819/sys/src/9/port/print.c:255,263
1990/0227    
	} 
1992/1024    
	n = 0; 
	if(c >= 0 && c < MAXFMT) 
		n = fmtindex[c]; 
1999/0819    
		n = fmtalloc.index[c]; 
1992/1024    
	local.chr = c; 
1996/0214    
	n = (*fmtconv[n])(&argp, &local); 
1999/0819    
	n = (*fmtalloc.conv[n])(&argp, &local); 
1992/1024    
	if(n < 0) { 
		local.f3 |= -n; 
		goto l0; 
1999/0810/sys/src/9/port/print.c:218,2241999/0819/sys/src/9/port/print.c:270,275
1990/0227    
{ 
1992/1024    
	char s[IDIGIT]; 
1996/0214    
	int i, f, n, b, ucase; 
1990/0227    
	short h; 
1992/1024    
	long v; 
1998/0327    
	vlong vl; 
1990/0227    
 
1999/0810/sys/src/9/port/print.c:234,2391999/0819/sys/src/9/port/print.c:285,294
1992/1024    
		b = 10; 
		break; 
 
1999/0819    
	case 'b': 
		b = 2; 
		break; 
 
1992/1024    
	case 'o': 
		b = 8; 
		break; 
1999/0810/sys/src/9/port/print.c:250,2561999/0819/sys/src/9/port/print.c:305,311
1992/1024    
	} 
 
1990/0227    
	f = 0; 
1998/0327    
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 
1999/0819    
	switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) { 
1998/0327    
	case FVLONG|FLONG: 
		vl = va_arg(*arg, vlong); 
		break; 
1999/0810/sys/src/9/port/print.c:259,2641999/0819/sys/src/9/port/print.c:314,323
1998/0327    
		vl = va_arg(*arg, uvlong); 
		break; 
 
1999/0819    
	case FUNSIGN|FPOINTER: 
		v = (ulong)va_arg(*arg, void*); 
		break; 
 
1990/0227    
	case FLONG: 
1996/0214    
		v = va_arg(*arg, long); 
1990/0227    
		break; 
1999/0810/sys/src/9/port/print.c:267,2861999/0819/sys/src/9/port/print.c:326,331
1996/0214    
		v = va_arg(*arg, ulong); 
1990/0227    
		break; 
 
	case FSHORT: 
1996/0214    
		h = va_arg(*arg, int); 
1990/0227    
		v = h; 
		break; 
                 
	case FUNSIGN|FSHORT: 
1996/0214    
		h = va_arg(*arg, int); 
1992/1024    
		v = (ushort)h; 
1999/0517    
		break; 
                 
	case FUNSIGN|FPOINTER: 
		v = (ulong)va_arg(*arg, void*); 
1990/0227    
		break; 
                 
	default: 
1996/0214    
		v = va_arg(*arg, int); 
1990/0227    
		break; 
1999/0810/sys/src/9/port/print.c:351,3581999/0819/sys/src/9/port/print.c:396,402
1990/0227    
void 
1992/1024    
Strconv(Rune *s, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int n, c, i; 
	Rune rune; 
1999/0819    
	int n, c; 
1990/0227    
 
1992/1024    
	if(fp->f3 & FMINUS) 
		fp->f1 = -fp->f1; 
1999/0810/sys/src/9/port/print.c:361,3681999/0819/sys/src/9/port/print.c:405,411
1992/1024    
		for(; s[n]; n++) 
			; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
1990/0227    
			n++; 
		} 
1999/0810/sys/src/9/port/print.c:373,3851999/0819/sys/src/9/port/print.c:416,422
1992/1024    
			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; 
1999/0819    
			pchar(c, fp); 
1992/1024    
			if(fp->f2 != NONE) 
				fp->f2--; 
			switch(c) { 
1999/0810/sys/src/9/port/print.c:398,4051999/0819/sys/src/9/port/print.c:435,441
1992/1024    
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
1990/0227    
			n++; 
		} 
1999/0810/sys/src/9/port/print.c:418,4251999/0819/sys/src/9/port/print.c:454,460
1992/1024    
	if(fp->f1 != NONE && fp->f1 >= 0) { 
		n = utflen(s); 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
			n++; 
		} 
1999/0810/sys/src/9/port/print.c:436,4481999/0819/sys/src/9/port/print.c:471,477
1992/1024    
			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; 
1999/0819    
			pchar(c, fp); 
1992/1024    
			if(fp->f2 != NONE) 
				fp->f2--; 
			switch(c) { 
1999/0810/sys/src/9/port/print.c:461,4681999/0819/sys/src/9/port/print.c:490,496
1992/1024    
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			if(fp->out < fp->eout) 
				*fp->out++ = ' '; 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
			n++; 
		} 
1999/0810/sys/src/9/port/print.c:469,4881999/0819/sys/src/9/port/print.c:497,507
1992/1024    
	} 
1990/0227    
} 
 
1992/1024    
static 
int 
1996/0214    
noconv(va_list *arg, Fconv *fp) 
1999/0819    
static int 
noconv(va_list*, 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]; 
1996/0214    
		return (*fmtconv[n])(arg, fp); 
1992/1024    
	} 
1996/0214    
	s[0] = '*'; 
	s[1] = fp->chr; 
	s[2] = '*'; 
1999/0810/sys/src/9/port/print.c:494,5011999/0819/sys/src/9/port/print.c:513,533
1992/1024    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1999/0819    
#ifdef NOTDEF 
static int 
rconv(va_list*, Fconv *fp) 
{ 
	char s[ERRLEN]; 
 
	s[0] = 0; 
	errstr(s); 
	fp->f2 = NONE; 
	strconv(s, fp); 
	return 0; 
} 
#endif 
 
static int 
1996/0214    
cconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
1999/0810/sys/src/9/port/print.c:511,5181999/0819/sys/src/9/port/print.c:543,549
1996/0214    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1999/0819    
static	int 
1996/0214    
sconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char *s; 
1999/0810/sys/src/9/port/print.c:532,5571999/0819/sys/src/9/port/print.c:563,602
1996/0214    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1996/0214    
percent(va_list *arg, Fconv *fp) 
1999/0819    
static	int 
percent(va_list*, Fconv *fp) 
1990/0227    
{ 
                 
1996/0214    
	USED(arg); 
1992/1024    
	if(fp->out < fp->eout) 
		*fp->out++ = '%'; 
1999/0819    
	pchar('%', fp); 
1996/0214    
	printcol++; 
1992/1024    
	return 0; 
1990/0227    
} 
 
1992/1024    
static 
int 
1996/0214    
flags(va_list *arg, Fconv *fp) 
1999/0819    
#ifdef NOTDEF 
static	int 
column(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	int f; 
1999/0819    
	int col, pc; 
1996/0214    
 
	USED(arg); 
1999/0819    
	col = va_arg(*arg, int); 
	while(printcol < col) { 
		pc = (printcol+8) & ~7; 
		if(pc <= col) { 
			pchar('\t', fp); 
			printcol = pc; 
		} else { 
			pchar(' ', fp); 
			printcol++; 
		} 
	} 
	return 0; 
} 
#endif 
1990/0227    
 
1999/0819    
static	int 
flags(va_list*, Fconv *fp) 
{ 
	int f; 
 
1992/1024    
	f = 0; 
	switch(fp->chr) { 
	case '+': 
1999/0810/sys/src/9/port/print.c:566,5751999/0819/sys/src/9/port/print.c:611,616
1992/1024    
		f = FSHARP; 
		break; 
1990/0227    
 
1992/1024    
	case 'h': 
		f = FSHORT; 
		break; 
1990/0227    
                 
1992/1024    
	case 'l': 
		f = FLONG; 
		if(fp->f3 & FLONG) 
1999/0810/sys/src/9/port/print.c:582,5841999/0819/sys/src/9/port/print.c:623,839
1992/1024    
	} 
	return -f; 
1990/0227    
} 
1999/0819    
 
#ifdef NOTDEF 
int 
fltconv(va_list *arg, Fconv *fp) 
{ 
	char s1[FDIGIT+10], s2[FDIGIT+10]; 
	double f, g, h; 
	int e, d, i, n, s; 
	int c1, c2, c3, f2, ucase; 
 
	f2 = fp->f2; 
	fp->f2 = NONE; 
 
	f = va_arg(*arg, double); 
	if(isNaN(f)){ 
		strconv("NaN", fp); 
		return 0; 
	} 
	if(isInf(f, 1)){ 
		strconv("+Inf", fp); 
		return 0; 
	} 
	if(isInf(f, -1)){ 
		strconv("-Inf", fp); 
		return 0; 
	} 
	s = 0; 
	if(f < 0) { 
		f = -f; 
		s++; 
	} 
	ucase = 0; 
	if(fp->chr >= 'A' && fp->chr <= 'Z') { 
		ucase = 1; 
		fp->chr += 'a'-'A'; 
	} 
 
loop: 
	e = 0; 
	if(f != 0) { 
		frexp(f, &e); 
		e = e * .30103; 
		d = e/2; 
		h = f * pow10(-d);		/* 10**-e in 2 parts */ 
		g = h * pow10(d-e); 
		while(g < 1) { 
			e--; 
			g = h * pow10(d-e); 
		} 
		while(g >= 10) { 
			e++; 
			g = h * pow10(d-e); 
		} 
	} 
	if(f2 == NONE) 
		f2 = FDEFLT; 
	if(fp->chr == 'g' && f2 > 0) 
		f2--; 
	if(f2 > FDIGIT) 
		f2 = FDIGIT; 
 
	/* 
	 * n is number of digits to convert 
	 * 1 before, f2 after, 1 extra for rounding 
	 */ 
	n = f2 + 2; 
	if(fp->chr == 'f') { 
 
		/* 
		 * e+1 before, f2 after, 1 extra 
		 */ 
		n += e; 
		if(n <= 0) 
			n = 1; 
	} 
	if(n >= FDIGIT+2) { 
		if(fp->chr == 'e') 
			f2 = -1; 
		fp->chr = 'e'; 
		goto loop; 
	} 
 
	/* 
	 * convert n digits 
	 */ 
	g = f; 
	if(e < 0) { 
		if(e < -55) { 
			g *= pow10(50); 
			g *= pow10(-e-51); 
		} else 
			g *= pow10(-e-1); 
	} 
	for(i=0; i<n; i++) { 
		d = e-i; 
		if(d >= 0) { 
			h = pow10(d); 
			d = floor(g/h); 
			g -= d * h; 
		} else { 
			g *= 10; 
			d = floor(g); 
			g -= d; 
		} 
		s1[i+1] = d + '0'; 
	} 
 
	/* 
	 * round by adding .5 into extra digit 
	 */ 
	d = 5; 
	for(i=n-1; i>=0; i--) { 
		s1[i+1] += d; 
		d = 0; 
		if(s1[i+1] > '9') { 
			s1[i+1] -= 10; 
			d++; 
		} 
	} 
	i = 1; 
	if(d) { 
		s1[0] = '1'; 
		e++; 
		i = 0; 
	} 
 
	/* 
	 * copy into final place 
	 * c1 digits of leading '0' 
	 * c2 digits from conversion 
	 * c3 digits after '.' 
	 */ 
	d = 0; 
	if(s) 
		s2[d++] = '-'; 
	else 
	if(fp->f3 & FPLUS) 
		s2[d++] = '+'; 
	c1 = 0; 
	c2 = f2 + 1; 
	c3 = f2; 
	if(fp->chr == 'g') 
	if(e >= -5 && e <= f2) { 
		c1 = -e - 1; 
		if(c1 < 0) 
			c1 = 0; 
		c3 = f2 - e; 
		fp->chr = 'h'; 
	} 
	if(fp->chr == 'f') { 
		c1 = -e; 
		if(c1 < 0) 
			c1 = 0; 
		if(c1 > f2) 
			c1 = c2; 
		c2 += e; 
		if(c2 < 0) 
			c2 = 0; 
	} 
	while(c1 > 0) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
		s2[d++] = '0'; 
		c1--; 
	} 
	while(c2 > 0) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
		s2[d++] = s1[i++]; 
		c2--; 
	} 
 
	/* 
	 * strip trailing '0' on g conv 
	 */ 
	if(fp->f3 & FSHARP) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
	} else 
	if(fp->chr == 'g' || fp->chr == 'h') { 
		for(n=d-1; n>=0; n--) 
			if(s2[n] != '0') 
				break; 
		for(i=n; i>=0; i--) 
			if(s2[i] == '.') { 
				d = n; 
				if(i != n) 
					d++; 
				break; 
			} 
	} 
	if(fp->chr == 'e' || fp->chr == 'g') { 
		if(ucase) 
			s2[d++] = 'E'; 
		else 
			s2[d++] = 'e'; 
		c1 = e; 
		if(c1 < 0) { 
			s2[d++] = '-'; 
			c1 = -c1; 
		} else 
			s2[d++] = '+'; 
		if(c1 >= 100) { 
			s2[d++] = c1/100 + '0'; 
			c1 = c1%100; 
		} 
		s2[d++] = c1/10 + '0'; 
		s2[d++] = c1%10 + '0'; 
	} 
	s2[d] = 0; 
	strconv(s2, fp); 
	return 0; 
} 
#endif 
1999/0819/sys/src/9/port/print.c:43,482001/0316/sys/src/9/port/print.c:43,50 (short | long)
Add %q for quoted strings.
rsc Fri Mar 4 12:44:25 2005
1992/1024    
 
1999/0819    
extern	int	numbconv(va_list*, Fconv*); 
/* extern	int	fltconv(va_list*, Fconv*); */ 
2001/0316    
extern	int	quotestrconv(va_list*, Fconv*); 
extern	int	quoterunestrconv(va_list*, Fconv*); 
1992/1024    
 
 
1999/0819    
static	void 
1999/0819/sys/src/9/port/print.c:90,962001/0316/sys/src/9/port/print.c:92,105
1999/0819    
	fmtalloc.index['r'] = cc; 
1992/1024    
	cc++; 
1999/0819    
*/ 
2001/0316    
	fmtalloc.conv[cc] = quotestrconv; 
	fmtalloc.index['q'] = cc; 
	cc++; 
1992/1024    
 
2001/0316    
	fmtalloc.conv[cc] = quoterunestrconv; 
	fmtalloc.index['Q'] = cc; 
	cc++; 
 
1999/0819    
	fmtalloc.conv[cc] = sconv; 
	fmtalloc.index['s'] = cc; 
	fmtalloc.index['S'] = cc; 
1999/0819/sys/src/9/port/print.c:622,6272001/0316/sys/src/9/port/print.c:631,852
1992/1024    
		break; 
	} 
	return -f; 
2001/0316    
} 
 
static	void 
qchar(Rune c, Fconv *fp, int hold, int *closed) 
{ 
	int n; 
 
	if(*closed) 
		return; 
	n = fp->eout - fp->out - hold; 
	if(n > 0) { 
		if(c < Runeself) { 
			*fp->out++ = c; 
			return; 
		} 
		if(n >= UTFmax || n >= runelen(c)) { 
			n = runetochar(fp->out, &c); 
			fp->out += n; 
			return; 
		} 
	} 
	if(hold) 
		*closed = 1; 
	else 
		fp->eout = fp->out; 
} 
 
static int 
needsquotes(char *s, int *quotelenp) 
{ 
	char *t; 
	int nextra, ok, w; 
	Rune r; 
 
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t+=w){ 
		w = chartorune(&r, t); 
		if(r <= L' ') 
			ok = 0; 
		else if(r == L'\''){ 
			ok = 0; 
			nextra++;	/* ' becomes '' */ 
		} 
	} 
 
	if(ok){ 
		*quotelenp = t-s; 
		return 0; 
	} 
	*quotelenp = 1+ t-s + nextra +1; 
	return 1; 
} 
 
static int 
runeneedsquotes(Rune *s, int *quotelenp) 
{ 
	Rune *t; 
	int nextra, ok; 
	Rune r; 
 
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t++){ 
		r = *t; 
		if(r <= L' ') 
			ok = 0; 
		else if(r == L'\''){ 
			ok = 0; 
			nextra++;	/* ' becomes '' */ 
		} 
	} 
 
	if(ok){ 
		*quotelenp = t-s; 
		return 0; 
	} 
	*quotelenp = 1+ t-s + nextra +1; 
	return 1; 
} 
 
void 
qadv(Rune c, Fconv *fp, int hold, int *np, int *closedp) 
{ 
	if(fp->f2 == NONE || fp->f2 > 0) { 
		qchar(c, fp, hold, closedp); 
		(*np)++; 
		if(fp->f2 != NONE) 
			fp->f2--; 
		switch(c) { 
		default: 
			printcol++; 
			break; 
		case '\n': 
			printcol = 0; 
			break; 
		case '\t': 
			printcol = (printcol+8) & ~7; 
			break; 
		} 
	} 
} 
 
static int 
qstrconv(char *s, Rune *r, int quotelen, Fconv *fp) 
{ 
	int closed, i, n, c; 
	Rune rune; 
 
	closed = 0; 
	if(fp->f3 & FMINUS) 
		fp->f1 = -fp->f1; 
	n = 0; 
	if(fp->f1 != NONE && fp->f1 >= 0) { 
		n = quotelen; 
		while(n < fp->f1) { 
			qchar(' ', fp, 0, &closed); 
			printcol++; 
			n++; 
		} 
	} 
 
	if(fp->eout - fp->out < 2)	/* 2 because need at least '' */ 
		return 0; 
 
	qchar('\'', fp, 0, &closed); 
	n++; 
 
	for(;;) { 
		if(s){ 
			c = *s & 0xff; 
			if(c >= Runeself) { 
				i = chartorune(&rune, s); 
				s += i; 
				c = rune; 
			} else 
				s++; 
		}else 
			c = *r++; 
 
		if(c == 0) 
			break; 
		if(c == '\'') 
			qadv(c, fp, 2, &n, &closed);	/* '' plus closing quote */ 
		qadv(c, fp, 1, &n, &closed); 
	} 
	closed = 0;	/* there will always be room for closing quote */ 
	qchar('\'', fp, 0, &closed); 
	n++; 
 
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			qchar(' ', fp, 0, &closed); 
			printcol++; 
			n++; 
		} 
	} 
 
	return 0; 
 
} 
 
int 
quotestrconv(va_list *arg, Fconv *fp) 
{ 
	char *s; 
	int quotelen; 
 
	s = va_arg(*arg, char*); 
	if(s == nil){ 
		strconv("<null>", fp); 
		return 0; 
	} 
 
	if(needsquotes(s, "elen) == 0){ 
		strconv(s, fp); 
		va_end(arg); 
		return 0; 
	} 
 
	qstrconv(s, nil, quotelen, fp); 
 
	va_end(arg); 
	return 0; 
} 
 
int 
quoterunestrconv(va_list *arg, Fconv *fp) 
{ 
	Rune *r; 
	int quotelen; 
 
	r = va_arg(*arg, Rune*); 
	if(r == nil){ 
		strconv("<null>", fp); 
		return 0; 
	} 
 
	if(runeneedsquotes(r, "elen) == 0){ 
		Strconv(r, fp); 
		va_end(arg); 
		return 0; 
	} 
 
	qstrconv(nil, r, quotelen, fp); 
 
	va_end(arg); 
	return 0; 
} 
 
void 
quotefmtinstall(void) 
{ 
	fmtinstall('q', quotestrconv); 
	fmtinstall('Q', quoterunestrconv); 
1990/0227    
} 
1999/0819    
 
#ifdef NOTDEF 
2001/0316/sys/src/9/port/print.c:665,6702001/0819/sys/src/9/port/print.c:665,672 (short | long)
Change rune from '\0' to L'\0'.
rsc Fri Mar 4 12:44:25 2005
2001/0316    
	int nextra, ok, w; 
	Rune r; 
 
2001/0819    
	if(*s == '\0') 
		return 1; 
2001/0316    
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t+=w){ 
2001/0316/sys/src/9/port/print.c:692,6972001/0819/sys/src/9/port/print.c:694,701
2001/0316    
	int nextra, ok; 
	Rune r; 
 
2001/0819    
	if(*s == L'\0') 
		return 1; 
2001/0316    
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t++){ 
2001/0819/sys/src/9/port/print.c:1,10682002/0217/sys/src/9/port/print.c:1,25 (short | long)
Remove print code; link with fmt library instead.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1999/0819    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
2002/0217    
#include "u.h" 
#include "../port/lib.h" 
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
1990/0227    
 
1992/1024    
enum 
{ 
	IDIGIT	= 30, 
	MAXCONV	= 40, 
	FDIGIT	= 30, 
	FDEFLT	= 6, 
	NONE	= -1000, 
	MAXFMT	= 512, 
2002/0217    
static Lock fmtl; 
1992/1024    
 
1996/0214    
	FPLUS	= 1<<0, 
	FMINUS	= 1<<1, 
	FSHARP	= 1<<2, 
	FLONG	= 1<<3, 
	FUNSIGN	= 1<<5, 
	FVLONG	= 1<<6, 
1999/0819    
	FPOINTER= 1<<7, 
1992/1024    
}; 
                 
int	printcol; 
1990/0227    
                 
1999/0819    
static struct 
{ 
	Lock; 
	int	convcount; 
	char	index[MAXFMT]; 
	int	(*conv[MAXCONV])(va_list*, Fconv*); 
} fmtalloc; 
1990/0227    
                 
1996/0214    
static	int	noconv(va_list*, Fconv*); 
static	int	flags(va_list*, Fconv*); 
1990/0227    
                 
1996/0214    
static	int	cconv(va_list*, Fconv*); 
1999/0819    
/* static	int	rconv(va_list*, Fconv*); */ 
1996/0214    
static	int	sconv(va_list*, Fconv*); 
static	int	percent(va_list*, Fconv*); 
1999/0819    
/* static	int	column(va_list*, Fconv*); */ 
1992/1024    
                 
1999/0819    
extern	int	numbconv(va_list*, Fconv*); 
/* extern	int	fltconv(va_list*, Fconv*); */ 
2001/0316    
extern	int	quotestrconv(va_list*, Fconv*); 
extern	int	quoterunestrconv(va_list*, Fconv*); 
1992/1024    
                 
                 
1999/0819    
static	void 
1992/1024    
initfmt(void) 
1990/0227    
{ 
1992/1024    
	int cc; 
1990/0227    
                 
1992/1024    
	cc = 0; 
1999/0819    
	fmtalloc.conv[cc] = noconv; 
1992/1024    
	cc++; 
                 
1999/0819    
	fmtalloc.conv[cc] = flags; 
	fmtalloc.index['+'] = cc; 
	fmtalloc.index['-'] = cc; 
	fmtalloc.index['#'] = cc; 
	fmtalloc.index['l'] = cc; 
	fmtalloc.index['u'] = cc; 
1992/1024    
	cc++; 
                 
1999/0819    
	fmtalloc.conv[cc] = numbconv; 
	fmtalloc.index['d'] = cc; 
	fmtalloc.index['o'] = cc; 
	fmtalloc.index['x'] = cc; 
	fmtalloc.index['X'] = cc; 
	fmtalloc.index['p'] = cc; 
1992/1024    
	cc++; 
                 
1999/0819    
/* 
	fmtalloc.conv[cc] = fltconv; 
	fmtalloc.index['e'] = cc; 
	fmtalloc.index['f'] = cc; 
	fmtalloc.index['g'] = cc; 
	fmtalloc.index['E'] = cc; 
	fmtalloc.index['G'] = cc; 
1992/1024    
	cc++; 
1999/0819    
*/ 
1992/1024    
                 
1999/0819    
	fmtalloc.conv[cc] = cconv; 
	fmtalloc.index['c'] = cc; 
	fmtalloc.index['C'] = cc; 
1992/1024    
	cc++; 
                 
1999/0819    
/* 
	fmtalloc.conv[cc] = rconv; 
	fmtalloc.index['r'] = cc; 
1992/1024    
	cc++; 
1999/0819    
*/ 
2001/0316    
	fmtalloc.conv[cc] = quotestrconv; 
	fmtalloc.index['q'] = cc; 
	cc++; 
1992/1024    
                 
2001/0316    
	fmtalloc.conv[cc] = quoterunestrconv; 
	fmtalloc.index['Q'] = cc; 
	cc++; 
                 
1999/0819    
	fmtalloc.conv[cc] = sconv; 
	fmtalloc.index['s'] = cc; 
	fmtalloc.index['S'] = cc; 
	cc++; 
                 
	fmtalloc.conv[cc] = percent; 
	fmtalloc.index['%'] = cc; 
	cc++; 
                 
/* 
	fmtalloc.conv[cc] = column; 
	fmtalloc.index['|'] = cc; 
	cc++; 
*/ 
                 
	fmtalloc.convcount = cc; 
1992/1024    
} 
                 
1990/0227    
int 
1996/0214    
fmtinstall(int c, int (*f)(va_list*, Fconv*)) 
1990/0227    
{ 
                 
1999/0819    
	lock(&fmtalloc); 
                 
	if(fmtalloc.convcount <= 0) 
1992/1024    
		initfmt(); 
1999/0819    
	if(c < 0 || c >= MAXFMT){ 
		unlock(&fmtalloc); 
1996/0214    
		return -1; 
1999/0819    
	} 
	if(fmtalloc.convcount >= MAXCONV){ 
		unlock(&fmtalloc); 
1996/0214    
		return -1; 
1999/0819    
	} 
	fmtalloc.conv[fmtalloc.convcount] = f; 
	fmtalloc.index[c] = fmtalloc.convcount; 
	fmtalloc.convcount++; 
                 
	unlock(&fmtalloc); 
1990/0227    
	return 0; 
} 
                 
1999/0819    
static	void 
pchar(Rune c, Fconv *fp) 
{ 
	int n; 
                 
	n = fp->eout - fp->out; 
	if(n > 0) { 
		if(c < Runeself) { 
			*fp->out++ = c; 
			return; 
		} 
		if(n >= UTFmax || n >= runelen(c)) { 
			n = runetochar(fp->out, &c); 
			fp->out += n; 
			return; 
		} 
		fp->eout = fp->out; 
	} 
} 
                 
1990/0227    
char* 
1996/0214    
doprint(char *s, char *es, char *fmt, va_list argp) 
1990/0227    
{ 
1992/1024    
	int n, c; 
	Rune rune; 
	Fconv local; 
1990/0227    
                 
1999/0819    
	if(fmtalloc.convcount <= 0) 
		initfmt(); 
                 
	if(s >= es) 
		return s; 
1992/1024    
	local.out = s; 
1999/0819    
	local.eout = es-1; 
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; 
1999/0819    
	                 
1992/1024    
	default: 
		printcol++; 
		goto common; 
                 
	case '\n': 
		printcol = 0; 
		goto common; 
                 
	case '\t': 
		printcol = (printcol+8) & ~7; 
		goto common; 
                 
	common: 
1999/0819    
		pchar(c, &local); 
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 == '*') { 
1996/0214    
		n = va_arg(argp, int); 
1992/1024    
		if(local.f1 == NONE) 
			local.f1 = n; 
		else 
			local.f2 = n; 
		goto l0; 
1990/0227    
	} 
1992/1024    
	n = 0; 
	if(c >= 0 && c < MAXFMT) 
1999/0819    
		n = fmtalloc.index[c]; 
1992/1024    
	local.chr = c; 
1999/0819    
	n = (*fmtalloc.conv[n])(&argp, &local); 
1992/1024    
	if(n < 0) { 
		local.f3 |= -n; 
		goto l0; 
	} 
1990/0227    
	goto loop; 
} 
                 
int 
1996/0214    
numbconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[IDIGIT]; 
1996/0214    
	int i, f, n, b, ucase; 
1992/1024    
	long v; 
1998/0327    
	vlong vl; 
1990/0227    
                 
1998/0327    
	SET(v); 
	SET(vl); 
                 
1992/1024    
	ucase = 0; 
	b = fp->chr; 
	switch(fp->chr) { 
	case 'u': 
		fp->f3 |= FUNSIGN; 
	case 'd': 
		b = 10; 
		break; 
                 
1999/0819    
	case 'b': 
		b = 2; 
		break; 
                 
1992/1024    
	case 'o': 
		b = 8; 
		break; 
                 
	case 'X': 
		ucase = 1; 
	case 'x': 
		b = 16; 
		break; 
1999/0517    
	case 'p': 
		fp->f3 |= FPOINTER|FUNSIGN; 
		b = 16; 
		break; 
1992/1024    
	} 
                 
1990/0227    
	f = 0; 
1999/0819    
	switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) { 
1998/0327    
	case FVLONG|FLONG: 
		vl = va_arg(*arg, vlong); 
		break; 
                 
	case FUNSIGN|FVLONG|FLONG: 
		vl = va_arg(*arg, uvlong); 
		break; 
                 
1999/0819    
	case FUNSIGN|FPOINTER: 
		v = (ulong)va_arg(*arg, void*); 
		break; 
                 
1990/0227    
	case FLONG: 
1996/0214    
		v = va_arg(*arg, long); 
1990/0227    
		break; 
                 
	case FUNSIGN|FLONG: 
1996/0214    
		v = va_arg(*arg, ulong); 
1990/0227    
		break; 
                 
	default: 
1996/0214    
		v = va_arg(*arg, int); 
1990/0227    
		break; 
                 
	case FUNSIGN: 
1996/0214    
		v = va_arg(*arg, unsigned); 
1990/0227    
		break; 
	} 
1998/0327    
	if(fp->f3 & FVLONG) { 
		if(!(fp->f3 & FUNSIGN) && vl < 0) { 
			vl = -vl; 
			f = 1; 
		} 
	} else { 
		if(!(fp->f3 & FUNSIGN) && v < 0) { 
			v = -v; 
			f = 1; 
		} 
1990/0227    
	} 
1992/1024    
	s[IDIGIT-1] = 0; 
1990/0227    
	for(i = IDIGIT-2;; i--) { 
1998/0327    
		if(fp->f3 & FVLONG) 
			n = (uvlong)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; 
1998/0327    
		if(fp->f3 & FVLONG) 
			vl = (uvlong)vl / b; 
		else 
			v = (ulong)v / b; 
1992/1024    
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2) 
1990/0227    
			continue; 
1998/0327    
		if(fp->f3 & FVLONG) { 
			if(vl <= 0) 
				break; 
			continue; 
		} 
1990/0227    
		if(v <= 0) 
			break; 
	} 
1996/0214    
                 
	if(fp->f3 & FSHARP) { 
		if(b == 8 && s[i] != '0') 
1992/1024    
			s[--i] = '0'; 
		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); 
1996/0214    
	return 0; 
1990/0227    
} 
                 
void 
1992/1024    
Strconv(Rune *s, Fconv *fp) 
2002/0217    
_fmtlock(void) 
1990/0227    
{ 
1999/0819    
	int n, c; 
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) { 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
1990/0227    
			n++; 
		} 
1992/1024    
	} 
	for(;;) { 
		c = *s++; 
		if(c == 0) 
			break; 
		n++; 
		if(fp->f2 == NONE || fp->f2 > 0) { 
1999/0819    
			pchar(c, fp); 
1992/1024    
			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) { 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
1990/0227    
			n++; 
		} 
	} 
2002/0217    
	lock(&fmtl); 
1990/0227    
} 
 
1992/1024    
void 
strconv(char *s, Fconv *fp) 
2002/0217    
_fmtunlock(void) 
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) { 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			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) { 
1999/0819    
			pchar(c, fp); 
1992/1024    
			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) { 
1999/0819    
			pchar(' ', fp); 
1992/1024    
			printcol++; 
			n++; 
		} 
	} 
2002/0217    
	unlock(&fmtl); 
1990/0227    
} 
 
1999/0819    
static int 
noconv(va_list*, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
1990/0227    
                 
1996/0214    
	s[0] = '*'; 
	s[1] = fp->chr; 
	s[2] = '*'; 
	s[3] = 0; 
1992/1024    
	fp->f1 = 0; 
	fp->f2 = NONE; 
	fp->f3 = 0; 
	strconv(s, fp); 
	return 0; 
1990/0227    
} 
                 
1999/0819    
#ifdef NOTDEF 
static int 
rconv(va_list*, Fconv *fp) 
{ 
	char s[ERRLEN]; 
                 
	s[0] = 0; 
	errstr(s); 
	fp->f2 = NONE; 
	strconv(s, fp); 
	return 0; 
} 
#endif 
                 
static int 
1996/0214    
cconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char s[10]; 
	Rune rune; 
1990/0227    
                 
1996/0214    
	rune = va_arg(*arg, int); 
1992/1024    
	if(fp->chr == 'c') 
		rune &= 0xff; 
	s[runetochar(s, &rune)] = 0; 
1990/0227    
                 
1992/1024    
	fp->f2 = NONE; 
	strconv(s, fp); 
1996/0214    
	return 0; 
1990/0227    
} 
                 
1999/0819    
static	int 
1996/0214    
sconv(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1992/1024    
	char *s; 
	Rune *r; 
1990/0227    
                 
1992/1024    
	if(fp->chr == 's') { 
1996/0214    
		s = va_arg(*arg, char*); 
1992/1024    
		if(s == 0) 
			s = "<null>"; 
		strconv(s, fp); 
	} else { 
1996/0214    
		r = va_arg(*arg, Rune*); 
1992/1024    
		if(r == 0) 
			r = L"<null>"; 
		Strconv(r, fp); 
	} 
1996/0214    
	return 0; 
1990/0227    
} 
                 
1999/0819    
static	int 
percent(va_list*, Fconv *fp) 
1990/0227    
{ 
1999/0819    
	pchar('%', fp); 
1996/0214    
	printcol++; 
1992/1024    
	return 0; 
1990/0227    
} 
                 
1999/0819    
#ifdef NOTDEF 
static	int 
column(va_list *arg, Fconv *fp) 
1990/0227    
{ 
1999/0819    
	int col, pc; 
1996/0214    
                 
1999/0819    
	col = va_arg(*arg, int); 
	while(printcol < col) { 
		pc = (printcol+8) & ~7; 
		if(pc <= col) { 
			pchar('\t', fp); 
			printcol = pc; 
		} else { 
			pchar(' ', fp); 
			printcol++; 
		} 
	} 
	return 0; 
} 
#endif 
1990/0227    
                 
1999/0819    
static	int 
flags(va_list*, Fconv *fp) 
{ 
	int f; 
                 
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 'l': 
		f = FLONG; 
		if(fp->f3 & FLONG) 
			f = FVLONG; 
		break; 
1990/0227    
                 
1992/1024    
	case 'u': 
		f = FUNSIGN; 
		break; 
	} 
	return -f; 
2001/0316    
} 
                 
static	void 
qchar(Rune c, Fconv *fp, int hold, int *closed) 
{ 
	int n; 
                 
	if(*closed) 
		return; 
	n = fp->eout - fp->out - hold; 
	if(n > 0) { 
		if(c < Runeself) { 
			*fp->out++ = c; 
			return; 
		} 
		if(n >= UTFmax || n >= runelen(c)) { 
			n = runetochar(fp->out, &c); 
			fp->out += n; 
			return; 
		} 
	} 
	if(hold) 
		*closed = 1; 
	else 
		fp->eout = fp->out; 
} 
                 
static int 
needsquotes(char *s, int *quotelenp) 
{ 
	char *t; 
	int nextra, ok, w; 
	Rune r; 
                 
2001/0819    
	if(*s == '\0') 
		return 1; 
2001/0316    
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t+=w){ 
		w = chartorune(&r, t); 
		if(r <= L' ') 
			ok = 0; 
		else if(r == L'\''){ 
			ok = 0; 
			nextra++;	/* ' becomes '' */ 
		} 
	} 
                 
	if(ok){ 
		*quotelenp = t-s; 
		return 0; 
	} 
	*quotelenp = 1+ t-s + nextra +1; 
	return 1; 
} 
                 
static int 
runeneedsquotes(Rune *s, int *quotelenp) 
{ 
	Rune *t; 
	int nextra, ok; 
	Rune r; 
                 
2001/0819    
	if(*s == L'\0') 
		return 1; 
2001/0316    
	nextra = 0; 
	ok = 1; 
	for(t=s; *t; t++){ 
		r = *t; 
		if(r <= L' ') 
			ok = 0; 
		else if(r == L'\''){ 
			ok = 0; 
			nextra++;	/* ' becomes '' */ 
		} 
	} 
                 
	if(ok){ 
		*quotelenp = t-s; 
		return 0; 
	} 
	*quotelenp = 1+ t-s + nextra +1; 
	return 1; 
} 
                 
void 
qadv(Rune c, Fconv *fp, int hold, int *np, int *closedp) 
{ 
	if(fp->f2 == NONE || fp->f2 > 0) { 
		qchar(c, fp, hold, closedp); 
		(*np)++; 
		if(fp->f2 != NONE) 
			fp->f2--; 
		switch(c) { 
		default: 
			printcol++; 
			break; 
		case '\n': 
			printcol = 0; 
			break; 
		case '\t': 
			printcol = (printcol+8) & ~7; 
			break; 
		} 
	} 
} 
                 
static int 
qstrconv(char *s, Rune *r, int quotelen, Fconv *fp) 
{ 
	int closed, i, n, c; 
	Rune rune; 
                 
	closed = 0; 
	if(fp->f3 & FMINUS) 
		fp->f1 = -fp->f1; 
	n = 0; 
	if(fp->f1 != NONE && fp->f1 >= 0) { 
		n = quotelen; 
		while(n < fp->f1) { 
			qchar(' ', fp, 0, &closed); 
			printcol++; 
			n++; 
		} 
	} 
                 
	if(fp->eout - fp->out < 2)	/* 2 because need at least '' */ 
		return 0; 
                 
	qchar('\'', fp, 0, &closed); 
	n++; 
                 
	for(;;) { 
		if(s){ 
			c = *s & 0xff; 
			if(c >= Runeself) { 
				i = chartorune(&rune, s); 
				s += i; 
				c = rune; 
			} else 
				s++; 
		}else 
			c = *r++; 
                 
		if(c == 0) 
			break; 
		if(c == '\'') 
			qadv(c, fp, 2, &n, &closed);	/* '' plus closing quote */ 
		qadv(c, fp, 1, &n, &closed); 
	} 
	closed = 0;	/* there will always be room for closing quote */ 
	qchar('\'', fp, 0, &closed); 
	n++; 
                 
	if(fp->f1 != NONE && fp->f1 < 0) { 
		fp->f1 = -fp->f1; 
		while(n < fp->f1) { 
			qchar(' ', fp, 0, &closed); 
			printcol++; 
			n++; 
		} 
	} 
                 
	return 0; 
                 
} 
                 
int 
quotestrconv(va_list *arg, Fconv *fp) 
2002/0217    
_efgfmt(Fmt*) 
2001/0316    
{ 
	char *s; 
	int quotelen; 
                 
	s = va_arg(*arg, char*); 
	if(s == nil){ 
		strconv("<null>", fp); 
		return 0; 
	} 
                 
	if(needsquotes(s, "elen) == 0){ 
		strconv(s, fp); 
		va_end(arg); 
		return 0; 
	} 
                 
	qstrconv(s, nil, quotelen, fp); 
                 
	va_end(arg); 
	return 0; 
2002/0217    
	return -1; 
2001/0316    
} 
                 
int 
quoterunestrconv(va_list *arg, Fconv *fp) 
{ 
	Rune *r; 
	int quotelen; 
                 
	r = va_arg(*arg, Rune*); 
	if(r == nil){ 
		strconv("<null>", fp); 
		return 0; 
	} 
                 
	if(runeneedsquotes(r, "elen) == 0){ 
		Strconv(r, fp); 
		va_end(arg); 
		return 0; 
	} 
                 
	qstrconv(nil, r, quotelen, fp); 
                 
	va_end(arg); 
	return 0; 
} 
                 
void 
quotefmtinstall(void) 
{ 
	fmtinstall('q', quotestrconv); 
	fmtinstall('Q', quoterunestrconv); 
1990/0227    
} 
1999/0819    
                 
#ifdef NOTDEF 
int 
fltconv(va_list *arg, Fconv *fp) 
{ 
	char s1[FDIGIT+10], s2[FDIGIT+10]; 
	double f, g, h; 
	int e, d, i, n, s; 
	int c1, c2, c3, f2, ucase; 
                 
	f2 = fp->f2; 
	fp->f2 = NONE; 
                 
	f = va_arg(*arg, double); 
	if(isNaN(f)){ 
		strconv("NaN", fp); 
		return 0; 
	} 
	if(isInf(f, 1)){ 
		strconv("+Inf", fp); 
		return 0; 
	} 
	if(isInf(f, -1)){ 
		strconv("-Inf", fp); 
		return 0; 
	} 
	s = 0; 
	if(f < 0) { 
		f = -f; 
		s++; 
	} 
	ucase = 0; 
	if(fp->chr >= 'A' && fp->chr <= 'Z') { 
		ucase = 1; 
		fp->chr += 'a'-'A'; 
	} 
                 
loop: 
	e = 0; 
	if(f != 0) { 
		frexp(f, &e); 
		e = e * .30103; 
		d = e/2; 
		h = f * pow10(-d);		/* 10**-e in 2 parts */ 
		g = h * pow10(d-e); 
		while(g < 1) { 
			e--; 
			g = h * pow10(d-e); 
		} 
		while(g >= 10) { 
			e++; 
			g = h * pow10(d-e); 
		} 
	} 
	if(f2 == NONE) 
		f2 = FDEFLT; 
	if(fp->chr == 'g' && f2 > 0) 
		f2--; 
	if(f2 > FDIGIT) 
		f2 = FDIGIT; 
                 
	/* 
	 * n is number of digits to convert 
	 * 1 before, f2 after, 1 extra for rounding 
	 */ 
	n = f2 + 2; 
	if(fp->chr == 'f') { 
                 
		/* 
		 * e+1 before, f2 after, 1 extra 
		 */ 
		n += e; 
		if(n <= 0) 
			n = 1; 
	} 
	if(n >= FDIGIT+2) { 
		if(fp->chr == 'e') 
			f2 = -1; 
		fp->chr = 'e'; 
		goto loop; 
	} 
                 
	/* 
	 * convert n digits 
	 */ 
	g = f; 
	if(e < 0) { 
		if(e < -55) { 
			g *= pow10(50); 
			g *= pow10(-e-51); 
		} else 
			g *= pow10(-e-1); 
	} 
	for(i=0; i<n; i++) { 
		d = e-i; 
		if(d >= 0) { 
			h = pow10(d); 
			d = floor(g/h); 
			g -= d * h; 
		} else { 
			g *= 10; 
			d = floor(g); 
			g -= d; 
		} 
		s1[i+1] = d + '0'; 
	} 
                 
	/* 
	 * round by adding .5 into extra digit 
	 */ 
	d = 5; 
	for(i=n-1; i>=0; i--) { 
		s1[i+1] += d; 
		d = 0; 
		if(s1[i+1] > '9') { 
			s1[i+1] -= 10; 
			d++; 
		} 
	} 
	i = 1; 
	if(d) { 
		s1[0] = '1'; 
		e++; 
		i = 0; 
	} 
                 
	/* 
	 * copy into final place 
	 * c1 digits of leading '0' 
	 * c2 digits from conversion 
	 * c3 digits after '.' 
	 */ 
	d = 0; 
	if(s) 
		s2[d++] = '-'; 
	else 
	if(fp->f3 & FPLUS) 
		s2[d++] = '+'; 
	c1 = 0; 
	c2 = f2 + 1; 
	c3 = f2; 
	if(fp->chr == 'g') 
	if(e >= -5 && e <= f2) { 
		c1 = -e - 1; 
		if(c1 < 0) 
			c1 = 0; 
		c3 = f2 - e; 
		fp->chr = 'h'; 
	} 
	if(fp->chr == 'f') { 
		c1 = -e; 
		if(c1 < 0) 
			c1 = 0; 
		if(c1 > f2) 
			c1 = c2; 
		c2 += e; 
		if(c2 < 0) 
			c2 = 0; 
	} 
	while(c1 > 0) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
		s2[d++] = '0'; 
		c1--; 
	} 
	while(c2 > 0) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
		s2[d++] = s1[i++]; 
		c2--; 
	} 
                 
	/* 
	 * strip trailing '0' on g conv 
	 */ 
	if(fp->f3 & FSHARP) { 
		if(c1+c2 == c3) 
			s2[d++] = '.'; 
	} else 
	if(fp->chr == 'g' || fp->chr == 'h') { 
		for(n=d-1; n>=0; n--) 
			if(s2[n] != '0') 
				break; 
		for(i=n; i>=0; i--) 
			if(s2[i] == '.') { 
				d = n; 
				if(i != n) 
					d++; 
				break; 
			} 
	} 
	if(fp->chr == 'e' || fp->chr == 'g') { 
		if(ucase) 
			s2[d++] = 'E'; 
		else 
			s2[d++] = 'e'; 
		c1 = e; 
		if(c1 < 0) { 
			s2[d++] = '-'; 
			c1 = -c1; 
		} else 
			s2[d++] = '+'; 
		if(c1 >= 100) { 
			s2[d++] = c1/100 + '0'; 
			c1 = c1%100; 
		} 
		s2[d++] = c1/10 + '0'; 
		s2[d++] = c1%10 + '0'; 
	} 
	s2[d] = 0; 
	strconv(s2, fp); 
	return 0; 
} 
#endif 


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