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