~kris/9p

9hist

b2a603594b65c9199456292b4ffc9946435a55b1 — David du Colombier 27 years ago f120c0c
Plan 9 from Bell Labs 1999-08-19
M pc/audio.h => pc/audio.h +1 -1
@@ 12,4 12,4 @@ enum
#define UNCACHED(type, v)	(type*)((ulong)(v))

#define Int0vec
#define setvec(v, f, a)		intrenable(v, f, a, BUSUNKNOWN)
#define setvec(v, f, a)		intrenable(v, f, a, BUSUNKNOWN, "audio")

M pc/devastar.c => pc/devastar.c +4 -2
@@ 977,6 977,7 @@ startcp(Astar *a)
	uchar *x;
	CCB *ccb;
	Astarchan *ac;
	char name[10];

	if(a->running)
		error(Eio);


@@ 1079,20 1080,21 @@ startcp(Astar *a)
		x += sz;
	}

	snprint(name, sizeof name, "astar%d", a->id);
	/* set up interrupt level, enable interrupts */
	if(a->pci){
		/*
		 * Which bits in the interrupt control register should be set?
		 */
		outl(a->port+PCIcontrol, 0x00031F00);
		intrenable(a->irq, astarintr, a, a->pci->tbdf);
		intrenable(a->irq, astarintr, a, a->pci->tbdf, name);
	}
	else{
		c = inb(a->port+ISActl1);
		c &= ~ISAirq;
		c |= ISAien|isairqcode[a->irq];
		outb(a->port+ISActl1, c);
		intrenable(a->irq, astarintr, a, BUSUNKNOWN);
		intrenable(a->irq, astarintr, a, BUSUNKNOWN, name);
	}

	/* enable control program interrupt generation */

M pc/devata.c => pc/devata.c +2 -1
@@ 619,7 619,8 @@ atapislave:

	print("#H%d: cmdport 0x%uX ctlport 0x%uX irq %d mask 0x%uX atapi 0x%uX\n",
		ctlrno, cmdport, ctlport,  irq, mask, atapi);
	intrenable(irq, ataintr, ctlr, ctlr->tbdf);
	snprint(name, sizeof name, "ata%d", ctlrno);
	intrenable(irq, ataintr, ctlr, ctlr->tbdf, name);
	inb(cmdport+Pstatus);
	outb(ctlport+Pctl, 0);
	if(devp->ienable)

M pc/devether.c => pc/devether.c +2 -2
@@ 368,7 368,8 @@ etherreset(void)
			 */
			if(ether->irq == 2)
				ether->irq = 9;
			intrenable(ether->irq, ether->interrupt, ether, ether->tbdf);
			snprint(name, sizeof(name), "ether%d", ctlrno);
			intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);

			i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
				ctlrno, ether->type, ether->mbps, ether->port, ether->irq);


@@ 382,7 383,6 @@ etherreset(void)
			sprint(buf+i, "\n");
			print(buf);

			snprint(name, sizeof(name), "ether%d", ctlrno);
			if(ether->mbps == 100){
				netifinit(ether, name, Ntypes, 256*1024);
				if(ether->oq == 0)

M pc/devi82365.c => pc/devi82365.c +1 -1
@@ 658,7 658,7 @@ i82365reset(void)

	/* for card management interrupts */
	if(ncontroller)
		intrenable(irq, i82365intr, 0, BUSUNKNOWN);
		intrenable(irq, i82365intr, 0, BUSUNKNOWN, "i82365");
}

static Chan*

M pc/devlml.c => pc/devlml.c +1 -1
@@ 215,7 215,7 @@ lmlreset(void)
	}

	// Interrupt handler
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf, "lml");

	return;
}

M pc/devlpt.c => pc/devlpt.c +1 -1
@@ 82,7 82,7 @@ lptattach(char *spec)
	if(!set){
		outb(lptbase[i-1]+Qpcr, 0);	/* turn off interrupts */
		set = 1;
		intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN);
		intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt");
	}
	if(i < 1 || i > NDEV)
		error(Ebadarg);

M pc/floppy.h => pc/floppy.h +1 -1
@@ 164,7 164,7 @@ floppysetup1(FController *fl)
		floppysetdef(&fl->d[1]);
	}

	intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
	intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy");
}

/*

M pc/fns.h => pc/fns.h +3 -2
@@ 47,12 47,13 @@ ushort	ins(int);
void	inss(int, void*, int);
ulong	inl(int);
void	insl(int, void*, int);
void	intrenable(int, void (*)(Ureg*, void*), void*, int);
void	intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
void	iofree(int);
void	ioinit(void);
int	iounused(int, int);
int	ioalloc(int, int, int, char*);
int	iprint(char*, ...);
int	irqallocread(char*, long, vlong);
int	isaconfig(char*, int, ISAConf*);
void	kbdinit(void);
void	lgdt(ushort[3]);


@@ 103,7 104,7 @@ void	screeninit(void);
int	screenprint(char*, ...);			/* debugging */
void	(*screenputs)(char*, int);
void	touser(void*);
void	trapenable(int, void (*)(Ureg*, void*), void*);
void	trapenable(int, void (*)(Ureg*, void*), void*, char*);
void	trapinit(void);
int	tas(void*);
ulong	umbmalloc(ulong, int, int);

M pc/i8253.c => pc/i8253.c +1 -1
@@ 127,7 127,7 @@ i8253init(int aalcycles, int havecycleclock)
void
i8253enable(void)
{
	intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN);
	intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN, "clock");
}

/*

M pc/io.h => pc/io.h +1 -0
@@ 43,6 43,7 @@ enum {
typedef struct Vctl {
	Vctl*	next;			/* handlers on this vector */

	char	name[NAMELEN];	/* of driver */
	int	isintr;			/* interrupt or fault/trap */
	int	irq;
	int	tbdf;

M pc/kbd.c => pc/kbd.c +2 -2
@@ 384,7 384,7 @@ i8042auxenable(void (*putc)(int, int))
		return;
	}
	auxputc = putc;
	intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN);
	intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
	iunlock(&i8042lock);
}



@@ 401,7 401,7 @@ kbdinit(void)
	ioalloc(Data, 1, 0, "kbd");
	ioalloc(Cmd, 1, 0, "kbd");

	intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN);
	intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");

	/* wait for a quiescent controller */
	while((c = inb(Status)) & (Outbusy | Inready))

M pc/main.c => pc/main.c +4 -4
@@ 566,11 566,11 @@ mathover(Ureg*, void*)
void
mathinit(void)
{
	trapenable(VectorCERR, matherror, 0);
	trapenable(VectorCERR, matherror, 0, "matherror");
	if(X86FAMILY(m->cpuidax) == 3)
		intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN);
	trapenable(VectorCNA, mathemu, 0);
	trapenable(VectorCSO, mathover, 0);
		intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
	trapenable(VectorCNA, mathemu, 0, "mathemu");
	trapenable(VectorCSO, mathover, 0, "mathover");
}

/*

M pc/mp.c => pc/mp.c +3 -3
@@ 552,9 552,9 @@ mpinit(void)
	 * and do not appear in the I/O APIC so it is OK
	 * to set them now.
	 */
	intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN);
	intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN);
	intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN);
	intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN, "clock");
	intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror");
	intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious");
	lapiconline();

	checkmtrr();

M pc/ns16552.h => pc/ns16552.h +7 -8
@@ 96,11 96,11 @@ ns16552install(void)
	if(ioalloc(0x3f8, 8, 0, "eia0") < 0)
		print("eia0: port %d in use\n", 0x3f8);
	ns16552setup(0x3F8, UartFREQ, "eia0", Ns550);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN, "eia0");
	if(ioalloc(0x2F8, 8, 0, "eia1") < 0)
		print("eia1: port %d in use\n", 0x2F8);
	ns16552setup(0x2F8, UartFREQ, "eia1", Ns550);
	intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN);
	intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN, "eia1");
	addclock0link(uartclock);

	/* set up a serial console */


@@ 120,6 120,7 @@ ns16552install(void)
			continue;
		}

		snprint(name, sizeof name, "eia%d00", nscard);
		if(cistrcmp(sc->type, "MP008") == 0){
			/*
			 *  port gives base port address for uarts


@@ 133,13 134,13 @@ ns16552install(void)
			if(sc->freq == 0)
				sc->freq = UartFREQ;
			sc->first = nuart;
			if(ioalloc(sc->port, 8*sc->size, 0, "mp008") < 0){
			if(ioalloc(sc->port, 8*sc->size, 0, name) < 0){
				print("mp008: port %lud in use\n", sc->port);
				xfree(sc);
				scard[nscard] = 0;
				continue;
			}
			intrenable(sc->irq, mp008intr, sc, BUSUNKNOWN);
			intrenable(sc->irq, mp008intr, sc, BUSUNKNOWN, name);
			port = sc->port;
			for(j=0; j < sc->size; j++){
				sprint(name, "eia%d%2.2d", nscard, j);


@@ 154,7 155,6 @@ ns16552install(void)
			 */
			if(sc->freq == 0)
				sc->freq = UartFREQ*4;
			sprint(name, "eia%d00", nscard);
			if(ioalloc(sc->port, 8, 0, name) < 0){
				print("%s: port %lud in use\n", name, sc->port);
				xfree(sc);


@@ 171,7 171,7 @@ ns16552install(void)
			else
				outb(sc->mem, 0);

			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN, name);
		} else if(cistrcmp(sc->type, "com") == 0 && sc->port != 0x3F8 && sc->port != 0x2F8){
			/*
			 *  port gives base port address for the uart


@@ 180,7 180,6 @@ ns16552install(void)
			 */
			if(sc->freq == 0)
				sc->freq = UartFREQ;
			sprint(name, "eia%d00", nscard);
			if(ioalloc(sc->port, 8, 0, name) < 0){
				print("%s: port %lud in use\n", name, sc->port);
				xfree(sc);


@@ 188,7 187,7 @@ ns16552install(void)
				continue;
			}
			ns16552setup(sc->port, sc->freq, name, Ns550);
			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN);
			intrenable(sc->irq, ns16552intrx, (void*)(nuart-1), BUSUNKNOWN, name);
		}
		nscard++;
	}

M pc/trap.c => pc/trap.c +58 -8
@@ 16,10 16,10 @@ static Lock vctllock;
static Vctl *vctl[256];

void
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
{
	int vno;
	Vctl *v;
	Vctl *v, *p;

	v = xalloc(sizeof(Vctl));
	v->isintr = 1;


@@ 27,19 27,28 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)
	v->tbdf = tbdf;
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN-1);
	v->name[NAMELEN-1] = 0;

	ilock(&vctllock);
	vno = arch->intrenable(v);
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX\n",
			irq, tbdf);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
			irq, tbdf, v->name);
		if(p=vctl[vno]){
			print("intrenable: irq %d is already used by", irq);
			for(; p; p=p->next)
				print(" %s", p->name);
			print("\n");
		}
		xfree(v);
		return;
	}
	if(vctl[vno]){
		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
			panic("intrenable: handler: %luX %luX %luX %luX\n",
			panic("intrenable: handler: %s %s %luX %luX %luX %luX\n",
				vctl[vno]->name, v->name,
				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
		v->next = vctl[vno];
	}


@@ 47,8 56,47 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)
	iunlock(&vctllock);
}

int
irqallocread(char *buf, long n, vlong offset)
{
	int vno;
	Vctl *v;
	long oldn;
	char str[11+1+NAMELEN+1], *p;
	int m;

	if(n < 0 || offset < 0)
		error(Ebadarg);

	oldn = n;
	for(vno=0; vno<nelem(vctl); vno++){
		for(v=vctl[vno]; v; v=v->next){
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name);
			if(m <= offset)	/* if do not want this, skip entry */
				offset -= m;
			else{
				/* skip offset bytes */
				m -= offset;
				p = str+offset;
				offset = 0;

				/* write at most max(n,m) bytes */
				if(m > n)
					m = n;
				memmove(buf, p, m);
				n -= m;
				buf += m;

				if(n == 0)
					return oldn;
			}	
		}
	}
	return oldn - n;
}

void
trapenable(int vno, void (*f)(Ureg*, void*), void* a)
trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name)
{
	Vctl *v;



@@ 58,6 106,8 @@ trapenable(int vno, void (*f)(Ureg*, void*), void* a)
	v->tbdf = BUSUNKNOWN;
	v->f = f;
	v->a = a;
	strncpy(v->name, name, NAMELEN);
	v->name[NAMELEN-1] = 0;

	lock(&vctllock);
	if(vctl[vno])


@@ 116,8 166,8 @@ trapinit(void)
	 * Special traps.
	 * Syscall() is called directly without going through trap().
	 */
	trapenable(VectorBPT, debugbpt, 0);
	trapenable(VectorPF, fault386, 0);
	trapenable(VectorBPT, debugbpt, 0, "debugpt");
	trapenable(VectorPF, fault386, 0, "fault386");

	nmienable();
}

M port/lib.h => port/lib.h +1 -0
@@ 40,6 40,7 @@ extern	int	runetochar(char*, Rune*);
extern	int	chartorune(Rune*, char*);
extern	char*	utfrune(char*, long);
extern	int	utflen(char*);
extern	int	runelen(long);

extern	int	abs(int);


M port/print.c => port/print.c +378 -123
@@ 1,5 1,8 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"

enum
{


@@ 14,92 17,142 @@ enum
	FMINUS	= 1<<1,
	FSHARP	= 1<<2,
	FLONG	= 1<<3,
	FSHORT	= 1<<4,
	FUNSIGN	= 1<<5,
	FVLONG	= 1<<6,
	FPOINTER	= 1<<7,
	FPOINTER= 1<<7,
};

int	printcol;

static	int	convcount;
static	char	fmtindex[MAXFMT];
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*); */

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

static
int	(*fmtconv[MAXCONV])(va_list*, Fconv*) =
{
	noconv
};

static
void
static	void
initfmt(void)
{
	int cc;

	cc = 0;
	fmtconv[cc] = noconv;
	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++;

	fmtconv[cc] = flags;
	fmtindex['+'] = cc;
	fmtindex['-'] = cc;
	fmtindex['#'] = cc;
	fmtindex['h'] = cc;
	fmtindex['l'] = cc;
	fmtindex['u'] = 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++;
*/

	fmtconv[cc] = numbconv;
	fmtindex['d'] = cc;
	fmtindex['o'] = cc;
	fmtindex['x'] = cc;
	fmtindex['X'] = cc;
	fmtindex['p'] = cc;
	fmtalloc.conv[cc] = cconv;
	fmtalloc.index['c'] = cc;
	fmtalloc.index['C'] = cc;
	cc++;

	fmtconv[cc] = cconv;
	fmtindex['c'] = cc;
	fmtindex['C'] = cc;
/*
	fmtalloc.conv[cc] = rconv;
	fmtalloc.index['r'] = cc;
	cc++;
*/

	fmtconv[cc] = sconv;
	fmtindex['s'] = cc;
	fmtindex['S'] = cc;
	fmtalloc.conv[cc] = sconv;
	fmtalloc.index['s'] = cc;
	fmtalloc.index['S'] = cc;
	cc++;

	fmtconv[cc] = percent;
	fmtindex['%'] = cc;
	fmtalloc.conv[cc] = percent;
	fmtalloc.index['%'] = cc;
	cc++;

	convcount = cc;
/*
	fmtalloc.conv[cc] = column;
	fmtalloc.index['|'] = cc;
	cc++;
*/

	fmtalloc.convcount = cc;
}

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

	if(convcount == 0)
	lock(&fmtalloc);

	if(fmtalloc.convcount <= 0)
		initfmt();
	if(c < 0 || c >= MAXFMT)
	if(c < 0 || c >= MAXFMT){
		unlock(&fmtalloc);
		return -1;
	if(convcount >= MAXCONV)
	}
	if(fmtalloc.convcount >= MAXCONV){
		unlock(&fmtalloc);
		return -1;
	fmtconv[convcount] = f;
	fmtindex[c] = convcount;
	convcount++;
	}
	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)
{


@@ 107,8 160,13 @@ doprint(char *s, char *es, char *fmt, va_list argp)
	Rune rune;
	Fconv local;

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

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

loop:
	c = *fmt & 0xff;


@@ 122,7 180,7 @@ loop:
	case 0:
		*local.out = 0;
		return local.out;

	
	default:
		printcol++;
		goto common;


@@ 136,13 194,7 @@ loop:
		goto common;

	common:
		if(local.out < local.eout)
			if(c >= Runeself) {
				rune = c;
				n = runetochar(local.out, &rune);
				local.out += n;
			} else
				*local.out++ = c;
		pchar(c, &local);
		goto loop;

	case '%':


@@ 203,9 255,9 @@ l1:
	}
	n = 0;
	if(c >= 0 && c < MAXFMT)
		n = fmtindex[c];
		n = fmtalloc.index[c];
	local.chr = c;
	n = (*fmtconv[n])(&argp, &local);
	n = (*fmtalloc.conv[n])(&argp, &local);
	if(n < 0) {
		local.f3 |= -n;
		goto l0;


@@ 218,7 270,6 @@ numbconv(va_list *arg, Fconv *fp)
{
	char s[IDIGIT];
	int i, f, n, b, ucase;
	short h;
	long v;
	vlong vl;



@@ 234,6 285,10 @@ numbconv(va_list *arg, Fconv *fp)
		b = 10;
		break;

	case 'b':
		b = 2;
		break;

	case 'o':
		b = 8;
		break;


@@ 250,7 305,7 @@ numbconv(va_list *arg, Fconv *fp)
	}

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


@@ 259,6 314,10 @@ numbconv(va_list *arg, Fconv *fp)
		vl = va_arg(*arg, uvlong);
		break;

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

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


@@ 267,20 326,6 @@ numbconv(va_list *arg, Fconv *fp)
		v = va_arg(*arg, ulong);
		break;

	case FSHORT:
		h = va_arg(*arg, int);
		v = h;
		break;

	case FUNSIGN|FSHORT:
		h = va_arg(*arg, int);
		v = (ushort)h;
		break;

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

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


@@ 351,8 396,7 @@ numbconv(va_list *arg, Fconv *fp)
void
Strconv(Rune *s, Fconv *fp)
{
	int n, c, i;
	Rune rune;
	int n, c;

	if(fp->f3 & FMINUS)
		fp->f1 = -fp->f1;


@@ 361,8 405,7 @@ Strconv(Rune *s, Fconv *fp)
		for(; s[n]; n++)
			;
		while(n < fp->f1) {
			if(fp->out < fp->eout)
				*fp->out++ = ' ';
			pchar(' ', fp);
			printcol++;
			n++;
		}


@@ 373,13 416,7 @@ Strconv(Rune *s, Fconv *fp)
			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;
			pchar(c, fp);
			if(fp->f2 != NONE)
				fp->f2--;
			switch(c) {


@@ 398,8 435,7 @@ Strconv(Rune *s, Fconv *fp)
	if(fp->f1 != NONE && fp->f1 < 0) {
		fp->f1 = -fp->f1;
		while(n < fp->f1) {
			if(fp->out < fp->eout)
				*fp->out++ = ' ';
			pchar(' ', fp);
			printcol++;
			n++;
		}


@@ 418,8 454,7 @@ strconv(char *s, Fconv *fp)
	if(fp->f1 != NONE && fp->f1 >= 0) {
		n = utflen(s);
		while(n < fp->f1) {
			if(fp->out < fp->eout)
				*fp->out++ = ' ';
			pchar(' ', fp);
			printcol++;
			n++;
		}


@@ 436,13 471,7 @@ strconv(char *s, Fconv *fp)
			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;
			pchar(c, fp);
			if(fp->f2 != NONE)
				fp->f2--;
			switch(c) {


@@ 461,28 490,18 @@ strconv(char *s, Fconv *fp)
	if(fp->f1 != NONE && fp->f1 < 0) {
		fp->f1 = -fp->f1;
		while(n < fp->f1) {
			if(fp->out < fp->eout)
				*fp->out++ = ' ';
			pchar(' ', fp);
			printcol++;
			n++;
		}
	}
}

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

	if(convcount == 0) {
		initfmt();
		n = 0;
		if(fp->chr >= 0 && fp->chr < MAXFMT)
			n = fmtindex[fp->chr];
		return (*fmtconv[n])(arg, fp);
	}
	s[0] = '*';
	s[1] = fp->chr;
	s[2] = '*';


@@ 494,8 513,21 @@ noconv(va_list *arg, Fconv *fp)
	return 0;
}

static
int
#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];


@@ 511,8 543,7 @@ cconv(va_list *arg, Fconv *fp)
	return 0;
}

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


@@ 532,25 563,39 @@ sconv(va_list *arg, Fconv *fp)
	return 0;
}

static
int
percent(va_list *arg, Fconv *fp)
static	int
percent(va_list*, Fconv *fp)
{

	USED(arg);
	if(fp->out < fp->eout)
		*fp->out++ = '%';
	pchar('%', fp);
	printcol++;
	return 0;
}

static
int
flags(va_list *arg, Fconv *fp)
#ifdef NOTDEF
static	int
column(va_list *arg, Fconv *fp)
{
	int f;
	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

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

	f = 0;
	switch(fp->chr) {


@@ 566,10 611,6 @@ flags(va_list *arg, Fconv *fp)
		f = FSHARP;
		break;

	case 'h':
		f = FSHORT;
		break;

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


@@ 582,3 623,217 @@ flags(va_list *arg, Fconv *fp)
	}
	return -f;
}

#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