19a747e4fSDavid du Colombier #include <plan9.h>
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier #define lock(x)
49a747e4fSDavid du Colombier #define unlock(x)
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier enum
79a747e4fSDavid du Colombier {
89a747e4fSDavid du Colombier IDIGIT = 40,
99a747e4fSDavid du Colombier MAXCONV = 40,
109a747e4fSDavid du Colombier FDIGIT = 30,
119a747e4fSDavid du Colombier FDEFLT = 6,
129a747e4fSDavid du Colombier NONE = -1000,
139a747e4fSDavid du Colombier MAXFMT = 512,
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier FPLUS = 1<<0,
169a747e4fSDavid du Colombier FMINUS = 1<<1,
179a747e4fSDavid du Colombier FSHARP = 1<<2,
189a747e4fSDavid du Colombier FLONG = 1<<3,
199a747e4fSDavid du Colombier FUNSIGN = 1<<5,
209a747e4fSDavid du Colombier FVLONG = 1<<6,
219a747e4fSDavid du Colombier FPOINTER= 1<<7
229a747e4fSDavid du Colombier };
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier int printcol;
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier static struct
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier /* Lock; */
299a747e4fSDavid du Colombier int convcount;
309a747e4fSDavid du Colombier char index[MAXFMT];
319a747e4fSDavid du Colombier int (*conv[MAXCONV])(va_list*, Fconv*);
329a747e4fSDavid du Colombier } fmtalloc;
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier static int noconv(va_list*, Fconv*);
359a747e4fSDavid du Colombier static int flags(va_list*, Fconv*);
369a747e4fSDavid du Colombier
379a747e4fSDavid du Colombier static int cconv(va_list*, Fconv*);
389a747e4fSDavid du Colombier static int sconv(va_list*, Fconv*);
399a747e4fSDavid du Colombier static int percent(va_list*, Fconv*);
409a747e4fSDavid du Colombier static int column(va_list*, Fconv*);
419a747e4fSDavid du Colombier
429a747e4fSDavid du Colombier extern int numbconv(va_list*, Fconv*);
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier static void
initfmt(void)469a747e4fSDavid du Colombier initfmt(void)
479a747e4fSDavid du Colombier {
489a747e4fSDavid du Colombier int cc;
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier lock(&fmtalloc);
519a747e4fSDavid du Colombier if(fmtalloc.convcount <= 0) {
529a747e4fSDavid du Colombier cc = 0;
539a747e4fSDavid du Colombier fmtalloc.conv[cc] = noconv;
549a747e4fSDavid du Colombier cc++;
559a747e4fSDavid du Colombier
569a747e4fSDavid du Colombier fmtalloc.conv[cc] = flags;
579a747e4fSDavid du Colombier fmtalloc.index['+'] = cc;
589a747e4fSDavid du Colombier fmtalloc.index['-'] = cc;
599a747e4fSDavid du Colombier fmtalloc.index['#'] = cc;
609a747e4fSDavid du Colombier fmtalloc.index['l'] = cc;
619a747e4fSDavid du Colombier fmtalloc.index['u'] = cc;
629a747e4fSDavid du Colombier cc++;
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier fmtalloc.conv[cc] = numbconv;
659a747e4fSDavid du Colombier fmtalloc.index['d'] = cc;
669a747e4fSDavid du Colombier fmtalloc.index['o'] = cc;
679a747e4fSDavid du Colombier fmtalloc.index['x'] = cc;
689a747e4fSDavid du Colombier fmtalloc.index['X'] = cc;
699a747e4fSDavid du Colombier fmtalloc.index['p'] = cc;
709a747e4fSDavid du Colombier cc++;
719a747e4fSDavid du Colombier
729a747e4fSDavid du Colombier
739a747e4fSDavid du Colombier fmtalloc.conv[cc] = cconv;
749a747e4fSDavid du Colombier fmtalloc.index['c'] = cc;
759a747e4fSDavid du Colombier fmtalloc.index['C'] = cc;
769a747e4fSDavid du Colombier cc++;
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier fmtalloc.conv[cc] = sconv;
799a747e4fSDavid du Colombier fmtalloc.index['s'] = cc;
809a747e4fSDavid du Colombier fmtalloc.index['S'] = cc;
819a747e4fSDavid du Colombier cc++;
829a747e4fSDavid du Colombier
839a747e4fSDavid du Colombier fmtalloc.conv[cc] = percent;
849a747e4fSDavid du Colombier fmtalloc.index['%'] = cc;
859a747e4fSDavid du Colombier cc++;
869a747e4fSDavid du Colombier
879a747e4fSDavid du Colombier fmtalloc.conv[cc] = column;
889a747e4fSDavid du Colombier fmtalloc.index['|'] = cc;
899a747e4fSDavid du Colombier cc++;
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier fmtalloc.convcount = cc;
929a747e4fSDavid du Colombier }
939a747e4fSDavid du Colombier unlock(&fmtalloc);
949a747e4fSDavid du Colombier }
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier int
fmtinstall(int c,int (* f)(va_list *,Fconv *))979a747e4fSDavid du Colombier fmtinstall(int c, int (*f)(va_list*, Fconv*))
989a747e4fSDavid du Colombier {
999a747e4fSDavid du Colombier
1009a747e4fSDavid du Colombier if(fmtalloc.convcount <= 0)
1019a747e4fSDavid du Colombier initfmt();
1029a747e4fSDavid du Colombier
1039a747e4fSDavid du Colombier lock(&fmtalloc);
1049a747e4fSDavid du Colombier if(c < 0 || c >= MAXFMT) {
1059a747e4fSDavid du Colombier unlock(&fmtalloc);
1069a747e4fSDavid du Colombier return -1;
1079a747e4fSDavid du Colombier }
1089a747e4fSDavid du Colombier if(fmtalloc.convcount >= MAXCONV) {
1099a747e4fSDavid du Colombier unlock(&fmtalloc);
1109a747e4fSDavid du Colombier return -1;
1119a747e4fSDavid du Colombier }
1129a747e4fSDavid du Colombier fmtalloc.conv[fmtalloc.convcount] = f;
1139a747e4fSDavid du Colombier fmtalloc.index[c] = fmtalloc.convcount;
1149a747e4fSDavid du Colombier fmtalloc.convcount++;
1159a747e4fSDavid du Colombier
1169a747e4fSDavid du Colombier unlock(&fmtalloc);
1179a747e4fSDavid du Colombier return 0;
1189a747e4fSDavid du Colombier }
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier static void
pchar(Rune c,Fconv * fp)1219a747e4fSDavid du Colombier pchar(Rune c, Fconv *fp)
1229a747e4fSDavid du Colombier {
1239a747e4fSDavid du Colombier int n;
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier n = fp->eout - fp->out;
1269a747e4fSDavid du Colombier if(n > 0) {
1279a747e4fSDavid du Colombier if(c < Runeself) {
1289a747e4fSDavid du Colombier *fp->out++ = c;
1299a747e4fSDavid du Colombier return;
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier if(n >= UTFmax || n >= runelen(c)) {
1329a747e4fSDavid du Colombier n = runetochar(fp->out, &c);
1339a747e4fSDavid du Colombier fp->out += n;
1349a747e4fSDavid du Colombier return;
1359a747e4fSDavid du Colombier }
1369a747e4fSDavid du Colombier fp->eout = fp->out;
1379a747e4fSDavid du Colombier }
1389a747e4fSDavid du Colombier }
1399a747e4fSDavid du Colombier
1409a747e4fSDavid du Colombier char*
doprint(char * s,char * es,char * fmt,va_list * argp)141*9df35464SDavid du Colombier doprint(char *s, char *es, char *fmt, va_list *argp)
1429a747e4fSDavid du Colombier {
1439a747e4fSDavid du Colombier int n, c;
1449a747e4fSDavid du Colombier Rune rune;
1459a747e4fSDavid du Colombier Fconv local;
1469a747e4fSDavid du Colombier
1479a747e4fSDavid du Colombier if(fmtalloc.convcount <= 0)
1489a747e4fSDavid du Colombier initfmt();
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier if(s >= es)
1519a747e4fSDavid du Colombier return s;
1529a747e4fSDavid du Colombier local.out = s;
1539a747e4fSDavid du Colombier local.eout = es-1;
1549a747e4fSDavid du Colombier
1559a747e4fSDavid du Colombier loop:
1569a747e4fSDavid du Colombier c = *fmt & 0xff;
1579a747e4fSDavid du Colombier if(c >= Runeself) {
1589a747e4fSDavid du Colombier n = chartorune(&rune, fmt);
1599a747e4fSDavid du Colombier fmt += n;
1609a747e4fSDavid du Colombier c = rune;
1619a747e4fSDavid du Colombier } else
1629a747e4fSDavid du Colombier fmt++;
1639a747e4fSDavid du Colombier switch(c) {
1649a747e4fSDavid du Colombier case 0:
1659a747e4fSDavid du Colombier *local.out = 0;
1669a747e4fSDavid du Colombier return local.out;
1679a747e4fSDavid du Colombier
1689a747e4fSDavid du Colombier default:
1699a747e4fSDavid du Colombier printcol++;
1709a747e4fSDavid du Colombier goto common;
1719a747e4fSDavid du Colombier
1729a747e4fSDavid du Colombier case '\n':
1739a747e4fSDavid du Colombier printcol = 0;
1749a747e4fSDavid du Colombier goto common;
1759a747e4fSDavid du Colombier
1769a747e4fSDavid du Colombier case '\t':
1779a747e4fSDavid du Colombier printcol = (printcol+8) & ~7;
1789a747e4fSDavid du Colombier goto common;
1799a747e4fSDavid du Colombier
1809a747e4fSDavid du Colombier common:
1819a747e4fSDavid du Colombier pchar(c, &local);
1829a747e4fSDavid du Colombier goto loop;
1839a747e4fSDavid du Colombier
1849a747e4fSDavid du Colombier case '%':
1859a747e4fSDavid du Colombier break;
1869a747e4fSDavid du Colombier }
1879a747e4fSDavid du Colombier local.f1 = NONE;
1889a747e4fSDavid du Colombier local.f2 = NONE;
1899a747e4fSDavid du Colombier local.f3 = 0;
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier /*
1929a747e4fSDavid du Colombier * read one of the following
1939a747e4fSDavid du Colombier * 1. number, => f1, f2 in order.
1949a747e4fSDavid du Colombier * 2. '*' same as number (from args)
1959a747e4fSDavid du Colombier * 3. '.' ignored (separates numbers)
1969a747e4fSDavid du Colombier * 4. flag => f3
1979a747e4fSDavid du Colombier * 5. verb and terminate
1989a747e4fSDavid du Colombier */
1999a747e4fSDavid du Colombier l0:
2009a747e4fSDavid du Colombier c = *fmt & 0xff;
2019a747e4fSDavid du Colombier if(c >= Runeself) {
2029a747e4fSDavid du Colombier n = chartorune(&rune, fmt);
2039a747e4fSDavid du Colombier fmt += n;
2049a747e4fSDavid du Colombier c = rune;
2059a747e4fSDavid du Colombier } else
2069a747e4fSDavid du Colombier fmt++;
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier l1:
2099a747e4fSDavid du Colombier if(c == 0) {
2109a747e4fSDavid du Colombier fmt--;
2119a747e4fSDavid du Colombier goto loop;
2129a747e4fSDavid du Colombier }
2139a747e4fSDavid du Colombier if(c == '.') {
2149a747e4fSDavid du Colombier if(local.f1 == NONE)
2159a747e4fSDavid du Colombier local.f1 = 0;
2169a747e4fSDavid du Colombier local.f2 = 0;
2179a747e4fSDavid du Colombier goto l0;
2189a747e4fSDavid du Colombier }
2199a747e4fSDavid du Colombier if((c >= '1' && c <= '9') ||
2209a747e4fSDavid du Colombier (c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */
2219a747e4fSDavid du Colombier n = 0;
2229a747e4fSDavid du Colombier while(c >= '0' && c <= '9') {
2239a747e4fSDavid du Colombier n = n*10 + c-'0';
2249a747e4fSDavid du Colombier c = *fmt++;
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier if(local.f1 == NONE)
2279a747e4fSDavid du Colombier local.f1 = n;
2289a747e4fSDavid du Colombier else
2299a747e4fSDavid du Colombier local.f2 = n;
2309a747e4fSDavid du Colombier goto l1;
2319a747e4fSDavid du Colombier }
2329a747e4fSDavid du Colombier if(c == '*') {
233*9df35464SDavid du Colombier n = va_arg(*argp, int);
2349a747e4fSDavid du Colombier if(local.f1 == NONE)
2359a747e4fSDavid du Colombier local.f1 = n;
2369a747e4fSDavid du Colombier else
2379a747e4fSDavid du Colombier local.f2 = n;
2389a747e4fSDavid du Colombier goto l0;
2399a747e4fSDavid du Colombier }
2409a747e4fSDavid du Colombier n = 0;
2419a747e4fSDavid du Colombier if(c >= 0 && c < MAXFMT)
2429a747e4fSDavid du Colombier n = fmtalloc.index[c];
2439a747e4fSDavid du Colombier local.chr = c;
244*9df35464SDavid du Colombier n = (*fmtalloc.conv[n])(argp, &local);
2459a747e4fSDavid du Colombier if(n < 0) {
2469a747e4fSDavid du Colombier local.f3 |= -n;
2479a747e4fSDavid du Colombier goto l0;
2489a747e4fSDavid du Colombier }
2499a747e4fSDavid du Colombier goto loop;
2509a747e4fSDavid du Colombier }
2519a747e4fSDavid du Colombier
2529a747e4fSDavid du Colombier int
numbconv(va_list * arg,Fconv * fp)2539a747e4fSDavid du Colombier numbconv(va_list *arg, Fconv *fp)
2549a747e4fSDavid du Colombier {
2559a747e4fSDavid du Colombier char s[IDIGIT];
2569a747e4fSDavid du Colombier int i, f, n, b, ucase;
2579a747e4fSDavid du Colombier long v;
2589a747e4fSDavid du Colombier vlong vl;
2599a747e4fSDavid du Colombier
2609a747e4fSDavid du Colombier SET(v);
2619a747e4fSDavid du Colombier SET(vl);
2629a747e4fSDavid du Colombier
2639a747e4fSDavid du Colombier ucase = 0;
2649a747e4fSDavid du Colombier b = fp->chr;
2659a747e4fSDavid du Colombier switch(fp->chr) {
2669a747e4fSDavid du Colombier case 'u':
2679a747e4fSDavid du Colombier fp->f3 |= FUNSIGN;
2689a747e4fSDavid du Colombier case 'd':
2699a747e4fSDavid du Colombier b = 10;
2709a747e4fSDavid du Colombier break;
2719a747e4fSDavid du Colombier
2729a747e4fSDavid du Colombier case 'b':
2739a747e4fSDavid du Colombier b = 2;
2749a747e4fSDavid du Colombier break;
2759a747e4fSDavid du Colombier
2769a747e4fSDavid du Colombier case 'o':
2779a747e4fSDavid du Colombier b = 8;
2789a747e4fSDavid du Colombier break;
2799a747e4fSDavid du Colombier
2809a747e4fSDavid du Colombier case 'X':
2819a747e4fSDavid du Colombier ucase = 1;
2829a747e4fSDavid du Colombier case 'x':
2839a747e4fSDavid du Colombier b = 16;
2849a747e4fSDavid du Colombier break;
2859a747e4fSDavid du Colombier case 'p':
2869a747e4fSDavid du Colombier fp->f3 |= FPOINTER|FUNSIGN;
2879a747e4fSDavid du Colombier b = 16;
2889a747e4fSDavid du Colombier break;
2899a747e4fSDavid du Colombier }
2909a747e4fSDavid du Colombier
2919a747e4fSDavid du Colombier f = 0;
2929a747e4fSDavid du Colombier switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) {
2939a747e4fSDavid du Colombier case FVLONG|FLONG:
2949a747e4fSDavid du Colombier vl = va_arg(*arg, vlong);
2959a747e4fSDavid du Colombier break;
2969a747e4fSDavid du Colombier
2979a747e4fSDavid du Colombier case FUNSIGN|FVLONG|FLONG:
2989a747e4fSDavid du Colombier vl = va_arg(*arg, uvlong);
2999a747e4fSDavid du Colombier break;
3009a747e4fSDavid du Colombier
3019a747e4fSDavid du Colombier case FUNSIGN|FPOINTER:
3029a747e4fSDavid du Colombier v = (ulong)va_arg(*arg, void*);
3039a747e4fSDavid du Colombier break;
3049a747e4fSDavid du Colombier
3059a747e4fSDavid du Colombier case FLONG:
3069a747e4fSDavid du Colombier v = va_arg(*arg, long);
3079a747e4fSDavid du Colombier break;
3089a747e4fSDavid du Colombier
3099a747e4fSDavid du Colombier case FUNSIGN|FLONG:
3109a747e4fSDavid du Colombier v = va_arg(*arg, ulong);
3119a747e4fSDavid du Colombier break;
3129a747e4fSDavid du Colombier
3139a747e4fSDavid du Colombier default:
3149a747e4fSDavid du Colombier v = va_arg(*arg, int);
3159a747e4fSDavid du Colombier break;
3169a747e4fSDavid du Colombier
3179a747e4fSDavid du Colombier case FUNSIGN:
3189a747e4fSDavid du Colombier v = va_arg(*arg, unsigned);
3199a747e4fSDavid du Colombier break;
3209a747e4fSDavid du Colombier }
3219a747e4fSDavid du Colombier if(fp->f3 & FVLONG) {
3229a747e4fSDavid du Colombier if(!(fp->f3 & FUNSIGN) && vl < 0) {
3239a747e4fSDavid du Colombier vl = -vl;
3249a747e4fSDavid du Colombier f = 1;
3259a747e4fSDavid du Colombier }
3269a747e4fSDavid du Colombier } else {
3279a747e4fSDavid du Colombier if(!(fp->f3 & FUNSIGN) && v < 0) {
3289a747e4fSDavid du Colombier v = -v;
3299a747e4fSDavid du Colombier f = 1;
3309a747e4fSDavid du Colombier }
3319a747e4fSDavid du Colombier }
3329a747e4fSDavid du Colombier s[IDIGIT-1] = 0;
3339a747e4fSDavid du Colombier for(i = IDIGIT-2;; i--) {
3349a747e4fSDavid du Colombier if(fp->f3 & FVLONG)
3359a747e4fSDavid du Colombier n = (uvlong)vl % b;
3369a747e4fSDavid du Colombier else
3379a747e4fSDavid du Colombier n = (ulong)v % b;
3389a747e4fSDavid du Colombier n += '0';
3399a747e4fSDavid du Colombier if(n > '9') {
3409a747e4fSDavid du Colombier n += 'a' - ('9'+1);
3419a747e4fSDavid du Colombier if(ucase)
3429a747e4fSDavid du Colombier n += 'A'-'a';
3439a747e4fSDavid du Colombier }
3449a747e4fSDavid du Colombier s[i] = n;
3459a747e4fSDavid du Colombier if(i < 2)
3469a747e4fSDavid du Colombier break;
3479a747e4fSDavid du Colombier if(fp->f3 & FVLONG)
3489a747e4fSDavid du Colombier vl = (uvlong)vl / b;
3499a747e4fSDavid du Colombier else
3509a747e4fSDavid du Colombier v = (ulong)v / b;
3519a747e4fSDavid du Colombier if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
3529a747e4fSDavid du Colombier continue;
3539a747e4fSDavid du Colombier if(fp->f3 & FVLONG) {
3549a747e4fSDavid du Colombier if(vl <= 0)
3559a747e4fSDavid du Colombier break;
3569a747e4fSDavid du Colombier continue;
3579a747e4fSDavid du Colombier }
3589a747e4fSDavid du Colombier if(v <= 0)
3599a747e4fSDavid du Colombier break;
3609a747e4fSDavid du Colombier }
3619a747e4fSDavid du Colombier
3629a747e4fSDavid du Colombier if(fp->f3 & FSHARP) {
3639a747e4fSDavid du Colombier if(b == 8 && s[i] != '0')
3649a747e4fSDavid du Colombier s[--i] = '0';
3659a747e4fSDavid du Colombier if(b == 16) {
3669a747e4fSDavid du Colombier if(ucase)
3679a747e4fSDavid du Colombier s[--i] = 'X';
3689a747e4fSDavid du Colombier else
3699a747e4fSDavid du Colombier s[--i] = 'x';
3709a747e4fSDavid du Colombier s[--i] = '0';
3719a747e4fSDavid du Colombier }
3729a747e4fSDavid du Colombier }
3739a747e4fSDavid du Colombier if(f)
3749a747e4fSDavid du Colombier s[--i] = '-';
3759a747e4fSDavid du Colombier else if(fp->f3 & FPLUS)
3769a747e4fSDavid du Colombier s[--i] = '+';
3779a747e4fSDavid du Colombier
3789a747e4fSDavid du Colombier fp->f2 = NONE;
3799a747e4fSDavid du Colombier strconv(s+i, fp);
3809a747e4fSDavid du Colombier return 0;
3819a747e4fSDavid du Colombier }
3829a747e4fSDavid du Colombier
3839a747e4fSDavid du Colombier void
Strconv(Rune * s,Fconv * fp)3849a747e4fSDavid du Colombier Strconv(Rune *s, Fconv *fp)
3859a747e4fSDavid du Colombier {
3869a747e4fSDavid du Colombier int n, c;
3879a747e4fSDavid du Colombier
3889a747e4fSDavid du Colombier if(fp->f3 & FMINUS)
3899a747e4fSDavid du Colombier fp->f1 = -fp->f1;
3909a747e4fSDavid du Colombier n = 0;
3919a747e4fSDavid du Colombier if(fp->f1 != NONE && fp->f1 >= 0) {
3929a747e4fSDavid du Colombier for(; s[n]; n++)
3939a747e4fSDavid du Colombier ;
3949a747e4fSDavid du Colombier while(n < fp->f1) {
3959a747e4fSDavid du Colombier pchar(' ', fp);
3969a747e4fSDavid du Colombier printcol++;
3979a747e4fSDavid du Colombier n++;
3989a747e4fSDavid du Colombier }
3999a747e4fSDavid du Colombier }
4009a747e4fSDavid du Colombier for(;;) {
4019a747e4fSDavid du Colombier c = *s++;
4029a747e4fSDavid du Colombier if(c == 0)
4039a747e4fSDavid du Colombier break;
4049a747e4fSDavid du Colombier n++;
4059a747e4fSDavid du Colombier if(fp->f2 == NONE || fp->f2 > 0) {
4069a747e4fSDavid du Colombier pchar(c, fp);
4079a747e4fSDavid du Colombier if(fp->f2 != NONE)
4089a747e4fSDavid du Colombier fp->f2--;
4099a747e4fSDavid du Colombier switch(c) {
4109a747e4fSDavid du Colombier default:
4119a747e4fSDavid du Colombier printcol++;
4129a747e4fSDavid du Colombier break;
4139a747e4fSDavid du Colombier case '\n':
4149a747e4fSDavid du Colombier printcol = 0;
4159a747e4fSDavid du Colombier break;
4169a747e4fSDavid du Colombier case '\t':
4179a747e4fSDavid du Colombier printcol = (printcol+8) & ~7;
4189a747e4fSDavid du Colombier break;
4199a747e4fSDavid du Colombier }
4209a747e4fSDavid du Colombier }
4219a747e4fSDavid du Colombier }
4229a747e4fSDavid du Colombier if(fp->f1 != NONE && fp->f1 < 0) {
4239a747e4fSDavid du Colombier fp->f1 = -fp->f1;
4249a747e4fSDavid du Colombier while(n < fp->f1) {
4259a747e4fSDavid du Colombier pchar(' ', fp);
4269a747e4fSDavid du Colombier printcol++;
4279a747e4fSDavid du Colombier n++;
4289a747e4fSDavid du Colombier }
4299a747e4fSDavid du Colombier }
4309a747e4fSDavid du Colombier }
4319a747e4fSDavid du Colombier
4329a747e4fSDavid du Colombier void
strconv(char * s,Fconv * fp)4339a747e4fSDavid du Colombier strconv(char *s, Fconv *fp)
4349a747e4fSDavid du Colombier {
4359a747e4fSDavid du Colombier int n, c, i;
4369a747e4fSDavid du Colombier Rune rune;
4379a747e4fSDavid du Colombier
4389a747e4fSDavid du Colombier if(fp->f3 & FMINUS)
4399a747e4fSDavid du Colombier fp->f1 = -fp->f1;
4409a747e4fSDavid du Colombier n = 0;
4419a747e4fSDavid du Colombier if(fp->f1 != NONE && fp->f1 >= 0) {
4429a747e4fSDavid du Colombier n = utflen(s);
4439a747e4fSDavid du Colombier while(n < fp->f1) {
4449a747e4fSDavid du Colombier pchar(' ', fp);
4459a747e4fSDavid du Colombier printcol++;
4469a747e4fSDavid du Colombier n++;
4479a747e4fSDavid du Colombier }
4489a747e4fSDavid du Colombier }
4499a747e4fSDavid du Colombier for(;;) {
4509a747e4fSDavid du Colombier c = *s & 0xff;
4519a747e4fSDavid du Colombier if(c >= Runeself) {
4529a747e4fSDavid du Colombier i = chartorune(&rune, s);
4539a747e4fSDavid du Colombier s += i;
4549a747e4fSDavid du Colombier c = rune;
4559a747e4fSDavid du Colombier } else
4569a747e4fSDavid du Colombier s++;
4579a747e4fSDavid du Colombier if(c == 0)
4589a747e4fSDavid du Colombier break;
4599a747e4fSDavid du Colombier n++;
4609a747e4fSDavid du Colombier if(fp->f2 == NONE || fp->f2 > 0) {
4619a747e4fSDavid du Colombier pchar(c, fp);
4629a747e4fSDavid du Colombier if(fp->f2 != NONE)
4639a747e4fSDavid du Colombier fp->f2--;
4649a747e4fSDavid du Colombier switch(c) {
4659a747e4fSDavid du Colombier default:
4669a747e4fSDavid du Colombier printcol++;
4679a747e4fSDavid du Colombier break;
4689a747e4fSDavid du Colombier case '\n':
4699a747e4fSDavid du Colombier printcol = 0;
4709a747e4fSDavid du Colombier break;
4719a747e4fSDavid du Colombier case '\t':
4729a747e4fSDavid du Colombier printcol = (printcol+8) & ~7;
4739a747e4fSDavid du Colombier break;
4749a747e4fSDavid du Colombier }
4759a747e4fSDavid du Colombier }
4769a747e4fSDavid du Colombier }
4779a747e4fSDavid du Colombier if(fp->f1 != NONE && fp->f1 < 0) {
4789a747e4fSDavid du Colombier fp->f1 = -fp->f1;
4799a747e4fSDavid du Colombier while(n < fp->f1) {
4809a747e4fSDavid du Colombier pchar(' ', fp);
4819a747e4fSDavid du Colombier printcol++;
4829a747e4fSDavid du Colombier n++;
4839a747e4fSDavid du Colombier }
4849a747e4fSDavid du Colombier }
4859a747e4fSDavid du Colombier }
4869a747e4fSDavid du Colombier
4879a747e4fSDavid du Colombier static int
noconv(va_list * va,Fconv * fp)4889a747e4fSDavid du Colombier noconv(va_list *va, Fconv *fp)
4899a747e4fSDavid du Colombier {
4909a747e4fSDavid du Colombier char s[10];
4919a747e4fSDavid du Colombier
4929a747e4fSDavid du Colombier USED(va);
4939a747e4fSDavid du Colombier s[0] = '*';
4949a747e4fSDavid du Colombier s[1] = fp->chr;
4959a747e4fSDavid du Colombier s[2] = '*';
4969a747e4fSDavid du Colombier s[3] = 0;
4979a747e4fSDavid du Colombier fp->f1 = 0;
4989a747e4fSDavid du Colombier fp->f2 = NONE;
4999a747e4fSDavid du Colombier fp->f3 = 0;
5009a747e4fSDavid du Colombier strconv(s, fp);
5019a747e4fSDavid du Colombier return 0;
5029a747e4fSDavid du Colombier }
5039a747e4fSDavid du Colombier
5049a747e4fSDavid du Colombier static int
cconv(va_list * arg,Fconv * fp)5059a747e4fSDavid du Colombier cconv(va_list *arg, Fconv *fp)
5069a747e4fSDavid du Colombier {
5079a747e4fSDavid du Colombier char s[10];
5089a747e4fSDavid du Colombier Rune rune;
5099a747e4fSDavid du Colombier
5109a747e4fSDavid du Colombier rune = va_arg(*arg, int);
5119a747e4fSDavid du Colombier if(fp->chr == 'c')
5129a747e4fSDavid du Colombier rune &= 0xff;
5139a747e4fSDavid du Colombier s[runetochar(s, &rune)] = 0;
5149a747e4fSDavid du Colombier
5159a747e4fSDavid du Colombier fp->f2 = NONE;
5169a747e4fSDavid du Colombier strconv(s, fp);
5179a747e4fSDavid du Colombier return 0;
5189a747e4fSDavid du Colombier }
5199a747e4fSDavid du Colombier
5209a747e4fSDavid du Colombier static Rune null[] = { L'<', L'n', L'u', L'l', L'l', L'>', L'\0' };
5219a747e4fSDavid du Colombier
5229a747e4fSDavid du Colombier static int
sconv(va_list * arg,Fconv * fp)5239a747e4fSDavid du Colombier sconv(va_list *arg, Fconv *fp)
5249a747e4fSDavid du Colombier {
5259a747e4fSDavid du Colombier char *s;
5269a747e4fSDavid du Colombier Rune *r;
5279a747e4fSDavid du Colombier
5289a747e4fSDavid du Colombier if(fp->chr == 's') {
5299a747e4fSDavid du Colombier s = va_arg(*arg, char*);
5309a747e4fSDavid du Colombier if(s == 0)
5319a747e4fSDavid du Colombier s = "<null>";
5329a747e4fSDavid du Colombier strconv(s, fp);
5339a747e4fSDavid du Colombier } else {
5349a747e4fSDavid du Colombier r = va_arg(*arg, Rune*);
5359a747e4fSDavid du Colombier if(r == 0)
5369a747e4fSDavid du Colombier r = null;
5379a747e4fSDavid du Colombier Strconv(r, fp);
5389a747e4fSDavid du Colombier }
5399a747e4fSDavid du Colombier return 0;
5409a747e4fSDavid du Colombier }
5419a747e4fSDavid du Colombier
5429a747e4fSDavid du Colombier static int
percent(va_list * va,Fconv * fp)5439a747e4fSDavid du Colombier percent(va_list *va, Fconv *fp)
5449a747e4fSDavid du Colombier {
5459a747e4fSDavid du Colombier USED(va);
5469a747e4fSDavid du Colombier
5479a747e4fSDavid du Colombier pchar('%', fp);
5489a747e4fSDavid du Colombier printcol++;
5499a747e4fSDavid du Colombier return 0;
5509a747e4fSDavid du Colombier }
5519a747e4fSDavid du Colombier
5529a747e4fSDavid du Colombier static int
column(va_list * arg,Fconv * fp)5539a747e4fSDavid du Colombier column(va_list *arg, Fconv *fp)
5549a747e4fSDavid du Colombier {
5559a747e4fSDavid du Colombier int col, pc;
5569a747e4fSDavid du Colombier
5579a747e4fSDavid du Colombier col = va_arg(*arg, int);
5589a747e4fSDavid du Colombier while(printcol < col) {
5599a747e4fSDavid du Colombier pc = (printcol+8) & ~7;
5609a747e4fSDavid du Colombier if(pc <= col) {
5619a747e4fSDavid du Colombier pchar('\t', fp);
5629a747e4fSDavid du Colombier printcol = pc;
5639a747e4fSDavid du Colombier } else {
5649a747e4fSDavid du Colombier pchar(' ', fp);
5659a747e4fSDavid du Colombier printcol++;
5669a747e4fSDavid du Colombier }
5679a747e4fSDavid du Colombier }
5689a747e4fSDavid du Colombier return 0;
5699a747e4fSDavid du Colombier }
5709a747e4fSDavid du Colombier
5719a747e4fSDavid du Colombier static int
flags(va_list * va,Fconv * fp)5729a747e4fSDavid du Colombier flags(va_list *va, Fconv *fp)
5739a747e4fSDavid du Colombier {
5749a747e4fSDavid du Colombier int f;
5759a747e4fSDavid du Colombier
5769a747e4fSDavid du Colombier USED(va);
5779a747e4fSDavid du Colombier f = 0;
5789a747e4fSDavid du Colombier switch(fp->chr) {
5799a747e4fSDavid du Colombier case '+':
5809a747e4fSDavid du Colombier f = FPLUS;
5819a747e4fSDavid du Colombier break;
5829a747e4fSDavid du Colombier
5839a747e4fSDavid du Colombier case '-':
5849a747e4fSDavid du Colombier f = FMINUS;
5859a747e4fSDavid du Colombier break;
5869a747e4fSDavid du Colombier
5879a747e4fSDavid du Colombier case '#':
5889a747e4fSDavid du Colombier f = FSHARP;
5899a747e4fSDavid du Colombier break;
5909a747e4fSDavid du Colombier
5919a747e4fSDavid du Colombier case 'l':
5929a747e4fSDavid du Colombier f = FLONG;
5939a747e4fSDavid du Colombier if(fp->f3 & FLONG)
5949a747e4fSDavid du Colombier f = FVLONG;
5959a747e4fSDavid du Colombier break;
5969a747e4fSDavid du Colombier
5979a747e4fSDavid du Colombier case 'u':
5989a747e4fSDavid du Colombier f = FUNSIGN;
5999a747e4fSDavid du Colombier break;
6009a747e4fSDavid du Colombier }
6019a747e4fSDavid du Colombier return -f;
6029a747e4fSDavid du Colombier }
6039a747e4fSDavid du Colombier
6049a747e4fSDavid du Colombier /*
6059a747e4fSDavid du Colombier * This code is superseded by the more accurate (but more complex)
6069a747e4fSDavid du Colombier * algorithm in fltconv.c and dtoa.c. Uncomment this routine to avoid
6079a747e4fSDavid du Colombier * using the more complex code.
6089a747e4fSDavid du Colombier *
6099a747e4fSDavid du Colombier */
6109a747e4fSDavid du Colombier
611