Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/print.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/print.c 1990/0227
## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/print.c
0a
#include	"u.h"
#include	"lib.h"

#define	PTR	sizeof(char*)
#define	SHORT	sizeof(int)
#define	INT	sizeof(int)
#define	LONG	sizeof(long)
#define	IDIGIT	30
#define	MAXCON	30

static	int	convcount  = { 10 };

#define	PUT(o, c)	if((o)->p < (o)->ep) *(o)->p++ = c

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*);

static
int	(*fmtconv[MAXCON])(Op*) =
{
	noconv,
	cconv, dconv, hconv, lconv,
	oconv, sconv, uconv, xconv,
	percent,
};
static
char	fmtindex[128] =
{
	['c'] 1,
	['d'] 2,
	['h'] 3,
	['l'] 4,
	['o'] 5,
	['s'] 6,
	['u'] 7,
	['x'] 8,
	['%'] 9,
};

int
fmtinstall(char c, int (*f)(Op*))
{

	c &= 0177;
	if(fmtindex[c] == 0) {
		if(convcount >= MAXCON)
			return 1;
		fmtindex[c] = convcount++;
	}
	fmtconv[fmtindex[c]] = f;
	return 0;
}

char*
donprint(char *p, char *ep, char *fmt, void *argp)
{
	int sf1, c;
	Op o;

	o.p = p;
	o.ep = ep;
	o.argp = argp;

loop:
	c = *fmt++;
	if(c != '%') {
		if(c == 0) {
			if(o.p < o.ep)
				*o.p = 0;
			return o.p;
		}
		PUT(&o, c);
		goto loop;
	}
	o.f1 = 0;
	o.f2 = -1;
	o.f3 = 0;
	c = *fmt++;
	sf1 = 0;
	if(c == '-') {
		sf1 = 1;
		c = *fmt++;
	}
	while(c >= '0' && c <= '9') {
		o.f1 = o.f1*10 + c-'0';
		c = *fmt++;
	}
	if(sf1)
		o.f1 = -o.f1;
	if(c != '.')
		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;
	}
	o.argp = (char*)o.argp + c;
	goto loop;
}

int
numbconv(Op *op, int base)
{
	char b[IDIGIT];
	int i, f, n, r;
	long v;
	short h;

	f = 0;
	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
	case FLONG:
		v = *(long*)op->argp;
		r = LONG;
		break;

	case FUNSIGN|FLONG:
		v = *(unsigned long*)op->argp;
		r = LONG;
		break;

	case FSHORT:
		h = *(int*)op->argp;
		v = h;
		r = SHORT;
		break;

	case FUNSIGN|FSHORT:
		h = *(int*)op->argp;
		v = (unsigned short)h;
		r = SHORT;
		break;

	default:
		v = *(int*)op->argp;
		r = INT;
		break;

	case FUNSIGN:
		v = *(unsigned*)op->argp;
		r = INT;
		break;
	}
	if(!(op->f3 & FUNSIGN) && v < 0) {
		v = -v;
		f = 1;
	}
	b[IDIGIT-1] = 0;
	for(i = IDIGIT-2;; i--) {
		n = (unsigned long)v % base;
		n += '0';
		if(n > '9')
			n += 'a' - ('9'+1);
		b[i] = n;
		if(i < 2)
			break;
		v = (unsigned long)v / base;
		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
			continue;
		if(v <= 0)
			break;
	}
sout:
	if(f)
		b[--i] = '-';
	strconv(b+i, op, op->f1, -1);
	return r;
}

void
strconv(char *o, Op *op, int f1, int f2)
{
	int n, c;
	char *p;

	n = strlen(o);
	if(f1 >= 0)
		while(n < f1) {
			PUT(op, ' ');
			n++;
		}
	for(p=o; c = *p++;)
		if(f2 != 0) {
			PUT(op, c);
			f2--;
		}
	if(f1 < 0) {
		f1 = -f1;
		while(n < f1) {
			PUT(op, ' ');
			n++;
		}
	}
}

static	int
noconv(Op *op)
{

	strconv("***", op, 0, -1);
	return 0;
}

static	int
cconv(Op *op)
{
	char b[2];

	b[0] = *(int*)op->argp;
	b[1] = 0;
	strconv(b, op, op->f1, -1);
	return INT;
}

static	int
dconv(Op *op)
{

	return numbconv(op, 10);
}

static	int
hconv(Op *op)
{
	return -FSHORT;
}

static	int
lconv(Op *op)
{

	return -FLONG;
}

static	int
oconv(Op *op)
{

	return numbconv(op, 8);
}

static	int
sconv(Op *op)
{

	strconv(*(char**)op->argp, op, op->f1, op->f2);
	return PTR;
}

static	int
uconv(Op *op)
{
	return -FUNSIGN;
}

static	int
xconv(Op *op)
{

	return numbconv(op, 16);
}

static	int
percent(Op *op)
{

	PUT(op, '%');
	return 0;
}
.
## diffname port/print.c 1990/06111
## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/print.c /n/bootesdump/1990/06111/sys/src/9/mips/print.c
63c
doprint(char *p, char *ep, char *fmt, void *argp)
.
## diffname port/print.c 1991/1115
## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/print.c /n/bootesdump/1991/1115/sys/src/9/port/print.c
270a

	USED(op);
.
249a
	USED(op);
.
242a

	USED(op);
.
## diffname port/print.c 1992/0321
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/print.c /n/bootesdump/1992/0321/sys/src/9/port/print.c
2c
#include	"../port/lib.h"
.
## diffname port/print.c 1992/1024
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/print.c /n/bootesdump/1992/1024/sys/src/9/port/print.c
290,291c
	case 'u':
		f = FUNSIGN;
		break;
	}
	return -f;
.
286,288c
	case 'l':
		f = FLONG;
		if(fp->f3 & FLONG)
			f = FVLONG;
		break;
.
283,284c
	case 'h':
		f = FSHORT;
		break;
.
279,281c
	case '#':
		f = FSHARP;
		break;
.
275,277c
	case '-':
		f = FMINUS;
		break;
.
271,273c
	f = 0;
	switch(fp->chr) {
	case '+':
		f = FPLUS;
		break;
.
267,269c
	USED(o);
.
265a
	int f;
.
263,264c
static
int
flags(void *o, Fconv *fp)
.
260c
	USED(o);
	if(fp->out < fp->eout)
		*fp->out++ = '%';
	return 0;
.
256,257c
static
int
percent(void *o, Fconv *fp)
.
252,253c
	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;
.
250a
	char *s;
	Rune *r;
.
248,249c
static
int
sconv(void *o, Fconv *fp)
.
240,245c
	fp->f2 = NONE;
	strconv(s, fp);
	return INT;
.
237,238c
	rune = *(int*)o;
	if(fp->chr == 'c')
		rune &= 0xff;
	s[runetochar(s, &rune)] = 0;
.
235a
	char s[10];
	Rune rune;
.
233,234c
static
int
cconv(void *o, Fconv *fp)
.
227,230c
	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;
.
225c
	int n;
	char s[10];
.
222,223c
static
int
noconv(void *o, Fconv *fp)
.
218,219c
	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++;
		}
	}
.
216a
	int n, c, i;
	Rune rune;
.
214,215c
void
strconv(char *s, Fconv *fp)
.
205,208c
	}
	if(fp->f1 != NONE && fp->f1 < 0) {
		fp->f1 = -fp->f1;
		while(n < fp->f1) {
			if(fp->out < fp->eout)
				*fp->out++ = ' ';
			printcol++;
.
200,203c
	}
	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;
			}
.
194,197c
	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++;
.
191,192c
	int n, c, i;
	Rune rune;
.
189c
Strconv(Rune *s, Fconv *fp)
.
183,184c
		s[--i] = '-';
	fp->f2 = NONE;
	strconv(s+i, fp);
.
181c
	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';
		}
	}
.
177a
		if(fp->f3 & FVLONG)
			if(vl <= 0)
				break;
.
175,176c
		if(fp->f3 & FVLONG)
			vl = vl / b;
		else
			v = (ulong)v / b;
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
.
172c
			if(ucase)
				n += 'A'-'a';
		}
		s[i] = n;
.
170c
		if(n > '9') {
.
168c
		if(fp->f3 & FVLONG)
			n = vl % b;
		else
			n = (ulong)v % b;
.
166c
	s[IDIGIT-1] = 0;
.
162c
	if(!(fp->f3 & FUNSIGN) && v < 0) {
.
158c
		v = *(unsigned*)o;
.
153c
		v = *(int*)o;
.
147,148c
		h = *(int*)o;
		v = (ushort)h;
.
141c
		h = *(int*)o;
.
136c
		v = *(ulong*)o;
.
131c
		v = *(long*)o;
.
129c
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
	case FVLONG|FLONG:
		vl = *(vlong*)o;
		r = VLONG;
		break;

.
127a
	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;
	}

.
126a
	long v;
	vlong vl;
.
123,125c
	char s[IDIGIT];
	int i, f, n, r, b, ucase;
.
121c
numbconv(void *o, Fconv *fp)
.
116c
	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;
.
107,114c
	if(c == '*') {
		n = *(int*)argp;
		argp = (char*)argp + INT;
		if(local.f1 == NONE)
			local.f1 = n;
		else
			local.f2 = n;
		goto l0;
.
100,105d
96,98c
	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;
.
92,94c
	if(c == '.') {
		if(local.f1 == NONE)
			local.f1 = 0;
		local.f2 = 0;
		goto l0;
.
83,90c
	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;
.
81a

	case '%':
		break;
.
73,80c
	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;
.
68,70c
	local.out = s;
	local.eout = es-4;		/* room for multi-byte character and 0 */
.
65,66c
	int n, c;
	Rune rune;
	Fconv local;
.
63c
doprint(char *s, char *es, char *fmt, void *argp)
.
52,58c
	if(convcount == 0)
		initfmt();
	if(c < 0 || c >= MAXFMT)
		return 1;
	if(convcount >= MAXCONV)
		return 1;
	fmtconv[convcount] = f;
	fmtindex[c] = convcount;
	convcount++;
.
49c
fmtinstall(int c, int (*f)(void*, Fconv*))
.
47a
	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;
}

.
37,46c
	int cc;
.
35c
void
initfmt(void)
.
33a

.
29,32c
	noconv
.
27c
int	(*fmtconv[MAXCONV])(void*, Fconv*) =
.
25a
static	int	cconv(void*, Fconv*);
static	int	sconv(void*, Fconv*);
static	int	percent(void*, Fconv*);

int	numbconv(void*, Fconv*);

.
15,24c
static	int	noconv(void*, Fconv*);
static	int	flags(void*, Fconv*);
.
13c
static	int	convcount;
static	char	fmtindex[MAXFMT];
.
11c
int	printcol;
.
8,9c
#define	VLONG	sizeof(vlong)
.
3a
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),
};

.
## diffname port/print.c 1995/0804
## diff -e /n/bootesdump/1992/1024/sys/src/9/port/print.c /n/fornaxdump/1995/0804/sys/src/brazil/port/print.c
542,543d
539c
flags(void*, Fconv *fp)
.
531d
528c
percent(void*, Fconv *fp)
.
## diffname port/print.c 1996/0214
## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/print.c /n/fornaxdump/1996/0214/sys/src/brazil/port/print.c
540a

	USED(arg);
.
538c
flags(va_list *arg, Fconv *fp)
.
532a
	printcol++;
.
530a
	USED(arg);
.
528c
percent(va_list *arg, Fconv *fp)
.
523c
	return 0;
.
518c
		r = va_arg(*arg, Rune*);
.
513c
		s = va_arg(*arg, char*);
.
507c
sconv(va_list *arg, Fconv *fp)
.
502c
	return 0;
.
495c
	rune = va_arg(*arg, int);
.
490c
cconv(va_list *arg, Fconv *fp)
.
480c
	s[0] = '*';
	s[1] = fp->chr;
	s[2] = '*';
	s[3] = 0;
.
478c
		return (*fmtconv[n])(arg, fp);
.
468c
noconv(va_list *arg, Fconv *fp)
.
342c
	return 0;
.
329d
325,327c

	if(fp->f3 & FSHARP) {
		if(b == 8 && s[i] != '0')
.
319,321d
313,316c
		v = (ulong)v / b;
.
300,303c
		n = (ulong)v % b;
.
290,291c
		v = va_arg(*arg, unsigned);
.
285,286c
		v = va_arg(*arg, int);
.
281d
279c
		h = va_arg(*arg, int);
.
275d
273c
		h = va_arg(*arg, int);
.
268,269c
		v = va_arg(*arg, ulong);
.
263,264c
		v = va_arg(*arg, long);
.
256,261c
	switch(fp->f3 & (FLONG|FSHORT|FUNSIGN)) {
.
232,234d
230d
227c
	int i, f, n, b, ucase;
.
224c
numbconv(va_list *arg, Fconv *fp)
.
219d
214c
	n = (*fmtconv[n])(&argp, &local);
.
202,203c
		n = va_arg(argp, int);
.
147c
				n = runetochar(local.out, &rune);
.
116c
	local.eout = es-UTFmax-1;
.
109c
doprint(char *s, char *es, char *fmt, va_list argp)
.
101c
		return -1;
.
99c
		return -1;
.
93c
fmtinstall(int c, int (*f)(va_list*, Fconv*))
.
44c
int	(*fmtconv[MAXCONV])(va_list*, Fconv*) =
.
41c
int	numbconv(va_list*, Fconv*);
.
37,39c
static	int	cconv(va_list*, Fconv*);
static	int	sconv(va_list*, Fconv*);
static	int	percent(va_list*, Fconv*);
.
34,35c
static	int	noconv(va_list*, Fconv*);
static	int	flags(va_list*, Fconv*);
.
23,28d
14,20c
	FPLUS	= 1<<0,
	FMINUS	= 1<<1,
	FSHARP	= 1<<2,
	FLONG	= 1<<3,
	FSHORT	= 1<<4,
	FUNSIGN	= 1<<5,
	FVLONG	= 1<<6,
.
## diffname port/print.c 1998/0327
## diff -e /n/fornaxdump/1996/0214/sys/src/brazil/port/print.c /n/emeliedump/1998/0327/sys/src/brazil/port/print.c
289a
		if(fp->f3 & FVLONG) {
			if(vl <= 0)
				break;
			continue;
		}
.
287c
		if(fp->f3 & FVLONG)
			vl = (uvlong)vl / b;
		else
			v = (ulong)v / b;
.
277c
		if(fp->f3 & FVLONG)
			n = (uvlong)vl % b;
		else
			n = (ulong)v % b;
.
271,273c
	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;
		}
.
244c
	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;

.
222a
	SET(v);
	SET(vl);

.
221a
	vlong vl;
.
## diffname port/print.c 1998/0512
## diff -e /n/emeliedump/1998/0327/sys/src/brazil/port/print.c /n/emeliedump/1998/0512/sys/src/brazil/port/print.c
124c

.
## diffname port/print.c 1999/0517
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/print.c /n/emeliedump/1999/0517/sys/src/brazil/port/print.c
272a
		break;

	case FUNSIGN|FPOINTER:
		v = (ulong)va_arg(*arg, void*);
.
244a
	case 'p':
		fp->f3 |= FPOINTER|FUNSIGN;
		b = 16;
		break;
.
66a
	fmtindex['p'] = cc;
.
20a
	FPOINTER	= 1<<7,
.
## diffname port/print.c 1999/0810
## diff -e /n/emeliedump/1999/0517/sys/src/brazil/port/print.c /n/emeliedump/1999/0810/sys/src/brazil/port/print.c
6d
## diffname port/print.c 1999/0819
## diff -e /n/emeliedump/1999/0810/sys/src/brazil/port/print.c /n/emeliedump/1999/0819/sys/src/brazil/port/print.c
584a

#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
.
569,572d
554a
static	int
flags(va_list*, Fconv *fp)
{
	int f;

.
553c
	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
.
551c
	int col, pc;
.
547,549c
#ifdef NOTDEF
static	int
column(va_list *arg, Fconv *fp)
.
539,542c
	pchar('%', fp);
.
535,537c
static	int
percent(va_list*, Fconv *fp)
.
514,515c
static	int
.
497,498c
#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
.
479,485d
476d
472,474c
static int
noconv(va_list*, Fconv *fp)
.
464,465c
			pchar(' ', fp);
.
439,445c
			pchar(c, fp);
.
421,422c
			pchar(' ', fp);
.
401,402c
			pchar(' ', fp);
.
376,382c
			pchar(c, fp);
.
364,365c
			pchar(' ', fp);
.
354,355c
	int n, c;
.
270,283d
261a
	case FUNSIGN|FPOINTER:
		v = (ulong)va_arg(*arg, void*);
		break;

.
253c
	switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) {
.
236a
	case 'b':
		b = 2;
		break;

.
221d
208c
	n = (*fmtalloc.conv[n])(&argp, &local);
.
206c
		n = fmtalloc.index[c];
.
139,145c
		pchar(c, &local);
.
125c
	
.
111c
	local.eout = es-1;
.
109a
	if(fmtalloc.convcount <= 0)
		initfmt();

	if(s >= es)
		return s;
.
102a
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;
	}
}

.
97,99c
	}
	fmtalloc.conv[fmtalloc.convcount] = f;
	fmtalloc.index[c] = fmtalloc.convcount;
	fmtalloc.convcount++;

	unlock(&fmtalloc);
.
95c
	}
	if(fmtalloc.convcount >= MAXCONV){
		unlock(&fmtalloc);
.
93c
	if(c < 0 || c >= MAXFMT){
		unlock(&fmtalloc);
.
91c
	lock(&fmtalloc);

	if(fmtalloc.convcount <= 0)
.
84c
	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;
.
82a
*/
.
80,81c
/*
	fmtalloc.conv[cc] = rconv;
	fmtalloc.index['r'] = cc;
.
75,77c
	fmtalloc.conv[cc] = cconv;
	fmtalloc.index['c'] = cc;
	fmtalloc.index['C'] = cc;
.
73a
*/
.
70,72c
/*
	fmtalloc.conv[cc] = fltconv;
	fmtalloc.index['e'] = cc;
	fmtalloc.index['f'] = cc;
	fmtalloc.index['g'] = cc;
	fmtalloc.index['E'] = cc;
	fmtalloc.index['G'] = cc;
.
62,67c
	fmtalloc.conv[cc] = numbconv;
	fmtalloc.index['d'] = cc;
	fmtalloc.index['o'] = cc;
	fmtalloc.index['x'] = cc;
	fmtalloc.index['X'] = cc;
	fmtalloc.index['p'] = cc;
.
53,59c
	fmtalloc.conv[cc] = flags;
	fmtalloc.index['+'] = cc;
	fmtalloc.index['-'] = cc;
	fmtalloc.index['#'] = cc;
	fmtalloc.index['l'] = cc;
	fmtalloc.index['u'] = cc;
.
50c
	fmtalloc.conv[cc] = noconv;
.
43,44c
static	void
.
37,41d
35c
extern	int	numbconv(va_list*, Fconv*);
/* extern	int	fltconv(va_list*, Fconv*); */
.
33a
/* static	int	column(va_list*, Fconv*); */
.
31a
/* static	int	rconv(va_list*, Fconv*); */
.
25,26c
static struct
{
	Lock;
	int	convcount;
	char	index[MAXFMT];
	int	(*conv[MAXCONV])(va_list*, Fconv*);
} fmtalloc;
.
20c
	FPOINTER= 1<<7,
.
17d
2a
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
.
## diffname port/print.c 2001/0316
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/port/print.c /n/emeliedump/2001/0316/sys/src/9/port/print.c
624a
}

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, &quotelen) == 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, &quotelen) == 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);
.
93a
	fmtalloc.conv[cc] = quoterunestrconv;
	fmtalloc.index['Q'] = cc;
	cc++;

.
92a
	fmtalloc.conv[cc] = quotestrconv;
	fmtalloc.index['q'] = cc;
	cc++;
.
45a
extern	int	quotestrconv(va_list*, Fconv*);
extern	int	quoterunestrconv(va_list*, Fconv*);
.
## diffname port/print.c 2001/0819
## diff -e /n/emeliedump/2001/0316/sys/src/9/port/print.c /n/emeliedump/2001/0819/sys/src/9/port/print.c
694a
	if(*s == L'\0')
		return 1;
.
667a
	if(*s == '\0')
		return 1;
.
## diffname port/print.c 2002/0217
## diff -e /n/emeliedump/2001/0819/sys/src/9/port/print.c /n/emeliedump/2002/0217/sys/src/9/port/print.c
824,1068d
804,822c
	return -1;
.
802c
_efgfmt(Fmt*)
.
509,800d
457,506c
	unlock(&fmtl);
.
455c
_fmtunlock(void)
.
408,451c
	lock(&fmtl);
.
406c
_fmtlock(void)
.
16,404d
7,14c
static Lock fmtl;
.
1,5c
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].