int __fmtcpy(Fmt *f, const void *vm, int n, int sz) { Rune *rt, *rs, r; char *t, *s, *m, *me; ulong fl; int nc, w; m = (char*)vm; me = m + sz; fl = f->flags; w = 0; if(fl & FmtWidth) w = f->width; if((fl & FmtPrec) && n > f->prec) n = f->prec; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) return -1; rt = (Rune*)f->to; rs = (Rune*)f->stop; for(nc = n; nc > 0; nc--){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, me-m)) m += chartorune(&r, m); else break; FMTRCHAR(f, rt, rs, r); } f->nfmt += rt - (Rune *)f->to; f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) return -1; t = (char*)f->to; s = (char*)f->stop; for(nc = n; nc > 0; nc--){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, me-m)) m += chartorune(&r, m); else break; FMTRUNE(f, t, s, r); } f->nfmt += t - (char *)f->to; f->to = t; if(fl & FmtLeft && __fmtpad(f, w - n) < 0) return -1; } return 0; }
int __fmtrcpy(Fmt *f, const void *vm, int n) { Rune r, *m, *me, *rt, *rs; char *t, *s; ulong fl; int w; m = (Rune*)vm; fl = f->flags; w = 0; if(fl & FmtWidth) w = f->width; if((fl & FmtPrec) && n > f->prec) n = f->prec; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) return -1; rt = (Rune*)f->to; rs = (Rune*)f->stop; for(me = m + n; m < me; m++) FMTRCHAR(f, rt, rs, *m); f->nfmt += rt - (Rune *)f->to; f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) return -1; t = (char*)f->to; s = (char*)f->stop; for(me = m + n; m < me; m++){ r = *m; FMTRUNE(f, t, s, r); } f->nfmt += t - (char *)f->to; f->to = t; if(fl & FmtLeft && __fmtpad(f, w - n) < 0) return -1; } return 0; }
int __efgfmt(Fmt *fmt) { double f; char s1[NSIGNIF+10]; int e, d, n; int c1, c2, c3, c4, ucase, sign, chr, prec, fl; f = va_arg(fmt->args, double); prec = FDEFLT; fl = fmt->flags; fmt->flags = 0; if(fl & FmtPrec) prec = fmt->prec; chr = fmt->r; ucase = 0; if(chr == 'E'){ chr = 'e'; ucase = 1; }else if(chr == 'F'){ chr = 'f'; ucase = 1; }else if(chr == 'G'){ chr = 'g'; ucase = 1; } if(prec > 0 && chr == 'g') prec--; if(prec < 0) prec = 0; xdodtoa(s1, f, chr, prec, &e, &sign); e--; if(*s1 == 'i' || *s1 == 'n'){ if(ucase){ if(*s1 == 'i'){ strcpy(s1, "INF"); }else{ strcpy(s1, "NAN"); } } fmt->flags = fl & (FmtWidth|FmtLeft); return __fmtcpy(fmt, (const void*)s1, 3, 3); } /* * copy into final place * c1 digits of leading '0' * c2 digits from conversion * c3 digits of trailing '0' * c4 digits after '.' */ c1 = 0; c2 = prec + 1; c3 = 0; c4 = prec; switch(chr) { default: chr = 'e'; break; case 'g': /* * decide on 'e' of 'f' style convers */ if(e >= -4 && e <= prec) { c1 = -e; c4 = prec - e; chr = 'h'; /* flag for 'f' style */ } break; case 'f': c1 = -e; if(c1 > prec) c1 = prec + 1; c2 += e; break; } /* * clean up c1 c2 and c3 */ if(c1 < 0) c1 = 0; if(c2 < 0) c2 = 0; if(c2 > NSIGNIF) { c3 = c2-NSIGNIF; c2 = NSIGNIF; } /* * trim trailing zeros for %g */ if(!(fl & FmtSharp) && (chr == 'g' || chr == 'h')){ if(c4 >= c3){ c4 -= c3; c3 = 0; }else{ c3 -= c4; c4 = 0; } while(c4 && c2 > 1 && s1[c2 - 1] == '0'){ c4--; c2--; } } /* * calculate the total length */ n = c1 + c2 + c3; if(sign || (fl & (FmtSign|FmtSpace))) n++; if(c4 || (fl & FmtSharp)){ n++; } if(chr == 'e' || chr == 'g'){ n += 4; if(e >= 100) n++; } /* * pad to width if right justified */ if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){ if(fl & FmtZero){ c1 += fmt->width - n; }else{ if(__fmtpad(fmt, fmt->width - n) < 0){ return -1; } } } /* * sign */ d = 0; if(sign) d = '-'; else if(fl & FmtSign) d = '+'; else if(fl & FmtSpace) d = ' '; if(d && fmtrune(fmt, d) < 0){ return -1; } /* * copy digits */ c4 = c1 + c2 + c3 - c4; if(c1 > 0){ if(fmtzdotpad(fmt, c1, c4) < 0){ return -1; } c4 -= c1; } d = 0; if(c4 >= 0 && c4 < c2){ if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0) return -1; d = c4; c2 -= c4; c4 = -1; } if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){ return -1; } c4 -= c2; if(c3 > 0){ if(fmtzdotpad(fmt, c3, c4) < 0){ return -1; } c4 -= c3; } /* * strip trailing '0' on g conv */ if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){ return -1; } if(chr == 'e' || chr == 'g') { d = 0; if(ucase) s1[d++] = 'E'; else s1[d++] = 'e'; c1 = e; if(c1 < 0) { s1[d++] = '-'; c1 = -c1; } else s1[d++] = '+'; if(c1 >= 100) { s1[d++] = c1/100 + '0'; c1 = c1%100; } s1[d++] = c1/10 + '0'; s1[d++] = c1%10 + '0'; if(__fmtcpy(fmt, s1, d, d) < 0){ return -1; } } if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){ if(__fmtpad(fmt, fmt->width - n) < 0){ return -1; } } return 0; }
static int qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f) { Rune r, *rm, *rme; char *t, *s, *m, *me; Rune *rt, *rs; ulong fl; int nc, w; m = sin; me = m + q->nbytesin; rm = rin; rme = rm + q->nrunesin; fl = f->flags; w = 0; if(fl & FmtWidth) w = f->width; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) return -1; } t = (char*)f->to; s = (char*)f->stop; rt = (Rune*)f->to; rs = (Rune*)f->stop; if(f->runes) FMTRCHAR(f, rt, rs, '\''); else FMTRUNE(f, t, s, '\''); for(nc = q->nrunesin; nc > 0; nc--){ if(sin){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, (int)(me-m))) m += chartorune(&r, m); else break; }else{ if(rm >= rme) break; r = *(uchar*)rm++; } if(f->runes){ FMTRCHAR(f, rt, rs, r); if(r == '\'') FMTRCHAR(f, rt, rs, r); }else{ FMTRUNE(f, t, s, r); if(r == '\'') FMTRUNE(f, t, s, r); } } if(f->runes){ FMTRCHAR(f, rt, rs, '\''); USED(rs); f->nfmt += (int)(rt - (Rune *)f->to); f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0) return -1; }else{ FMTRUNE(f, t, s, '\''); USED(s); f->nfmt += (int)(t - (char *)f->to); f->to = t; if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) return -1; } return 0; }