/* %Z from gc, for quoting import paths */ int Zconv(Fmt *fp) { Rune r; char *s, *se; int n; s = va_arg(fp->args, char*); if(s == nil) return fmtstrcpy(fp, "<nil>"); se = s + strlen(s); // NOTE: Keep in sync with ../gc/go.c:/^Zconv. while(s < se) { n = chartorune(&r, s); s += n; switch(r) { case Runeerror: if(n == 1) { fmtprint(fp, "\\x%02x", (uchar)*(s-1)); break; } // fall through default: if(r < ' ') { fmtprint(fp, "\\x%02x", r); break; } fmtrune(fp, r); break; case '\t': fmtstrcpy(fp, "\\t"); break; case '\n': fmtstrcpy(fp, "\\n"); break; case '\"': case '\\': fmtrune(fp, '\\'); fmtrune(fp, r); break; case 0xFEFF: // BOM, basically disallowed in source code fmtstrcpy(fp, "\\uFEFF"); break; } } return 0; }
static int constfmt(Fmt *f) { Const *c; int rc; int s; c = va_arg(f->args, Const *); rc = 0; if(c == nil || c->n == nil || c->x == nil) return fmtstrcpy(f, "<nil>"); s = c->n->sign; if(s < 0){ c->n->sign = 1; rc += fmtrune(f, '-'); } if(c->sz != 0) rc += fmtprint(f, "%d", c->sz); if(!is0(c->x)){ rc += binput(f, c); }else if(c->base == 0 || c->base == 10) rc += fmtprint(f, c->sz != 0 ? "'d%.10B" : "%.10B", c->n); else if(c->base == 16) rc += fmtprint(f, "'h%.16B", c->n); else rc += fmtprint(f, "'b%.2B", c->n); c->n->sign = s; return rc; }
static char* getquoted(void) { int c; Rune r; Fmt fmt; c = getnsc(); if(c != '"') return nil; fmtstrinit(&fmt); for(;;) { r = getr(); if(r == '\n') { free(fmtstrflush(&fmt)); return nil; } if(r == '"') break; fmtrune(&fmt, r); } free(lastfmt); lastfmt = fmtstrflush(&fmt); return strdup(lastfmt); }
void flushdi(void) { int n; Rune *p; if(ndi == 0 || difmtinit == 0) return; fmtrune(&difmt, Uunformatted); p = runefmtstrflush(&difmt); memset(&difmt, 0, sizeof difmt); difmtinit = 0; if(p == nil) warn("out of memory in diversion %C%S", dot, di[ndi-1]); else{ n = runestrlen(p); if(n > 0 && p[n-1] != '\n'){ p = runerealloc(p, n+2); p[n] = '\n'; p[n+1] = 0; } } as(di[ndi-1], p); free(p); }
char* unrfc2047(char *s) { char *p, *q, *t, *u, *v; int len; Rune r; Fmt fmt; if(s == nil) return nil; if(strstr(s, "=?") == nil) return s; fmtstrinit(&fmt); for(p=s; *p; ){ /* =?charset?e?text?= */ if(*p=='=' && *(p+1)=='?'){ p += 2; q = strchr(p, '?'); if(q == nil) goto emit; q++; if(*q == '?' || *(q+1) != '?') goto emit; t = q+2; u = strchr(t, '?'); if(u == nil || *(u+1) != '=') goto emit; switch(*q){ case 'q': case 'Q': *u = 0; v = decode(QuotedPrintableU, t, &len); break; case 'b': case 'B': *u = 0; v = decode(Base64, t, &len); break; default: goto emit; } *(q-1) = 0; v = tcs(p, v); fmtstrcpy(&fmt, v); free(v); p = u+2; } emit: p += chartorune(&r, p); fmtrune(&fmt, r); } p = fmtstrflush(&fmt); if(p == nil) sysfatal("out of memory"); free(s); return p; }
void outdi(Rune r) { if(!difmtinit) abort(); if(r == Uempty) return; fmtrune(&difmt, r); }
void emitdi(void) { flushdi(); runefmtstrinit(&difmt); difmtinit = 1; fmtrune(&difmt, Uformatted); }
/* .di, .da */ void r_di(int argc, Rune **argv) { br(); if(argc > 2) warn("extra arguments to %C%S", dot, argv[0]); if(argc == 1){ /* end diversion */ if(ndi <= 0){ /* warn("unmatched %C%S", dot, argv[0]); */ return; } flushdi(); if(--ndi == 0){ _nr(L(".z"), nil); outcb = nil; }else{ _nr(L(".z"), di[ndi-1]); runefmtstrinit(&difmt); fmtrune(&difmt, Uformatted); difmtinit = 1; } return; } /* start diversion */ /* various register state should be saved, but it's all useless to us */ flushdi(); if(ndi >= nelem(di)) sysfatal("%Cdi overflow", dot); if(argv[0][1] == 'i') ds(argv[1], nil); _nr(L(".z"), argv[1]); runestrcpy(di[ndi++], argv[1]); runefmtstrinit(&difmt); fmtrune(&difmt, Uformatted); difmtinit = 1; outcb = outdi; }
Bits getflag(char *s) { Bits flag; int f; Fmt fmt; Rune c; flag = zbits; nstar = 0; fmtstrinit(&fmt); for(;;) { s += chartorune(&c, s); if(c == 0 || c >= nelem(flagbits)) break; fmtrune(&fmt, c); f = flagbits[c]; switch(f) { case Fnone: argflag(c, Fverb); f = flagbits[c]; break; case Fstar: nstar++; case Fignor: continue; case Fl: if(bset(flag, Fl)) flag = bor(flag, blsh(Fvl)); } flag = bor(flag, blsh(f)); if(f >= Fverb) break; } free(lastfmt); lastfmt = fmtstrflush(&fmt); return flag; }
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; }