1*7dd7cddfSDavid du Colombier#include <u.h> 2*7dd7cddfSDavid du Colombier#include <libc.h> 3*7dd7cddfSDavid du Colombier 4*7dd7cddfSDavid du Colombierenum 5*7dd7cddfSDavid du Colombier{ 6*7dd7cddfSDavid du Colombier SIZE = 1024, 7*7dd7cddfSDavid du Colombier IDIGIT = 40, 8*7dd7cddfSDavid du Colombier MAXCONV = 40, 9*7dd7cddfSDavid du Colombier FDIGIT = 30, 10*7dd7cddfSDavid du Colombier FDEFLT = 6, 11*7dd7cddfSDavid du Colombier NONE = -1000, 12*7dd7cddfSDavid du Colombier MAXFMT = 512, 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier FPLUS = 1<<0, 15*7dd7cddfSDavid du Colombier FMINUS = 1<<1, 16*7dd7cddfSDavid du Colombier FSHARP = 1<<2, 17*7dd7cddfSDavid du Colombier FLONG = 1<<3, 18*7dd7cddfSDavid du Colombier FSHORT = 1<<4, 19*7dd7cddfSDavid du Colombier FUNSIGN = 1<<5, 20*7dd7cddfSDavid du Colombier FVLONG = 1<<6, 21*7dd7cddfSDavid du Colombier}; 22*7dd7cddfSDavid du Colombier 23*7dd7cddfSDavid du Colombierint printcol; 24*7dd7cddfSDavid du Colombier 25*7dd7cddfSDavid du Colombierstatic int convcount; 26*7dd7cddfSDavid du Colombierstatic char fmtindex[MAXFMT]; 27*7dd7cddfSDavid du Colombier 28*7dd7cddfSDavid du Colombierstatic int noconv(va_list*, Fconv*); 29*7dd7cddfSDavid du Colombierstatic int flags(va_list*, Fconv*); 30*7dd7cddfSDavid du Colombier 31*7dd7cddfSDavid du Colombierstatic int cconv(va_list*, Fconv*); 32*7dd7cddfSDavid du Colombierstatic int rconv(va_list*, Fconv*); 33*7dd7cddfSDavid du Colombierstatic int sconv(va_list*, Fconv*); 34*7dd7cddfSDavid du Colombierstatic int percent(va_list*, Fconv*); 35*7dd7cddfSDavid du Colombierstatic int column(va_list*, Fconv*); 36*7dd7cddfSDavid du Colombier 37*7dd7cddfSDavid du Colombierint numbconv(va_list*, Fconv*); 38*7dd7cddfSDavid du Colombier 39*7dd7cddfSDavid du Colombierstatic 40*7dd7cddfSDavid du Colombierint (*fmtconv[MAXCONV])(va_list*, Fconv*) = 41*7dd7cddfSDavid du Colombier{ 42*7dd7cddfSDavid du Colombier noconv 43*7dd7cddfSDavid du Colombier}; 44*7dd7cddfSDavid du Colombier 45*7dd7cddfSDavid du Colombierstatic 46*7dd7cddfSDavid du Colombiervoid 47*7dd7cddfSDavid du Colombierinitfmt(void) 48*7dd7cddfSDavid du Colombier{ 49*7dd7cddfSDavid du Colombier int cc; 50*7dd7cddfSDavid du Colombier 51*7dd7cddfSDavid du Colombier cc = 0; 52*7dd7cddfSDavid du Colombier fmtconv[cc] = noconv; 53*7dd7cddfSDavid du Colombier cc++; 54*7dd7cddfSDavid du Colombier 55*7dd7cddfSDavid du Colombier fmtconv[cc] = flags; 56*7dd7cddfSDavid du Colombier fmtindex['+'] = cc; 57*7dd7cddfSDavid du Colombier fmtindex['-'] = cc; 58*7dd7cddfSDavid du Colombier fmtindex['#'] = cc; 59*7dd7cddfSDavid du Colombier fmtindex['h'] = cc; 60*7dd7cddfSDavid du Colombier fmtindex['l'] = cc; 61*7dd7cddfSDavid du Colombier fmtindex['u'] = cc; 62*7dd7cddfSDavid du Colombier cc++; 63*7dd7cddfSDavid du Colombier 64*7dd7cddfSDavid du Colombier fmtconv[cc] = numbconv; 65*7dd7cddfSDavid du Colombier fmtindex['d'] = cc; 66*7dd7cddfSDavid du Colombier fmtindex['o'] = cc; 67*7dd7cddfSDavid du Colombier fmtindex['x'] = cc; 68*7dd7cddfSDavid du Colombier fmtindex['X'] = cc; 69*7dd7cddfSDavid du Colombier cc++; 70*7dd7cddfSDavid du Colombier 71*7dd7cddfSDavid du Colombier fmtconv[cc] = cconv; 72*7dd7cddfSDavid du Colombier fmtindex['c'] = cc; 73*7dd7cddfSDavid du Colombier fmtindex['C'] = cc; 74*7dd7cddfSDavid du Colombier cc++; 75*7dd7cddfSDavid du Colombier 76*7dd7cddfSDavid du Colombier fmtconv[cc] = rconv; 77*7dd7cddfSDavid du Colombier fmtindex['r'] = cc; 78*7dd7cddfSDavid du Colombier cc++; 79*7dd7cddfSDavid du Colombier 80*7dd7cddfSDavid du Colombier fmtconv[cc] = sconv; 81*7dd7cddfSDavid du Colombier fmtindex['s'] = cc; 82*7dd7cddfSDavid du Colombier fmtindex['S'] = cc; 83*7dd7cddfSDavid du Colombier cc++; 84*7dd7cddfSDavid du Colombier 85*7dd7cddfSDavid du Colombier fmtconv[cc] = percent; 86*7dd7cddfSDavid du Colombier fmtindex['%'] = cc; 87*7dd7cddfSDavid du Colombier cc++; 88*7dd7cddfSDavid du Colombier 89*7dd7cddfSDavid du Colombier fmtconv[cc] = column; 90*7dd7cddfSDavid du Colombier fmtindex['|'] = cc; 91*7dd7cddfSDavid du Colombier cc++; 92*7dd7cddfSDavid du Colombier 93*7dd7cddfSDavid du Colombier convcount = cc; 94*7dd7cddfSDavid du Colombier} 95*7dd7cddfSDavid du Colombier 96*7dd7cddfSDavid du Colombierint 97*7dd7cddfSDavid du Colombierfmtinstall(int c, int (*f)(va_list*, Fconv*)) 98*7dd7cddfSDavid du Colombier{ 99*7dd7cddfSDavid du Colombier 100*7dd7cddfSDavid du Colombier if(convcount == 0) 101*7dd7cddfSDavid du Colombier initfmt(); 102*7dd7cddfSDavid du Colombier if(c < 0 || c >= MAXFMT) 103*7dd7cddfSDavid du Colombier return -1; 104*7dd7cddfSDavid du Colombier if(convcount >= MAXCONV) 105*7dd7cddfSDavid du Colombier return -1; 106*7dd7cddfSDavid du Colombier fmtconv[convcount] = f; 107*7dd7cddfSDavid du Colombier fmtindex[c] = convcount; 108*7dd7cddfSDavid du Colombier convcount++; 109*7dd7cddfSDavid du Colombier return 0; 110*7dd7cddfSDavid du Colombier} 111*7dd7cddfSDavid du Colombier 112*7dd7cddfSDavid du Colombierchar* 113*7dd7cddfSDavid du Colombierdoprint(char *s, char *es, char *fmt, va_list argp) 114*7dd7cddfSDavid du Colombier{ 115*7dd7cddfSDavid du Colombier int n, c; 116*7dd7cddfSDavid du Colombier Rune rune; 117*7dd7cddfSDavid du Colombier Fconv local; 118*7dd7cddfSDavid du Colombier 119*7dd7cddfSDavid du Colombier if(s >= es) 120*7dd7cddfSDavid du Colombier return s; 121*7dd7cddfSDavid du Colombier local.out = s; 122*7dd7cddfSDavid du Colombier local.eout = es-UTFmax-1; 123*7dd7cddfSDavid du Colombier 124*7dd7cddfSDavid du Colombierloop: 125*7dd7cddfSDavid du Colombier c = *fmt & 0xff; 126*7dd7cddfSDavid du Colombier if(c >= Runeself) { 127*7dd7cddfSDavid du Colombier n = chartorune(&rune, fmt); 128*7dd7cddfSDavid du Colombier fmt += n; 129*7dd7cddfSDavid du Colombier c = rune; 130*7dd7cddfSDavid du Colombier } else 131*7dd7cddfSDavid du Colombier fmt++; 132*7dd7cddfSDavid du Colombier switch(c) { 133*7dd7cddfSDavid du Colombier case 0: 134*7dd7cddfSDavid du Colombier *local.out = 0; 135*7dd7cddfSDavid du Colombier return local.out; 136*7dd7cddfSDavid du Colombier 137*7dd7cddfSDavid du Colombier default: 138*7dd7cddfSDavid du Colombier printcol++; 139*7dd7cddfSDavid du Colombier goto common; 140*7dd7cddfSDavid du Colombier 141*7dd7cddfSDavid du Colombier case '\n': 142*7dd7cddfSDavid du Colombier printcol = 0; 143*7dd7cddfSDavid du Colombier goto common; 144*7dd7cddfSDavid du Colombier 145*7dd7cddfSDavid du Colombier case '\t': 146*7dd7cddfSDavid du Colombier printcol = (printcol+8) & ~7; 147*7dd7cddfSDavid du Colombier goto common; 148*7dd7cddfSDavid du Colombier 149*7dd7cddfSDavid du Colombier common: 150*7dd7cddfSDavid du Colombier if(local.out < local.eout) 151*7dd7cddfSDavid du Colombier if(c >= Runeself) { 152*7dd7cddfSDavid du Colombier rune = c; 153*7dd7cddfSDavid du Colombier n = runetochar(local.out, &rune); 154*7dd7cddfSDavid du Colombier local.out += n; 155*7dd7cddfSDavid du Colombier } else 156*7dd7cddfSDavid du Colombier *local.out++ = c; 157*7dd7cddfSDavid du Colombier goto loop; 158*7dd7cddfSDavid du Colombier 159*7dd7cddfSDavid du Colombier case '%': 160*7dd7cddfSDavid du Colombier break; 161*7dd7cddfSDavid du Colombier } 162*7dd7cddfSDavid du Colombier local.f1 = NONE; 163*7dd7cddfSDavid du Colombier local.f2 = NONE; 164*7dd7cddfSDavid du Colombier local.f3 = 0; 165*7dd7cddfSDavid du Colombier 166*7dd7cddfSDavid du Colombier /* 167*7dd7cddfSDavid du Colombier * read one of the following 168*7dd7cddfSDavid du Colombier * 1. number, => f1, f2 in order. 169*7dd7cddfSDavid du Colombier * 2. '*' same as number (from args) 170*7dd7cddfSDavid du Colombier * 3. '.' ignored (separates numbers) 171*7dd7cddfSDavid du Colombier * 4. flag => f3 172*7dd7cddfSDavid du Colombier * 5. verb and terminate 173*7dd7cddfSDavid du Colombier */ 174*7dd7cddfSDavid du Colombierl0: 175*7dd7cddfSDavid du Colombier c = *fmt & 0xff; 176*7dd7cddfSDavid du Colombier if(c >= Runeself) { 177*7dd7cddfSDavid du Colombier n = chartorune(&rune, fmt); 178*7dd7cddfSDavid du Colombier fmt += n; 179*7dd7cddfSDavid du Colombier c = rune; 180*7dd7cddfSDavid du Colombier } else 181*7dd7cddfSDavid du Colombier fmt++; 182*7dd7cddfSDavid du Colombier 183*7dd7cddfSDavid du Colombierl1: 184*7dd7cddfSDavid du Colombier if(c == 0) { 185*7dd7cddfSDavid du Colombier fmt--; 186*7dd7cddfSDavid du Colombier goto loop; 187*7dd7cddfSDavid du Colombier } 188*7dd7cddfSDavid du Colombier if(c == '.') { 189*7dd7cddfSDavid du Colombier if(local.f1 == NONE) 190*7dd7cddfSDavid du Colombier local.f1 = 0; 191*7dd7cddfSDavid du Colombier local.f2 = 0; 192*7dd7cddfSDavid du Colombier goto l0; 193*7dd7cddfSDavid du Colombier } 194*7dd7cddfSDavid du Colombier if((c >= '1' && c <= '9') || 195*7dd7cddfSDavid du Colombier (c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */ 196*7dd7cddfSDavid du Colombier n = 0; 197*7dd7cddfSDavid du Colombier while(c >= '0' && c <= '9') { 198*7dd7cddfSDavid du Colombier n = n*10 + c-'0'; 199*7dd7cddfSDavid du Colombier c = *fmt++; 200*7dd7cddfSDavid du Colombier } 201*7dd7cddfSDavid du Colombier if(local.f1 == NONE) 202*7dd7cddfSDavid du Colombier local.f1 = n; 203*7dd7cddfSDavid du Colombier else 204*7dd7cddfSDavid du Colombier local.f2 = n; 205*7dd7cddfSDavid du Colombier goto l1; 206*7dd7cddfSDavid du Colombier } 207*7dd7cddfSDavid du Colombier if(c == '*') { 208*7dd7cddfSDavid du Colombier n = va_arg(argp, int); 209*7dd7cddfSDavid du Colombier if(local.f1 == NONE) 210*7dd7cddfSDavid du Colombier local.f1 = n; 211*7dd7cddfSDavid du Colombier else 212*7dd7cddfSDavid du Colombier local.f2 = n; 213*7dd7cddfSDavid du Colombier goto l0; 214*7dd7cddfSDavid du Colombier } 215*7dd7cddfSDavid du Colombier n = 0; 216*7dd7cddfSDavid du Colombier if(c >= 0 && c < MAXFMT) 217*7dd7cddfSDavid du Colombier n = fmtindex[c]; 218*7dd7cddfSDavid du Colombier local.chr = c; 219*7dd7cddfSDavid du Colombier n = (*fmtconv[n])(&argp, &local); 220*7dd7cddfSDavid du Colombier if(n < 0) { 221*7dd7cddfSDavid du Colombier local.f3 |= -n; 222*7dd7cddfSDavid du Colombier goto l0; 223*7dd7cddfSDavid du Colombier } 224*7dd7cddfSDavid du Colombier goto loop; 225*7dd7cddfSDavid du Colombier} 226*7dd7cddfSDavid du Colombier 227*7dd7cddfSDavid du Colombierint 228*7dd7cddfSDavid du Colombiernumbconv(va_list *arg, Fconv *fp) 229*7dd7cddfSDavid du Colombier{ 230*7dd7cddfSDavid du Colombier char s[IDIGIT]; 231*7dd7cddfSDavid du Colombier int i, f, n, b, ucase; 232*7dd7cddfSDavid du Colombier short h; 233*7dd7cddfSDavid du Colombier long v; 234*7dd7cddfSDavid du Colombier vlong vl; 235*7dd7cddfSDavid du Colombier 236*7dd7cddfSDavid du Colombier SET(v); 237*7dd7cddfSDavid du Colombier SET(vl); 238*7dd7cddfSDavid du Colombier 239*7dd7cddfSDavid du Colombier ucase = 0; 240*7dd7cddfSDavid du Colombier b = fp->chr; 241*7dd7cddfSDavid du Colombier switch(fp->chr) { 242*7dd7cddfSDavid du Colombier case 'u': 243*7dd7cddfSDavid du Colombier fp->f3 |= FUNSIGN; 244*7dd7cddfSDavid du Colombier case 'd': 245*7dd7cddfSDavid du Colombier b = 10; 246*7dd7cddfSDavid du Colombier break; 247*7dd7cddfSDavid du Colombier 248*7dd7cddfSDavid du Colombier case 'o': 249*7dd7cddfSDavid du Colombier b = 8; 250*7dd7cddfSDavid du Colombier break; 251*7dd7cddfSDavid du Colombier 252*7dd7cddfSDavid du Colombier case 'X': 253*7dd7cddfSDavid du Colombier ucase = 1; 254*7dd7cddfSDavid du Colombier case 'x': 255*7dd7cddfSDavid du Colombier b = 16; 256*7dd7cddfSDavid du Colombier break; 257*7dd7cddfSDavid du Colombier } 258*7dd7cddfSDavid du Colombier 259*7dd7cddfSDavid du Colombier f = 0; 260*7dd7cddfSDavid du Colombier switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { 261*7dd7cddfSDavid du Colombier case FVLONG|FLONG: 262*7dd7cddfSDavid du Colombier vl = va_arg(*arg, vlong); 263*7dd7cddfSDavid du Colombier break; 264*7dd7cddfSDavid du Colombier 265*7dd7cddfSDavid du Colombier case FUNSIGN|FVLONG|FLONG: 266*7dd7cddfSDavid du Colombier vl = va_arg(*arg, uvlong); 267*7dd7cddfSDavid du Colombier break; 268*7dd7cddfSDavid du Colombier 269*7dd7cddfSDavid du Colombier case FLONG: 270*7dd7cddfSDavid du Colombier v = va_arg(*arg, long); 271*7dd7cddfSDavid du Colombier break; 272*7dd7cddfSDavid du Colombier 273*7dd7cddfSDavid du Colombier case FUNSIGN|FLONG: 274*7dd7cddfSDavid du Colombier v = va_arg(*arg, ulong); 275*7dd7cddfSDavid du Colombier break; 276*7dd7cddfSDavid du Colombier 277*7dd7cddfSDavid du Colombier case FSHORT: 278*7dd7cddfSDavid du Colombier h = va_arg(*arg, int); 279*7dd7cddfSDavid du Colombier v = h; 280*7dd7cddfSDavid du Colombier break; 281*7dd7cddfSDavid du Colombier 282*7dd7cddfSDavid du Colombier case FUNSIGN|FSHORT: 283*7dd7cddfSDavid du Colombier h = va_arg(*arg, int); 284*7dd7cddfSDavid du Colombier v = (ushort)h; 285*7dd7cddfSDavid du Colombier break; 286*7dd7cddfSDavid du Colombier 287*7dd7cddfSDavid du Colombier default: 288*7dd7cddfSDavid du Colombier v = va_arg(*arg, int); 289*7dd7cddfSDavid du Colombier break; 290*7dd7cddfSDavid du Colombier 291*7dd7cddfSDavid du Colombier case FUNSIGN: 292*7dd7cddfSDavid du Colombier v = va_arg(*arg, unsigned); 293*7dd7cddfSDavid du Colombier break; 294*7dd7cddfSDavid du Colombier } 295*7dd7cddfSDavid du Colombier if(fp->f3 & FVLONG) { 296*7dd7cddfSDavid du Colombier if(!(fp->f3 & FUNSIGN) && vl < 0) { 297*7dd7cddfSDavid du Colombier vl = -vl; 298*7dd7cddfSDavid du Colombier f = 1; 299*7dd7cddfSDavid du Colombier } 300*7dd7cddfSDavid du Colombier } else { 301*7dd7cddfSDavid du Colombier if(!(fp->f3 & FUNSIGN) && v < 0) { 302*7dd7cddfSDavid du Colombier v = -v; 303*7dd7cddfSDavid du Colombier f = 1; 304*7dd7cddfSDavid du Colombier } 305*7dd7cddfSDavid du Colombier } 306*7dd7cddfSDavid du Colombier s[IDIGIT-1] = 0; 307*7dd7cddfSDavid du Colombier for(i = IDIGIT-2;; i--) { 308*7dd7cddfSDavid du Colombier if(fp->f3 & FVLONG) 309*7dd7cddfSDavid du Colombier n = (uvlong)vl % b; 310*7dd7cddfSDavid du Colombier else 311*7dd7cddfSDavid du Colombier n = (ulong)v % b; 312*7dd7cddfSDavid du Colombier n += '0'; 313*7dd7cddfSDavid du Colombier if(n > '9') { 314*7dd7cddfSDavid du Colombier n += 'a' - ('9'+1); 315*7dd7cddfSDavid du Colombier if(ucase) 316*7dd7cddfSDavid du Colombier n += 'A'-'a'; 317*7dd7cddfSDavid du Colombier } 318*7dd7cddfSDavid du Colombier s[i] = n; 319*7dd7cddfSDavid du Colombier if(i < 2) 320*7dd7cddfSDavid du Colombier break; 321*7dd7cddfSDavid du Colombier if(fp->f3 & FVLONG) 322*7dd7cddfSDavid du Colombier vl = (uvlong)vl / b; 323*7dd7cddfSDavid du Colombier else 324*7dd7cddfSDavid du Colombier v = (ulong)v / b; 325*7dd7cddfSDavid du Colombier if(fp->f2 != NONE && i >= IDIGIT-fp->f2) 326*7dd7cddfSDavid du Colombier continue; 327*7dd7cddfSDavid du Colombier if(fp->f3 & FVLONG) { 328*7dd7cddfSDavid du Colombier if(vl <= 0) 329*7dd7cddfSDavid du Colombier break; 330*7dd7cddfSDavid du Colombier continue; 331*7dd7cddfSDavid du Colombier } 332*7dd7cddfSDavid du Colombier if(v <= 0) 333*7dd7cddfSDavid du Colombier break; 334*7dd7cddfSDavid du Colombier } 335*7dd7cddfSDavid du Colombier 336*7dd7cddfSDavid du Colombier if(fp->f3 & FSHARP) { 337*7dd7cddfSDavid du Colombier if(b == 8 && s[i] != '0') 338*7dd7cddfSDavid du Colombier s[--i] = '0'; 339*7dd7cddfSDavid du Colombier if(b == 16) { 340*7dd7cddfSDavid du Colombier if(ucase) 341*7dd7cddfSDavid du Colombier s[--i] = 'X'; 342*7dd7cddfSDavid du Colombier else 343*7dd7cddfSDavid du Colombier s[--i] = 'x'; 344*7dd7cddfSDavid du Colombier s[--i] = '0'; 345*7dd7cddfSDavid du Colombier } 346*7dd7cddfSDavid du Colombier } 347*7dd7cddfSDavid du Colombier if(f) 348*7dd7cddfSDavid du Colombier s[--i] = '-'; 349*7dd7cddfSDavid du Colombier fp->f2 = NONE; 350*7dd7cddfSDavid du Colombier strconv(s+i, fp); 351*7dd7cddfSDavid du Colombier return 0; 352*7dd7cddfSDavid du Colombier} 353*7dd7cddfSDavid du Colombier 354*7dd7cddfSDavid du Colombiervoid 355*7dd7cddfSDavid du ColombierStrconv(Rune *s, Fconv *fp) 356*7dd7cddfSDavid du Colombier{ 357*7dd7cddfSDavid du Colombier int n, c, i; 358*7dd7cddfSDavid du Colombier Rune rune; 359*7dd7cddfSDavid du Colombier 360*7dd7cddfSDavid du Colombier if(fp->f3 & FMINUS) 361*7dd7cddfSDavid du Colombier fp->f1 = -fp->f1; 362*7dd7cddfSDavid du Colombier n = 0; 363*7dd7cddfSDavid du Colombier if(fp->f1 != NONE && fp->f1 >= 0) { 364*7dd7cddfSDavid du Colombier for(; s[n]; n++) 365*7dd7cddfSDavid du Colombier ; 366*7dd7cddfSDavid du Colombier while(n < fp->f1) { 367*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 368*7dd7cddfSDavid du Colombier *fp->out++ = ' '; 369*7dd7cddfSDavid du Colombier printcol++; 370*7dd7cddfSDavid du Colombier n++; 371*7dd7cddfSDavid du Colombier } 372*7dd7cddfSDavid du Colombier } 373*7dd7cddfSDavid du Colombier for(;;) { 374*7dd7cddfSDavid du Colombier c = *s++; 375*7dd7cddfSDavid du Colombier if(c == 0) 376*7dd7cddfSDavid du Colombier break; 377*7dd7cddfSDavid du Colombier n++; 378*7dd7cddfSDavid du Colombier if(fp->f2 == NONE || fp->f2 > 0) { 379*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 380*7dd7cddfSDavid du Colombier if(c >= Runeself) { 381*7dd7cddfSDavid du Colombier rune = c; 382*7dd7cddfSDavid du Colombier i = runetochar(fp->out, &rune); 383*7dd7cddfSDavid du Colombier fp->out += i; 384*7dd7cddfSDavid du Colombier } else 385*7dd7cddfSDavid du Colombier *fp->out++ = c; 386*7dd7cddfSDavid du Colombier if(fp->f2 != NONE) 387*7dd7cddfSDavid du Colombier fp->f2--; 388*7dd7cddfSDavid du Colombier switch(c) { 389*7dd7cddfSDavid du Colombier default: 390*7dd7cddfSDavid du Colombier printcol++; 391*7dd7cddfSDavid du Colombier break; 392*7dd7cddfSDavid du Colombier case '\n': 393*7dd7cddfSDavid du Colombier printcol = 0; 394*7dd7cddfSDavid du Colombier break; 395*7dd7cddfSDavid du Colombier case '\t': 396*7dd7cddfSDavid du Colombier printcol = (printcol+8) & ~7; 397*7dd7cddfSDavid du Colombier break; 398*7dd7cddfSDavid du Colombier } 399*7dd7cddfSDavid du Colombier } 400*7dd7cddfSDavid du Colombier } 401*7dd7cddfSDavid du Colombier if(fp->f1 != NONE && fp->f1 < 0) { 402*7dd7cddfSDavid du Colombier fp->f1 = -fp->f1; 403*7dd7cddfSDavid du Colombier while(n < fp->f1) { 404*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 405*7dd7cddfSDavid du Colombier *fp->out++ = ' '; 406*7dd7cddfSDavid du Colombier printcol++; 407*7dd7cddfSDavid du Colombier n++; 408*7dd7cddfSDavid du Colombier } 409*7dd7cddfSDavid du Colombier } 410*7dd7cddfSDavid du Colombier} 411*7dd7cddfSDavid du Colombier 412*7dd7cddfSDavid du Colombiervoid 413*7dd7cddfSDavid du Colombierstrconv(char *s, Fconv *fp) 414*7dd7cddfSDavid du Colombier{ 415*7dd7cddfSDavid du Colombier int n, c, i; 416*7dd7cddfSDavid du Colombier Rune rune; 417*7dd7cddfSDavid du Colombier 418*7dd7cddfSDavid du Colombier if(fp->f3 & FMINUS) 419*7dd7cddfSDavid du Colombier fp->f1 = -fp->f1; 420*7dd7cddfSDavid du Colombier n = 0; 421*7dd7cddfSDavid du Colombier if(fp->f1 != NONE && fp->f1 >= 0) { 422*7dd7cddfSDavid du Colombier n = utflen(s); 423*7dd7cddfSDavid du Colombier while(n < fp->f1) { 424*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 425*7dd7cddfSDavid du Colombier *fp->out++ = ' '; 426*7dd7cddfSDavid du Colombier printcol++; 427*7dd7cddfSDavid du Colombier n++; 428*7dd7cddfSDavid du Colombier } 429*7dd7cddfSDavid du Colombier } 430*7dd7cddfSDavid du Colombier for(;;) { 431*7dd7cddfSDavid du Colombier c = *s & 0xff; 432*7dd7cddfSDavid du Colombier if(c >= Runeself) { 433*7dd7cddfSDavid du Colombier i = chartorune(&rune, s); 434*7dd7cddfSDavid du Colombier s += i; 435*7dd7cddfSDavid du Colombier c = rune; 436*7dd7cddfSDavid du Colombier } else 437*7dd7cddfSDavid du Colombier s++; 438*7dd7cddfSDavid du Colombier if(c == 0) 439*7dd7cddfSDavid du Colombier break; 440*7dd7cddfSDavid du Colombier n++; 441*7dd7cddfSDavid du Colombier if(fp->f2 == NONE || fp->f2 > 0) { 442*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 443*7dd7cddfSDavid du Colombier if(c >= Runeself) { 444*7dd7cddfSDavid du Colombier rune = c; 445*7dd7cddfSDavid du Colombier i = runetochar(fp->out, &rune); 446*7dd7cddfSDavid du Colombier fp->out += i; 447*7dd7cddfSDavid du Colombier } else 448*7dd7cddfSDavid du Colombier *fp->out++ = c; 449*7dd7cddfSDavid du Colombier if(fp->f2 != NONE) 450*7dd7cddfSDavid du Colombier fp->f2--; 451*7dd7cddfSDavid du Colombier switch(c) { 452*7dd7cddfSDavid du Colombier default: 453*7dd7cddfSDavid du Colombier printcol++; 454*7dd7cddfSDavid du Colombier break; 455*7dd7cddfSDavid du Colombier case '\n': 456*7dd7cddfSDavid du Colombier printcol = 0; 457*7dd7cddfSDavid du Colombier break; 458*7dd7cddfSDavid du Colombier case '\t': 459*7dd7cddfSDavid du Colombier printcol = (printcol+8) & ~7; 460*7dd7cddfSDavid du Colombier break; 461*7dd7cddfSDavid du Colombier } 462*7dd7cddfSDavid du Colombier } 463*7dd7cddfSDavid du Colombier } 464*7dd7cddfSDavid du Colombier if(fp->f1 != NONE && fp->f1 < 0) { 465*7dd7cddfSDavid du Colombier fp->f1 = -fp->f1; 466*7dd7cddfSDavid du Colombier while(n < fp->f1) { 467*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 468*7dd7cddfSDavid du Colombier *fp->out++ = ' '; 469*7dd7cddfSDavid du Colombier printcol++; 470*7dd7cddfSDavid du Colombier n++; 471*7dd7cddfSDavid du Colombier } 472*7dd7cddfSDavid du Colombier } 473*7dd7cddfSDavid du Colombier} 474*7dd7cddfSDavid du Colombier 475*7dd7cddfSDavid du Colombierstatic 476*7dd7cddfSDavid du Colombierint 477*7dd7cddfSDavid du Colombiernoconv(va_list *arg, Fconv *fp) 478*7dd7cddfSDavid du Colombier{ 479*7dd7cddfSDavid du Colombier int n; 480*7dd7cddfSDavid du Colombier char s[10]; 481*7dd7cddfSDavid du Colombier 482*7dd7cddfSDavid du Colombier if(convcount == 0) { 483*7dd7cddfSDavid du Colombier initfmt(); 484*7dd7cddfSDavid du Colombier n = 0; 485*7dd7cddfSDavid du Colombier if(fp->chr >= 0 && fp->chr < MAXFMT) 486*7dd7cddfSDavid du Colombier n = fmtindex[fp->chr]; 487*7dd7cddfSDavid du Colombier return (*fmtconv[n])(arg, fp); 488*7dd7cddfSDavid du Colombier } 489*7dd7cddfSDavid du Colombier s[0] = '*'; 490*7dd7cddfSDavid du Colombier s[1] = fp->chr; 491*7dd7cddfSDavid du Colombier s[2] = '*'; 492*7dd7cddfSDavid du Colombier s[3] = 0; 493*7dd7cddfSDavid du Colombier fp->f1 = 0; 494*7dd7cddfSDavid du Colombier fp->f2 = NONE; 495*7dd7cddfSDavid du Colombier fp->f3 = 0; 496*7dd7cddfSDavid du Colombier strconv(s, fp); 497*7dd7cddfSDavid du Colombier return 0; 498*7dd7cddfSDavid du Colombier} 499*7dd7cddfSDavid du Colombier 500*7dd7cddfSDavid du Colombierstatic 501*7dd7cddfSDavid du Colombierint 502*7dd7cddfSDavid du Colombierrconv(va_list*, Fconv *fp) 503*7dd7cddfSDavid du Colombier{ 504*7dd7cddfSDavid du Colombier char s[ERRLEN]; 505*7dd7cddfSDavid du Colombier 506*7dd7cddfSDavid du Colombier s[0] = 0; 507*7dd7cddfSDavid du Colombier errstr(s); 508*7dd7cddfSDavid du Colombier fp->f2 = NONE; 509*7dd7cddfSDavid du Colombier strconv(s, fp); 510*7dd7cddfSDavid du Colombier return 0; 511*7dd7cddfSDavid du Colombier} 512*7dd7cddfSDavid du Colombier 513*7dd7cddfSDavid du Colombierstatic 514*7dd7cddfSDavid du Colombierint 515*7dd7cddfSDavid du Colombiercconv(va_list *arg, Fconv *fp) 516*7dd7cddfSDavid du Colombier{ 517*7dd7cddfSDavid du Colombier char s[10]; 518*7dd7cddfSDavid du Colombier Rune rune; 519*7dd7cddfSDavid du Colombier 520*7dd7cddfSDavid du Colombier rune = va_arg(*arg, int); 521*7dd7cddfSDavid du Colombier if(fp->chr == 'c') 522*7dd7cddfSDavid du Colombier rune &= 0xff; 523*7dd7cddfSDavid du Colombier s[runetochar(s, &rune)] = 0; 524*7dd7cddfSDavid du Colombier 525*7dd7cddfSDavid du Colombier fp->f2 = NONE; 526*7dd7cddfSDavid du Colombier strconv(s, fp); 527*7dd7cddfSDavid du Colombier return 0; 528*7dd7cddfSDavid du Colombier} 529*7dd7cddfSDavid du Colombier 530*7dd7cddfSDavid du Colombierstatic 531*7dd7cddfSDavid du Colombierint 532*7dd7cddfSDavid du Colombiersconv(va_list *arg, Fconv *fp) 533*7dd7cddfSDavid du Colombier{ 534*7dd7cddfSDavid du Colombier char *s; 535*7dd7cddfSDavid du Colombier Rune *r; 536*7dd7cddfSDavid du Colombier 537*7dd7cddfSDavid du Colombier if(fp->chr == 's') { 538*7dd7cddfSDavid du Colombier s = va_arg(*arg, char*); 539*7dd7cddfSDavid du Colombier if(s == 0) 540*7dd7cddfSDavid du Colombier s = "<null>"; 541*7dd7cddfSDavid du Colombier strconv(s, fp); 542*7dd7cddfSDavid du Colombier } else { 543*7dd7cddfSDavid du Colombier r = va_arg(*arg, Rune*); 544*7dd7cddfSDavid du Colombier if(r == 0) 545*7dd7cddfSDavid du Colombier r = L"<null>"; 546*7dd7cddfSDavid du Colombier Strconv(r, fp); 547*7dd7cddfSDavid du Colombier } 548*7dd7cddfSDavid du Colombier return 0; 549*7dd7cddfSDavid du Colombier} 550*7dd7cddfSDavid du Colombier 551*7dd7cddfSDavid du Colombierstatic 552*7dd7cddfSDavid du Colombierint 553*7dd7cddfSDavid du Colombierpercent(va_list*, Fconv *fp) 554*7dd7cddfSDavid du Colombier{ 555*7dd7cddfSDavid du Colombier 556*7dd7cddfSDavid du Colombier if(fp->out < fp->eout) 557*7dd7cddfSDavid du Colombier *fp->out++ = '%'; 558*7dd7cddfSDavid du Colombier printcol++; 559*7dd7cddfSDavid du Colombier return 0; 560*7dd7cddfSDavid du Colombier} 561*7dd7cddfSDavid du Colombier 562*7dd7cddfSDavid du Colombierstatic 563*7dd7cddfSDavid du Colombierint 564*7dd7cddfSDavid du Colombiercolumn(va_list *arg, Fconv *fp) 565*7dd7cddfSDavid du Colombier{ 566*7dd7cddfSDavid du Colombier int col, pc; 567*7dd7cddfSDavid du Colombier 568*7dd7cddfSDavid du Colombier col = va_arg(*arg, int); 569*7dd7cddfSDavid du Colombier while(fp->out < fp->eout && printcol < col) { 570*7dd7cddfSDavid du Colombier pc = (printcol+8) & ~7; 571*7dd7cddfSDavid du Colombier if(pc <= col) { 572*7dd7cddfSDavid du Colombier *fp->out++ = '\t'; 573*7dd7cddfSDavid du Colombier printcol = pc; 574*7dd7cddfSDavid du Colombier } else { 575*7dd7cddfSDavid du Colombier *fp->out++ = ' '; 576*7dd7cddfSDavid du Colombier printcol++; 577*7dd7cddfSDavid du Colombier } 578*7dd7cddfSDavid du Colombier } 579*7dd7cddfSDavid du Colombier return 0; 580*7dd7cddfSDavid du Colombier} 581*7dd7cddfSDavid du Colombier 582*7dd7cddfSDavid du Colombierstatic 583*7dd7cddfSDavid du Colombierint 584*7dd7cddfSDavid du Colombierflags(va_list*, Fconv *fp) 585*7dd7cddfSDavid du Colombier{ 586*7dd7cddfSDavid du Colombier int f; 587*7dd7cddfSDavid du Colombier 588*7dd7cddfSDavid du Colombier f = 0; 589*7dd7cddfSDavid du Colombier switch(fp->chr) { 590*7dd7cddfSDavid du Colombier case '+': 591*7dd7cddfSDavid du Colombier f = FPLUS; 592*7dd7cddfSDavid du Colombier break; 593*7dd7cddfSDavid du Colombier 594*7dd7cddfSDavid du Colombier case '-': 595*7dd7cddfSDavid du Colombier f = FMINUS; 596*7dd7cddfSDavid du Colombier break; 597*7dd7cddfSDavid du Colombier 598*7dd7cddfSDavid du Colombier case '#': 599*7dd7cddfSDavid du Colombier f = FSHARP; 600*7dd7cddfSDavid du Colombier break; 601*7dd7cddfSDavid du Colombier 602*7dd7cddfSDavid du Colombier case 'h': 603*7dd7cddfSDavid du Colombier f = FSHORT; 604*7dd7cddfSDavid du Colombier break; 605*7dd7cddfSDavid du Colombier 606*7dd7cddfSDavid du Colombier case 'l': 607*7dd7cddfSDavid du Colombier f = FLONG; 608*7dd7cddfSDavid du Colombier if(fp->f3 & FLONG) 609*7dd7cddfSDavid du Colombier f = FVLONG; 610*7dd7cddfSDavid du Colombier break; 611*7dd7cddfSDavid du Colombier 612*7dd7cddfSDavid du Colombier case 'u': 613*7dd7cddfSDavid du Colombier f = FUNSIGN; 614*7dd7cddfSDavid du Colombier break; 615*7dd7cddfSDavid du Colombier } 616*7dd7cddfSDavid du Colombier return -f; 617*7dd7cddfSDavid du Colombier} 618