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