int fmtinstall(int c, int (*f)(va_list*, Fconv*)) { if(convcount == 0) initfmt(); if(c < 0 || c >= MAXFMT) return -1; if(convcount >= MAXCONV) return -1; fmtconv[convcount] = f; fmtindex[c] = convcount; convcount++; return 0; }
int fmtinstall(int c, int (*f)(va_list*, Fconv*)) { if(fmtalloc.convcount <= 0) initfmt(); lock(&fmtalloc); if(c < 0 || c >= MAXFMT) { unlock(&fmtalloc); return -1; } if(fmtalloc.convcount >= MAXCONV) { unlock(&fmtalloc); return -1; } fmtalloc.conv[fmtalloc.convcount] = f; fmtalloc.index[c] = fmtalloc.convcount; fmtalloc.convcount++; unlock(&fmtalloc); return 0; }
char* doprint(char *s, char *es, char *fmt, va_list *argp) { int n, c; Rune rune; Fconv local; if(fmtalloc.convcount <= 0) initfmt(); if(s >= es) return s; local.out = s; local.eout = es-1; loop: c = *fmt & 0xff; if(c >= Runeself) { n = chartorune(&rune, fmt); fmt += n; c = rune; } else fmt++; switch(c) { case 0: *local.out = 0; return local.out; default: printcol++; goto common; case '\n': printcol = 0; goto common; case '\t': printcol = (printcol+8) & ~7; goto common; common: pchar(c, &local); goto loop; case '%': break; } local.f1 = NONE; local.f2 = NONE; local.f3 = 0; /* * read one of the following * 1. number, => f1, f2 in order. * 2. '*' same as number (from args) * 3. '.' ignored (separates numbers) * 4. flag => f3 * 5. verb and terminate */ l0: c = *fmt & 0xff; if(c >= Runeself) { n = chartorune(&rune, fmt); fmt += n; c = rune; } else fmt++; l1: if(c == 0) { fmt--; goto loop; } if(c == '.') { if(local.f1 == NONE) local.f1 = 0; local.f2 = 0; goto l0; } if((c >= '1' && c <= '9') || (c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */ n = 0; while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = *fmt++; } if(local.f1 == NONE) local.f1 = n; else local.f2 = n; goto l1; } if(c == '*') { n = va_arg(*argp, int); if(local.f1 == NONE) local.f1 = n; else local.f2 = n; goto l0; }