From b2a603594b65c9199456292b4ffc9946435a55b1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 19 Aug 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-08-19 --- pc/audio.h | 2 +- pc/devastar.c | 6 +- pc/devata.c | 3 +- pc/devether.c | 4 +- pc/devi82365.c | 2 +- pc/devlml.c | 2 +- pc/devlpt.c | 2 +- pc/floppy.h | 2 +- pc/fns.h | 5 +- pc/i8253.c | 2 +- pc/io.h | 1 + pc/kbd.c | 4 +- pc/main.c | 8 +- pc/mp.c | 6 +- pc/ns16552.h | 15 +- pc/trap.c | 66 ++++++- port/lib.h | 1 + port/print.c | 501 +++++++++++++++++++++++++++++++++++++------------ 18 files changed, 471 insertions(+), 161 deletions(-) diff --git a/pc/audio.h b/pc/audio.h index 06406427a447f161db338e78a14b90016cf8c30c..fb11b11158579377fa7ae1f69af9776e426482c0 100644 --- a/pc/audio.h +++ b/pc/audio.h @@ -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") diff --git a/pc/devastar.c b/pc/devastar.c index a4a2867324456e7502939e7af955359467c9ce70..9614fc49c983f25043c53aa134f3ed62615adb74 100644 --- a/pc/devastar.c +++ b/pc/devastar.c @@ -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 */ diff --git a/pc/devata.c b/pc/devata.c index d7e92da71516ec88498e4c1768cff92e7e924a03..ef9433010d74879a8387621ee980ba8a3646da12 100644 --- a/pc/devata.c +++ b/pc/devata.c @@ -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) diff --git a/pc/devether.c b/pc/devether.c index 22bfea833b61cf42c474052771866455cc43ec22..fc9e06889f787b35b41f405311652b5a78b6c2b4 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -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) diff --git a/pc/devi82365.c b/pc/devi82365.c index 6c6df77e12a6f90f855b8d647547cc3e2a0b47f9..db20701a2d4659e12bb408d93fe581a3cea19d2d 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -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* diff --git a/pc/devlml.c b/pc/devlml.c index 0eb47b232f702b66a50d57b0237504818e0fae7e..feceda52f986d2be3b2fdadfa498d68e3130e811 100644 --- a/pc/devlml.c +++ b/pc/devlml.c @@ -215,7 +215,7 @@ lmlreset(void) } // Interrupt handler - intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); + intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf, "lml"); return; } diff --git a/pc/devlpt.c b/pc/devlpt.c index 792131fe7f7b0423b02866114432df661c6156a8..761f0249f56ed7919d66f72a1b75c3aeda541766 100644 --- a/pc/devlpt.c +++ b/pc/devlpt.c @@ -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); diff --git a/pc/floppy.h b/pc/floppy.h index 4f31670b6e272cd6f0d22d04efe6f67590863dad..a897b5223b986e732a530857c28818a542518a2f 100644 --- a/pc/floppy.h +++ b/pc/floppy.h @@ -164,7 +164,7 @@ floppysetup1(FController *fl) floppysetdef(&fl->d[1]); } - intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN); + intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy"); } /* diff --git a/pc/fns.h b/pc/fns.h index dca73c8c821ab5865d05f32d6f35cd80b8e09914..1cb32c56e666a9af16346e243c161e923d8dfefb 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -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); diff --git a/pc/i8253.c b/pc/i8253.c index d3ab91fe0e06fea0135813009cdfe977d963b00f..4e87537bac684d96367fdb896a69eefd0b50bb87 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -127,7 +127,7 @@ i8253init(int aalcycles, int havecycleclock) void i8253enable(void) { - intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN); + intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN, "clock"); } /* diff --git a/pc/io.h b/pc/io.h index 13a1d2c048dd5d12532da2e908bf9e75dc279875..c2092e5ee872c74b8ce0db8f01eaef4c2b343f64 100644 --- a/pc/io.h +++ b/pc/io.h @@ -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; diff --git a/pc/kbd.c b/pc/kbd.c index 09c69247bb13581a51fddeed9e45f4c9d5196314..27f70a4a6e1608f130dad6523b54405328317615 100644 --- a/pc/kbd.c +++ b/pc/kbd.c @@ -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)) diff --git a/pc/main.c b/pc/main.c index 82c5181dcd3a309333175b97f66fee57f6f64d6d..6a2ba27cb8ea42f4a9cd73e0b0dd20788599e293 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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"); } /* diff --git a/pc/mp.c b/pc/mp.c index 218c7f2a9c2a980a7e0c76dec3c4251e578dcf53..ed345ac39f10a670ab7fde521a92bb094be62ac6 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -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(); diff --git a/pc/ns16552.h b/pc/ns16552.h index 30e380c5d5ef5161cbe24ba85460524ed43aedfb..335e7eeb800bd743d01abaca26a247f5da709f9d 100644 --- a/pc/ns16552.h +++ b/pc/ns16552.h @@ -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++; } diff --git a/pc/trap.c b/pc/trap.c index dfb1e5b44e69bf5526389dcdbc6b045cb6ecfb1e..453f057dfb790e4db04bb3e7b261f09c02bdf124 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -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; vnonext){ + 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(); } diff --git a/port/lib.h b/port/lib.h index c82d83a5f3aa3dd64705c31bd9e0722e583bb192..6a277865b896c8724be35a38d11f23258eb4b7d7 100644 --- a/port/lib.h +++ b/port/lib.h @@ -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); diff --git a/port/print.c b/port/print.c index ad1ab994d05eb61c305b4eb4e9fdfb005355acb1..92cb3b9c6b01ba0cd892f5c43a5c58f917c0b0c5 100644 --- a/port/print.c +++ b/port/print.c @@ -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= 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