~kris/9p

9hist

f6df1313806917eba9a321b8d63beaf7db23280e — David du Colombier 24 years ago c08e139
Plan 9 from Bell Labs 2002-02-17
M alphapc/main.c => alphapc/main.c +1 -0
@@ 82,6 82,7 @@ main(void)
	printinit();
	kbdinit();
	i8250console();
	quotefmtinstall();
	print("\nPlan 9\n");

	cpuidprint();

M alphapc/sd53c8xx.c => alphapc/sd53c8xx.c +2 -2
@@ 337,7 337,7 @@ intrprint(char *format, ...)
{
	if (debuglast == 0)
		debuglast = debugbuf;
	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
}

static void


@@ 370,7 370,7 @@ oprint(char *format, ...)
	s = splhi();
	if (debuglast == 0)
		debuglast = debugbuf;
	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	splx(s);
	iflush();	
}

M bitsy/main.c => bitsy/main.c +1 -0
@@ 29,6 29,7 @@ main(void)
	active.machs = 1;

	rs232power(1);
	quotefmtinstall();
	iprint("\nPlan 9 bitsy kernel\n");
	confinit();
	xinit();

M bitsy/sdata.c => bitsy/sdata.c +1 -1
@@ 314,7 314,7 @@ atadebug(int cmdport, int ctlport, char* fmt, ...)
	}

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	if(cmdport){

M boot/boot.c => boot/boot.c +2 -5
@@ 19,16 19,13 @@ static void	swapproc(void);
static Method	*rootserver(char*);

static int
rconv(va_list *arg, Fconv *fp)
rconv(Fmt* fp)
{
	char s[ERRMAX];

	USED(arg);

	s[0] = '\0';
	errstr(s, sizeof s);
	strconv(s, fp);
	return 0;
	return fmtstrcpy(fp, s);
}

void

M boot/bootip.c => boot/bootip.c +3 -3
@@ 21,9 21,9 @@ configip(void)
	char **arg;
	char buf[32];
	
	fmtinstall('I', eipconv);
	fmtinstall('M', eipconv);
	fmtinstall('E', eipconv);
	fmtinstall('I', eipfmt);
	fmtinstall('M', eipfmt);
	fmtinstall('E', eipfmt);

	arg = malloc((bargc+1) * sizeof(char*));
	if(arg == nil)

M ip/devip.c => ip/devip.c +5 -5
@@ 260,11 260,11 @@ ipreset(void)
	nullmediumlink();
	pktmediumlink();

	fmtinstall('i', eipconv);
	fmtinstall('I', eipconv);
	fmtinstall('E', eipconv);
	fmtinstall('V', eipconv);
	fmtinstall('M', eipconv);
	fmtinstall('i', eipfmt);
	fmtinstall('I', eipfmt);
	fmtinstall('E', eipfmt);
	fmtinstall('V', eipfmt);
	fmtinstall('M', eipfmt);
}

static Fs*

M ip/ip.h => ip/ip.h +1 -1
@@ 478,7 478,7 @@ extern uchar*	defmask(uchar*);
extern int	isv4(uchar*);
extern void	v4tov6(uchar *v6, uchar *v4);
extern int	v6tov4(uchar *v4, uchar *v6);
extern int	eipconv(va_list *arg, Fconv *f);
extern int	eipfmt(Fmt*);

#define	ipcmp(x, y) memcmp(x, y, IPaddrlen)
#define	ipmove(x, y) memmove(x, y, IPaddrlen)

M ip/ipaux.c => ip/ipaux.c +42 -44
@@ 122,9 122,9 @@ static uchar prefixvals[256] =
};

int
eipconv(va_list *arg, Fconv *f)
eipfmt(Fmt *f)
{
	char buf[8*5];
	char buf[5*8];
	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
	static char *ifmt = "%d.%d.%d.%d";
	uchar *p, ip[16];


@@ 132,56 132,57 @@ eipconv(va_list *arg, Fconv *f)
	ushort s;
	int i, j, n, eln, eli;

	switch(f->chr) {
	switch(f->r) {
	case 'E':		/* Ethernet address */
		p = va_arg(*arg, uchar*);
		sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
		break;
		p = va_arg(f->args, uchar*);
		return fmtit(f, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);

	case 'I':		/* Ip address */
		p = va_arg(*arg, uchar*);
		p = va_arg(f->args, uchar*);
common:
		if(memcmp(p, v4prefix, 12) == 0)
			sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
		else {
			/* find longest elision */
			eln = eli = -1;
			for(i = 0; i < 16; i += 2){
				for(j = i; j < 16; j += 2)
					if(p[j] != 0 || p[j+1] != 0)
						break;
				if(j > i && j - i > eln){
					eli = i;
					eln = j - i;
				}
			return fmtit(f, ifmt, p[12], p[13], p[14], p[15]);

		/* find longest elision */
		eln = eli = -1;
		for(i = 0; i < 16; i += 2){
			for(j = i; j < 16; j += 2)
				if(p[j] != 0 || p[j+1] != 0)
					break;
			if(j > i && j - i > eln){
				eli = i;
				eln = j - i;
			}
		}

			/* print with possible elision */
			n = 0;
			for(i = 0; i < 16; i += 2){
				if(i == eli){
					n += sprint(buf+n, "::");
					i += eln;
					if(i >= 16)
						break;
				} else if(i != 0)
					n += sprint(buf+n, ":");
				s = (p[i]<<8) + p[i+1];
				n += sprint(buf+n, "%ux", s);
			}
		/* print with possible elision */
		n = 0;
		for(i = 0; i < 16; i += 2){
			if(i == eli){
				n += sprint(buf+n, "::");
				i += eln;
				if(i >= 16)
					break;
			} else if(i != 0)
				n += sprint(buf+n, ":");
			s = (p[i]<<8) + p[i+1];
			n += sprint(buf+n, "%ux", s);
		}
		break;
		return fmtstrcpy(f, buf);

	case 'i':		/* v6 address as 4 longs */
		lp = va_arg(*arg, ulong*);
		lp = va_arg(f->args, ulong*);
		for(i = 0; i < 4; i++)
			hnputl(ip+4*i, *lp++);
		p = ip;
		goto common;

	case 'V':		/* v4 ip address */
		p = va_arg(*arg, uchar*);
		sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
		break;
		p = va_arg(f->args, uchar*);
		return fmtit(f, ifmt, p[0], p[1], p[2], p[3]);

	case 'M':		/* ip mask */
		p = va_arg(*arg, uchar*);
		p = va_arg(f->args, uchar*);

		/* look for a prefix mask */
		for(i = 0; i < 16; i++)


@@ 198,13 199,10 @@ common:
			n = 8*16;

		/* got one, use /xx format */
		sprint(buf, "/%d", n);
		break;
	default:
		strcpy(buf, "(eipconv)");
		return fmtit(f, "/%d", n);

	}
	strconv(buf, f);
	return sizeof(uchar*);
	return fmtit(f, "(eipfmt)");
}

#define CLASS(p) ((*(uchar*)(p))>>6)

M ip/netlog.c => ip/netlog.c +4 -4
@@ 233,13 233,13 @@ netlog(Fs *f, int mask, char *fmt, ...)
	if(!(f->alog->logmask & mask))
		return;

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	if(f->alog->opens == 0)
		return;

	va_start(arg, fmt);
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	lock(f->alog);
	i = f->alog->len + n - Nlog;
	if(i > 0){

M mtx/main.c => mtx/main.c +1 -0
@@ 18,6 18,7 @@ main(void)
	machinit();
	ioinit();
	i8250console();
	quotefmtinstall();
	print("\nPlan 9\n");
	confinit();
	xinit();

M mtx/pci.c => mtx/pci.c +10 -13
@@ 25,7 25,7 @@ pcilog(char *fmt, ...)
	char buf[PRINTSIZE];

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	memmove(PCICONS.output+PCICONS.ptr, buf, n);


@@ 92,20 92,17 @@ static char* bustypes[] = {
#pragma	varargck	type	"T"	int

static int
tbdfconv(va_list* arg, Fconv* f)
tbdffmt(Fmt* fmt)
{
	char *p;
	int l, type, tbdf;
	int l, r, type, tbdf;

	p = malloc(READSTR);
	if(p == nil){
		strconv("(tbdfconv)", f);
		return sizeof(int);
	}
	if((p = malloc(READSTR)) == nil)
		return fmtstrcpy(fmt, "(tbdfconv)");
		
	switch(f->chr){
	switch(fmt->r){
	case 'T':
		tbdf = va_arg(*arg, int);
		tbdf = va_arg(fmt->args, int);
		type = BUSTYPE(tbdf);
		if(type < nelem(bustypes))
			l = snprint(p, READSTR, bustypes[type]);


@@ 119,10 116,10 @@ tbdfconv(va_list* arg, Fconv* f)
		snprint(p, READSTR, "(tbdfconv)");
		break;
	}
	strconv(p, f);
	r = fmtstrcpy(fmt, p);
	free(p);

	return sizeof(int);
	return r;
}

ulong


@@ 537,7 534,7 @@ pcicfginit(void)
	if(pcicfgmode < 0)
		goto out;

	fmtinstall('T', tbdfconv);
	fmtinstall('T', tbdffmt);

	if(p = getconf("*pcimaxbno"))
		pcimaxbno = strtoul(p, 0, 0);

M pc/etherif.h => pc/etherif.h +1 -0
@@ 30,6 30,7 @@ struct Ether {
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);

#define NEXT(x, l)	(((x)+1)%(l))
#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)

A pc/ethersink.c => pc/ethersink.c +63 -0
@@ 0,0 1,63 @@
/*
 * An ethernet /dev/null.
 * Useful as a bridging target with ethernet-based VPN.
 */
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"

static long
ctl(Ether *ether, void *buf, long n)
{
	uchar ea[Eaddrlen];
	Cmdbuf *cb;

	cb = parsecmd(buf, n);
	if(cb->nf >= 2
	&& strcmp(cb->f[0], "ea")==0
	&& parseether(ea, cb->f[1]) == 0){
		free(cb);
		memmove(ether->ea, ea, Eaddrlen);
		memmove(ether->addr, ether->ea, Eaddrlen);
		return 0;
	}
	free(cb);
	error(Ebadctl);
	return -1;	/* not reached */
}

static void
nop(Ether*)
{
}

static int
reset(Ether* ether)
{
	uchar ea[Eaddrlen];

	memset(ea, 0, sizeof ea);
	ether->mbps = 1000;
	ether->attach = nop;
	ether->transmit = nop;
	ether->irq = 0;
	ether->interrupt = nil;
	ether->ifstat = nil;
	ether->ctl = ctl;
	ether->promiscuous = nil;
	ether->multicast = nil;
	ether->arg = ether;
	return 0;
}

void
ethersinklink(void)
{
	addethercard("sink", reset);
}

M pc/main.c => pc/main.c +1 -0
@@ 76,6 76,7 @@ main(void)
	options();
	ioinit();
	i8250console();
	quotefmtinstall();

	print("\nPlan 9\n");


M pc/pci.c => pc/pci.c +10 -13
@@ 25,7 25,7 @@ pcilog(char *fmt, ...)
	char buf[PRINTSIZE];

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	memmove(PCICONS.output+PCICONS.ptr, buf, n);


@@ 93,20 93,17 @@ static char* bustypes[] = {
#pragma	varargck	type	"T"	int

static int
tbdfconv(va_list* arg, Fconv* f)
tbdffmt(Fmt* fmt)
{
	char *p;
	int l, type, tbdf;
	int l, r, type, tbdf;

	p = malloc(READSTR);
	if(p == nil){
		strconv("(tbdfconv)", f);
		return sizeof(int);
	}
	if((p = malloc(READSTR)) == nil)
		return fmtstrcpy(fmt, "(tbdfconv)");
		
	switch(f->chr){
	switch(fmt->r){
	case 'T':
		tbdf = va_arg(*arg, int);
		tbdf = va_arg(fmt->args, int);
		type = BUSTYPE(tbdf);
		if(type < nelem(bustypes))
			l = snprint(p, READSTR, bustypes[type]);


@@ 120,10 117,10 @@ tbdfconv(va_list* arg, Fconv* f)
		snprint(p, READSTR, "(tbdfconv)");
		break;
	}
	strconv(p, f);
	r = fmtstrcpy(fmt, p);
	free(p);

	return sizeof(int);
	return r;
}

ulong


@@ 820,7 817,7 @@ pcicfginit(void)
	if(pcicfgmode < 0)
		goto out;

	fmtinstall('T', tbdfconv);
	fmtinstall('T', tbdffmt);

	if(p = getconf("*pcimaxbno"))
		pcimaxbno = strtoul(p, 0, 0);

M pc/sd53c8xx.c => pc/sd53c8xx.c +2 -2
@@ 337,7 337,7 @@ intrprint(char *format, ...)
{
	if (debuglast == 0)
		debuglast = debugbuf;
	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
}

static void


@@ 370,7 370,7 @@ oprint(char *format, ...)
	s = splhi();
	if (debuglast == 0)
		debuglast = debugbuf;
	debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
	splx(s);
	iflush();	
}

M pc/sdata.c => pc/sdata.c +1 -1
@@ 332,7 332,7 @@ atadebug(int cmdport, int ctlport, char* fmt, ...)
	}

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	if(cmdport){

M port/alloc.c => port/alloc.c +2 -2
@@ 68,7 68,7 @@ poolprint(Pool *p, char *fmt, ...)

	pv = p->private;
	va_start(v, fmt);
	doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
	va_end(v);
}



@@ 81,7 81,7 @@ ppanic(Pool *p, char *fmt, ...)

	pv = p->private;
	va_start(v, fmt);
	doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
	va_end(v);
	memmove(msg, pv->msg, sizeof msg);
	iunlock(&pv->lk);

M port/devcons.c => port/devcons.c +4 -39
@@ 154,41 154,6 @@ putstrn(char *str, int n)
	putstrn0(str, n, 0);
}

int
snprint(char *s, int n, char *fmt, ...)
{
	va_list arg;

	va_start(arg, fmt);
	n = doprint(s, s+n, fmt, arg) - s;
	va_end(arg);
	return n;
}

int
sprint(char *s, char *fmt, ...)
{
	int n;
	va_list arg;

	va_start(arg, fmt);
	n = doprint(s, s+PRINTSIZE, fmt, arg) - s;
	va_end(arg);
	return n;
}

char*
seprint(char *buf, char *e, char *fmt, ...)
{
	char *out;
	va_list arg;

	va_start(arg, fmt);
	out = doprint(buf, e, fmt, arg);
	va_end(arg);
	return out;
}

int noprint;

int


@@ 202,7 167,7 @@ print(char *fmt, ...)
		return -1;

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);
	putstrn(buf, n);



@@ 218,7 183,7 @@ iprint(char *fmt, ...)

	s = splhi();
	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);
	if(screenputs != nil)
		screenputs(buf, n);


@@ 246,7 211,7 @@ panic(char *fmt, ...)
	splhi();
	strcpy(buf, "panic: ");
	va_start(arg, fmt);
	n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);
	buf[n] = '\n';
	if(serialputs != nil)


@@ 283,7 248,7 @@ pprint(char *fmt, ...)
		return 0;
	n = sprint(buf, "%s %lud: ", up->text, up->pid);
	va_start(arg, fmt);
	n = doprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
	n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	if(waserror())

M port/devmnt.c => port/devmnt.c +3 -3
@@ 81,9 81,9 @@ mntreset(void)
{
	mntalloc.id = 1;
	mntalloc.rpctag = Tagspace;
	fmtinstall('F', fcallconv);
	fmtinstall('D', dirconv);
	fmtinstall('M', dirmodeconv);
	fmtinstall('F', fcallfmt);
	fmtinstall('D', dirfmt);
	fmtinstall('M', dirmodefmt);

	cinit();
}

M port/devtls.c => port/devtls.c +1 -1
@@ 959,7 959,7 @@ rcvError(TlsRec *tr, int err, char *fmt, ...)
	va_list arg;

	va_start(arg, fmt);
	doprint(msg, msg+sizeof(msg), fmt, arg);
	vseprint(msg, msg+sizeof(msg), fmt, arg);
	va_end(arg);

	sendAlert(tr, err);

M port/lib.h => port/lib.h +43 -28
@@ 5,23 5,23 @@
/*
 * mem routines
 */
extern	void	*memccpy(void*, void*, int, long);
extern	void	*memset(void*, int, long);
extern	int	memcmp(void*, void*, long);
extern	void	*memmove(void*, void*, long);
extern	void	*memchr(void*, int, long);
extern	void*	memccpy(void*, void*, int, ulong);
extern	void*	memset(void*, int, ulong);
extern	int	memcmp(void*, void*, ulong);
extern	void*	memmove(void*, void*, ulong);
extern	void*	memchr(void*, int, ulong);

/*
 * string routines
 */
extern	char	*strcat(char*, char*);
extern	char	*strchr(char*, char);
extern	char	*strrchr(char*, char);
extern	char*	strcat(char*, char*);
extern	char*	strchr(char*, char);
extern	char*	strrchr(char*, char);
extern	int	strcmp(char*, char*);
extern	char	*strcpy(char*, char*);
extern	char *strecpy(char*, char*, char*);
extern	char	*strncat(char*, char*, long);
extern	char	*strncpy(char*, char*, long);
extern	char*	strcpy(char*, char*);
extern	char*	strecpy(char*, char*, char*);
extern	char*	strncat(char*, char*, long);
extern	char*	strncpy(char*, char*, long);
extern	int	strncmp(char*, char*, long);
extern	long	strlen(char*);
extern	char*	strstr(char*, char*);


@@ 50,24 50,39 @@ extern	int	abs(int);
/*
 * print routines
 */
typedef
struct
{
	char*	out;		/* pointer to next output */
	char*	eout;		/* pointer to end */
	int	f1;
	int	f2;
	int	f3;
	int	chr;
} Fconv;
extern	void	strconv(char*, Fconv*);
extern	int	numbconv(va_list*, Fconv*);
extern	char	*doprint(char*, char*, char*, va_list);
extern	int	fmtinstall(int, int (*)(va_list*, Fconv*));
extern	int	sprint(char*, char*, ...);
typedef struct Fmt	Fmt;
typedef int (*Fmts)(Fmt*);
struct Fmt{
	uchar	runes;			/* output buffer is runes or chars? */
	void	*start;			/* of buffer */
	void	*to;			/* current place in the buffer */
	void	*stop;			/* end of the buffer; overwritten if flush fails */
	int	(*flush)(Fmt *);	/* called when to == stop */
	void	*farg;			/* to make flush a closure */
	int	nfmt;			/* num chars formatted so far */
	va_list	args;			/* args passed to dofmt */
	int	r;			/* % format Rune */
	int	width;
	int	prec;
	ulong	flags;
};
extern	int	print(char*, ...);
extern	char*	seprint(char*, char*, char*, ...);
extern	char*	vseprint(char*, char*, char*, va_list);
extern	int	snprint(char*, int, char*, ...);
extern	int	print(char*, ...);
extern	int	vsnprint(char*, int, char*, va_list);
extern	int	sprint(char*, char*, ...);

extern	int	fmtinstall(int c, int (*f)(Fmt*));
extern	int	quotefmtinstall(void);
extern	int	fmtit(Fmt *f, char *fmt, ...);
extern	int	fmtstrcpy(Fmt *f, char *s);

#pragma	varargck	argpos	fmtit	2
#pragma	varargck	argpos	print	1
#pragma	varargck	argpos	seprint	3
#pragma	varargck	argpos	snprint	3
#pragma	varargck	argpos	sprint	2

/*
 * one-of-a-kind

M port/log.c => port/log.c +6 -14
@@ 166,10 166,11 @@ logn(Log *alog, int mask, void *buf, int n)
}

void
vlog(Log *alog, int mask, char *fmt, va_list arg)
log(Log *alog, int mask, char *fmt, ...)
{
	char buf[128];
	int n;
	va_list arg;
	char buf[128];

	if(!(alog->logmask & mask))
		return;


@@ 177,18 178,9 @@ vlog(Log *alog, int mask, char *fmt, va_list arg)
	if(alog->opens == 0)
		return;

	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;

	logn(alog, mask, buf, n);
}

void
log(Log *alog, int mask, char *fmt, ...)
{
	va_list arg;

	va_start(arg, fmt);
	vlog(alog, mask, fmt, arg);
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);
}

	logn(alog, mask, buf, n);
}

M port/portdat.h => port/portdat.h +0 -3
@@ 835,9 835,6 @@ struct Uart
#pragma	varargck	type	"x"	uint
#pragma	varargck	type	"c"	uint
#pragma	varargck	type	"C"	uint
#pragma	varargck	type	"f"	double
#pragma	varargck	type	"e"	double
#pragma	varargck	type	"g"	double
#pragma	varargck	type	"s"	char*
#pragma	varargck	type	"S"	Rune*
#pragma	varargck	type	"r"	void

M port/portfns.h => port/portfns.h +0 -1
@@ 156,7 156,6 @@ void		logn(Log*, int, void*, int);
long		logread(Log*, void*, ulong, long);
void		log(Log*, int, char*, ...);
Cmdtab*	lookupcmd(Cmdbuf*, Cmdtab*, int);
void		vlog(Log*, int, char*, va_list);
Page*		lookpage(Image*, ulong);
void		machinit(void);
void*		mallocz(ulong, int);

M port/print.c => port/print.c +12 -1055
@@ 1,1068 1,25 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"

enum
{
	IDIGIT	= 30,
	MAXCONV	= 40,
	FDIGIT	= 30,
	FDEFLT	= 6,
	NONE	= -1000,
	MAXFMT	= 512,

	FPLUS	= 1<<0,
	FMINUS	= 1<<1,
	FSHARP	= 1<<2,
	FLONG	= 1<<3,
	FUNSIGN	= 1<<5,
	FVLONG	= 1<<6,
	FPOINTER= 1<<7,
};

int	printcol;

static struct
{
	Lock;
	int	convcount;
	char	index[MAXFMT];
	int	(*conv[MAXCONV])(va_list*, Fconv*);
} fmtalloc;

static	int	noconv(va_list*, Fconv*);
static	int	flags(va_list*, Fconv*);

static	int	cconv(va_list*, Fconv*);
/* static	int	rconv(va_list*, Fconv*); */
static	int	sconv(va_list*, Fconv*);
static	int	percent(va_list*, Fconv*);
/* static	int	column(va_list*, Fconv*); */

extern	int	numbconv(va_list*, Fconv*);
/* extern	int	fltconv(va_list*, Fconv*); */
extern	int	quotestrconv(va_list*, Fconv*);
extern	int	quoterunestrconv(va_list*, Fconv*);


static	void
initfmt(void)
{
	int cc;

	cc = 0;
	fmtalloc.conv[cc] = noconv;
	cc++;

	fmtalloc.conv[cc] = flags;
	fmtalloc.index['+'] = cc;
	fmtalloc.index['-'] = cc;
	fmtalloc.index['#'] = cc;
	fmtalloc.index['l'] = cc;
	fmtalloc.index['u'] = cc;
	cc++;

	fmtalloc.conv[cc] = numbconv;
	fmtalloc.index['d'] = cc;
	fmtalloc.index['o'] = cc;
	fmtalloc.index['x'] = cc;
	fmtalloc.index['X'] = cc;
	fmtalloc.index['p'] = cc;
	cc++;

/*
	fmtalloc.conv[cc] = fltconv;
	fmtalloc.index['e'] = cc;
	fmtalloc.index['f'] = cc;
	fmtalloc.index['g'] = cc;
	fmtalloc.index['E'] = cc;
	fmtalloc.index['G'] = cc;
	cc++;
*/

	fmtalloc.conv[cc] = cconv;
	fmtalloc.index['c'] = cc;
	fmtalloc.index['C'] = cc;
	cc++;

/*
	fmtalloc.conv[cc] = rconv;
	fmtalloc.index['r'] = cc;
	cc++;
*/
	fmtalloc.conv[cc] = quotestrconv;
	fmtalloc.index['q'] = cc;
	cc++;

	fmtalloc.conv[cc] = quoterunestrconv;
	fmtalloc.index['Q'] = cc;
	cc++;

	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;
}

int
fmtinstall(int c, int (*f)(va_list*, Fconv*))
{

	lock(&fmtalloc);

	if(fmtalloc.convcount <= 0)
		initfmt();
	if(c < 0 || c >= MAXFMT){
		unlock(&fmtalloc);
		return -1;
	}
	if(fmtalloc.convcount >= MAXCONV){
		unlock(&fmtalloc);
		return -1;
	}
	fmtalloc.conv[fmtalloc.convcount] = f;
	fmtalloc.index[c] = fmtalloc.convcount;
	fmtalloc.convcount++;

	unlock(&fmtalloc);
	return 0;
}

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;
	}
}

char*
doprint(char *s, char *es, char *fmt, va_list argp)
{
	int n, c;
	Rune rune;
	Fconv local;

	if(fmtalloc.convcount <= 0)
		initfmt();

	if(s >= es)
		return s;
	local.out = s;
	local.eout = es-1;

loop:
	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:
		pchar(c, &local);
		goto loop;

	case '%':
		break;
	}
	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;
	}
	if(c == '.') {
		if(local.f1 == NONE)
			local.f1 = 0;
		local.f2 = 0;
		goto l0;
	}
	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;
		goto l1;
	}
	if(c == '*') {
		n = va_arg(argp, int);
		if(local.f1 == NONE)
			local.f1 = n;
		else
			local.f2 = n;
		goto l0;
	}
	n = 0;
	if(c >= 0 && c < MAXFMT)
		n = fmtalloc.index[c];
	local.chr = c;
	n = (*fmtalloc.conv[n])(&argp, &local);
	if(n < 0) {
		local.f3 |= -n;
		goto l0;
	}
	goto loop;
}

int
numbconv(va_list *arg, Fconv *fp)
{
	char s[IDIGIT];
	int i, f, n, b, ucase;
	long v;
	vlong vl;

	SET(v);
	SET(vl);

	ucase = 0;
	b = fp->chr;
	switch(fp->chr) {
	case 'u':
		fp->f3 |= FUNSIGN;
	case 'd':
		b = 10;
		break;

	case 'b':
		b = 2;
		break;

	case 'o':
		b = 8;
		break;

	case 'X':
		ucase = 1;
	case 'x':
		b = 16;
		break;
	case 'p':
		fp->f3 |= FPOINTER|FUNSIGN;
		b = 16;
		break;
	}

	f = 0;
	switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) {
	case FVLONG|FLONG:
		vl = va_arg(*arg, vlong);
		break;

	case FUNSIGN|FVLONG|FLONG:
		vl = va_arg(*arg, uvlong);
		break;

	case FUNSIGN|FPOINTER:
		v = (ulong)va_arg(*arg, void*);
		break;

	case FLONG:
		v = va_arg(*arg, long);
		break;

	case FUNSIGN|FLONG:
		v = va_arg(*arg, ulong);
		break;

	default:
		v = va_arg(*arg, int);
		break;

	case FUNSIGN:
		v = va_arg(*arg, unsigned);
		break;
	}
	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;
		}
	}
	s[IDIGIT-1] = 0;
	for(i = IDIGIT-2;; i--) {
		if(fp->f3 & FVLONG)
			n = (uvlong)vl % b;
		else
			n = (ulong)v % b;
		n += '0';
		if(n > '9') {
			n += 'a' - ('9'+1);
			if(ucase)
				n += 'A'-'a';
		}
		s[i] = n;
		if(i < 2)
			break;
		if(fp->f3 & FVLONG)
			vl = (uvlong)vl / b;
		else
			v = (ulong)v / b;
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
			continue;
		if(fp->f3 & FVLONG) {
			if(vl <= 0)
				break;
			continue;
		}
		if(v <= 0)
			break;
	}

	if(fp->f3 & FSHARP) {
		if(b == 8 && s[i] != '0')
			s[--i] = '0';
		if(b == 16) {
			if(ucase)
				s[--i] = 'X';
			else
				s[--i] = 'x';
			s[--i] = '0';
		}
	}
	if(f)
		s[--i] = '-';
	fp->f2 = NONE;
	strconv(s+i, fp);
	return 0;
}
static Lock fmtl;

void
Strconv(Rune *s, Fconv *fp)
_fmtlock(void)
{
	int n, c;

	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) {
			pchar(' ', fp);
			printcol++;
			n++;
		}
	}
	for(;;) {
		c = *s++;
		if(c == 0)
			break;
		n++;
		if(fp->f2 == NONE || fp->f2 > 0) {
			pchar(c, fp);
			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) {
			pchar(' ', fp);
			printcol++;
			n++;
		}
	}
	lock(&fmtl);
}

void
strconv(char *s, Fconv *fp)
_fmtunlock(void)
{
	int n, c, i;
	Rune rune;

	if(fp->f3 & FMINUS)
		fp->f1 = -fp->f1;
	n = 0;
	if(fp->f1 != NONE && fp->f1 >= 0) {
		n = utflen(s);
		while(n < fp->f1) {
			pchar(' ', fp);
			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) {
			pchar(c, fp);
			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) {
			pchar(' ', fp);
			printcol++;
			n++;
		}
	}
}

static int
noconv(va_list*, Fconv *fp)
{
	char s[10];

	s[0] = '*';
	s[1] = fp->chr;
	s[2] = '*';
	s[3] = 0;
	fp->f1 = 0;
	fp->f2 = NONE;
	fp->f3 = 0;
	strconv(s, fp);
	return 0;
}

#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
cconv(va_list *arg, Fconv *fp)
{
	char s[10];
	Rune rune;

	rune = va_arg(*arg, int);
	if(fp->chr == 'c')
		rune &= 0xff;
	s[runetochar(s, &rune)] = 0;

	fp->f2 = NONE;
	strconv(s, fp);
	return 0;
	unlock(&fmtl);
}

static	int
sconv(va_list *arg, Fconv *fp)
{
	char *s;
	Rune *r;

	if(fp->chr == 's') {
		s = va_arg(*arg, char*);
		if(s == 0)
			s = "<null>";
		strconv(s, fp);
	} else {
		r = va_arg(*arg, Rune*);
		if(r == 0)
			r = L"<null>";
		Strconv(r, fp);
	}
	return 0;
}

static	int
percent(va_list*, Fconv *fp)
{
	pchar('%', fp);
	printcol++;
	return 0;
}

#ifdef NOTDEF
static	int
column(va_list *arg, Fconv *fp)
{
	int col, pc;

	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

static	int
flags(va_list*, Fconv *fp)
{
	int f;

	f = 0;
	switch(fp->chr) {
	case '+':
		f = FPLUS;
		break;

	case '-':
		f = FMINUS;
		break;

	case '#':
		f = FSHARP;
		break;

	case 'l':
		f = FLONG;
		if(fp->f3 & FLONG)
			f = FVLONG;
		break;

	case 'u':
		f = FUNSIGN;
		break;
	}
	return -f;
}

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;

	if(*s == '\0')
		return 1;
	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;

	if(*s == L'\0')
		return 1;
	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);
}

#ifdef NOTDEF
int
fltconv(va_list *arg, Fconv *fp)
_efgfmt(Fmt*)
{
	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;
	return -1;
}
#endif

M port/rdb.c => port/rdb.c +1 -1
@@ 18,7 18,7 @@ scrprint(char *fmt, ...)
	int n;

	va_start(va, fmt);
	n = doprint(buf, buf+sizeof buf, fmt, va)-buf;
	n = vseprint(buf, buf+sizeof buf, fmt, va)-buf;
	va_end(va);
	putstrn(buf, n);
}

M port/sysproc.c => port/sysproc.c +1 -1
@@ 631,7 631,7 @@ werrstr(char *fmt, ...)
		return;

	va_start(va, fmt);
	doprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);
	vseprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);
	va_end(va);
}