123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792 |
- /*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Details at https://graphviz.org
- *************************************************************************/
- #include <assert.h>
- #include <cgraph/gv_ctype.h>
- #include <cgraph/gv_math.h>
- #include <inttypes.h>
- #include <sfio/sfhdr.h>
- #include <stddef.h>
- #include <stdio.h>
- #include <string.h>
- /* The engine for formatting data
- **
- ** Written by Kiem-Phong Vo.
- */
- #define HIGHBITI (~((~0u) >> 1))
- #define HIGHBITL (~((~0ull) >> 1))
- #define SFFMT_PREFIX (SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK)
- #define FPRECIS 6 /* default precision for floats */
- /**
- * @param f file to print to
- * @param format Structure describing how to print
- */
- int sfprint(FILE *f, Sffmt_t *format) {
- int v = 0, n_s, base, fmt, flags;
- long long lv;
- char *sp, *ssp, *endsp, *ep, *endep;
- int dot, width, precis, n, n_output = 0;
- int sign, decpt;
- ssize_t size;
- double dval;
- char *tls[2], **ls; /* for %..[separ]s */
- const char *t_str; /* stuff between () */
- ssize_t n_str; /* its length */
- Argv_t argv; /* for extf to return value */
- Sffmt_t *ft; /* format environment */
- int argp, argn; /* arg position and number */
- #define SLACK 1024
- char buf[SF_MAXDIGITS + SLACK];
- char decimal = 0, thousand = 0;
- #define SFputc(f,c) do { \
- if (putc((c), (f)) == EOF) { \
- goto done; \
- } \
- } while (0)
- #define SFnputc(f,c,n) do { \
- for (int i_ = 0; i_ < (n); ++i_) { \
- if (putc((c), (f)) == EOF) { \
- goto done; \
- } \
- } \
- (n) = 0; \
- } while (0)
- #define SFwrite(f,s,n) do { \
- if ((n) > 0 && fwrite((s), (size_t)(n), 1, (f)) < 1) { \
- goto done; \
- } \
- } while (0)
- tls[1] = NULL;
- ft = NULL;
- argn = -1;
- // stack a new environment
- argv.ft = format;
- assert(argv.ft != NULL);
- assert(argv.ft->form != NULL);
- const char *form = argv.ft->form;
- ft = argv.ft;
- while ((n = *form)) {
- if (n != '%') { /* collect the non-pattern chars */
- sp = (char *) form++;
- while (*form && *form != '%')
- form += 1;
- n = form - sp;
- SFwrite(f, sp, n);
- continue;
- } else
- form += 1;
- flags = 0;
- size = width = precis = base = n_s = argp = -1;
- ssp = _Sfdigits;
- endep = ep = NULL;
- endsp = sp = buf + (sizeof(buf) - 1);
- t_str = NULL;
- n_str = dot = 0;
- loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
- switch ((fmt = *form++)) {
- case '\0':
- SFputc(f, '%');
- goto done;
- case '%':
- SFputc(f, '%');
- continue;
- case LEFTP: /* get the type enclosed in balanced parens */
- t_str = form;
- for (v = 1;;) {
- switch (*form++) {
- case 0: /* not balancable, retract */
- form = t_str;
- t_str = NULL;
- n_str = 0;
- goto loop_flags;
- case LEFTP: /* increasing nested level */
- v += 1;
- continue;
- case RIGHTP: /* decreasing nested level */
- if ((v -= 1) != 0)
- continue;
- if (*t_str != '*')
- n_str = (form - 1) - t_str;
- else {
- t_str = _Sffmtintf(t_str + 1, &n);
- FP_SET(-1, argn);
- FMTSET(ft, form, LEFTP, 0, 0, 0, 0, 0, NULL, 0);
- n = ft->extf(&argv, ft);
- if (n < 0)
- goto done;
- assert(ft->flags & SFFMT_VALUE);
- if ((t_str = argv.s) && (n_str = (int)ft->size) < 0)
- n_str = (ssize_t)strlen(t_str);
- }
- goto loop_flags;
- default:
- // skip over
- break;
- }
- }
- case '-':
- flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;
- goto loop_flags;
- case '0':
- if (!(flags & SFFMT_LEFT))
- flags |= SFFMT_ZERO;
- goto loop_flags;
- case ' ':
- if (!(flags & SFFMT_SIGN))
- flags |= SFFMT_BLANK;
- goto loop_flags;
- case '+':
- flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN;
- goto loop_flags;
- case '#':
- flags |= SFFMT_ALTER;
- goto loop_flags;
- case QUOTE:
- SFSETLOCALE(decimal, thousand);
- if (thousand)
- flags |= SFFMT_THOUSAND;
- goto loop_flags;
- case '.':
- dot += 1;
- if (dot == 1) { /* so base can be defined without setting precis */
- if (*form != '.')
- precis = 0;
- } else if (dot == 2) {
- base = 0; /* for %s,%c */
- if (*form == 'c' || *form == 's')
- goto loop_flags;
- if (*form && !gv_isalnum(*form) &&
- (form[1] == 'c' || form[1] == 's')) {
- if (*form == '*')
- goto do_star;
- else {
- base = *form++;
- goto loop_flags;
- }
- }
- }
- if (gv_isdigit(*form)) {
- fmt = *form++;
- goto dot_size;
- } else if (*form != '*')
- goto loop_flags;
- do_star:
- form += 1; /* fall through */
- case '*':
- form = _Sffmtintf(form, &n);
- n = FP_SET(-1, argn);
- FMTSET(ft, form, '.', dot, 0, 0, 0, 0, NULL, 0);
- if (ft->extf(&argv, ft) < 0)
- goto done;
- assert(ft->flags & SFFMT_VALUE);
- v = argv.i;
- goto dot_set;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- dot_size:
- for (v = fmt - '0'; gv_isdigit(*form); ++form)
- v = v * 10 + (*form - '0');
- dot_set:
- if (dot == 0) {
- if ((width = v) < 0) {
- width = -width;
- flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;
- }
- } else if (dot == 1)
- precis = v;
- else if (dot == 2)
- base = v;
- goto loop_flags;
- case 'I': /* object length */
- size = 0;
- flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
- if (gv_isdigit(*form)) {
- for (n = *form; gv_isdigit(n); n = *++form)
- size = size * 10 + (n - '0');
- } else if (*form == '*') {
- form = _Sffmtintf(form + 1, &n);
- n = FP_SET(-1, argn);
- FMTSET(ft, form, 'I', sizeof(int), 0, 0, 0, 0, NULL, 0);
- if (ft->extf(&argv, ft) < 0)
- goto done;
- assert(ft->flags & SFFMT_VALUE);
- size = argv.i;
- }
- goto loop_flags;
- case 'l':
- size = -1;
- flags &= ~SFFMT_TYPES;
- if (*form == 'l') {
- form += 1;
- flags |= SFFMT_LLONG;
- } else
- flags |= SFFMT_LONG;
- goto loop_flags;
- case 'h':
- size = -1;
- flags &= ~SFFMT_TYPES;
- if (*form == 'h') {
- form += 1;
- flags |= SFFMT_SSHORT;
- } else
- flags |= SFFMT_SHORT;
- goto loop_flags;
- case 'L':
- size = -1;
- flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
- goto loop_flags;
- case 'j':
- size = -1;
- flags = (flags & ~SFFMT_TYPES) | SFFMT_JFLAG;
- goto loop_flags;
- case 'z':
- size = -1;
- flags = (flags & ~SFFMT_TYPES) | SFFMT_ZFLAG;
- goto loop_flags;
- case 't':
- size = -1;
- flags = (flags & ~SFFMT_TYPES) | SFFMT_TFLAG;
- goto loop_flags;
- default: // continue with logic below
- break;
- }
- /* set the correct size */
- if (flags & (SFFMT_TYPES & ~SFFMT_IFLAG)) {
- if (_Sftype[fmt] & (SFFMT_INT | SFFMT_UINT)) {
- size = (flags & SFFMT_LLONG) ? (ssize_t)sizeof(long long) :
- (flags & SFFMT_LONG) ? (ssize_t)sizeof(long) :
- (flags & SFFMT_SHORT) ? (ssize_t)sizeof(short) :
- (flags & SFFMT_SSHORT) ? (ssize_t)sizeof(char) :
- (flags & SFFMT_JFLAG) ? (ssize_t)sizeof(long long) :
- (flags & SFFMT_TFLAG) ? (ssize_t)sizeof(ptrdiff_t) :
- (flags & SFFMT_ZFLAG) ? (ssize_t)sizeof(size_t) : -1;
- } else if (_Sftype[fmt] & SFFMT_FLOAT) {
- size = (flags & SFFMT_LDOUBLE) ? (ssize_t)sizeof(long double) :
- (flags & (SFFMT_LONG | SFFMT_LLONG)) ? (ssize_t)sizeof(double) : -1;
- }
- }
- argp = FP_SET(argp, argn);
- FMTSET(ft, form, fmt, size, flags, width, precis, base, t_str, n_str);
- v = ft->extf(&argv, ft);
- if (v < 0)
- goto done;
- else if (v == 0) { // extf did not output
- FMTGET(ft, form, fmt, size, flags, width, precis, base);
- assert(ft->flags & SFFMT_VALUE);
- } else if (v > 0) { // extf output v bytes
- n_output += v;
- continue;
- }
- switch (fmt) { /* PRINTF DIRECTIVES */
- default: /* unknown directive */
- form -= 1;
- argn -= 1;
- continue;
- case 's':
- if (base >= 0) { /* list of strings */
- if (!(ls = argv.sp) || !ls[0])
- continue;
- } else {
- if (!(sp = argv.s))
- sp = "(null)";
- ls = tls;
- tls[0] = sp;
- }
- for (sp = *ls;;) {
- if ((v = size) >= 0) {
- if (precis >= 0 && v > precis)
- v = precis;
- } else if (precis < 0)
- v = strlen(sp);
- else { /* precis >= 0 means min(strlen,precis) */
- for (v = 0; v < precis; ++v)
- if (sp[v] == 0)
- break;
- }
- if ((n = width - v) > 0) {
- if (flags & SFFMT_ZERO) {
- SFnputc(f, '0', n);
- } else if (!(flags & SFFMT_LEFT)) {
- SFnputc(f, ' ', n);
- }
- }
- SFwrite(f, sp, v);
- if (n > 0) {
- SFnputc(f, ' ', n);
- }
- if (!(sp = *++ls))
- break;
- else if (base > 0) {
- SFputc(f, base);
- }
- }
- continue;
- case 'c': /* an array of characters */
- if (base >= 0) {
- if (!(sp = argv.s) || !sp[0])
- continue;
- } else {
- fmt = (int) argv.c;
- sp = buf;
- buf[0] = fmt;
- buf[1] = 0;
- }
- if (precis <= 0)
- precis = 1;
- for (fmt = *sp;;) {
- if ((n = width - precis) > 0 && !(flags & SFFMT_LEFT)) {
- SFnputc(f, ' ', n);
- }
- v = precis;
- SFnputc(f, fmt, v);
- if (n > 0) {
- SFnputc(f, ' ', n);
- }
- if (!(fmt = *++sp))
- break;
- else if (base > 0) {
- SFputc(f, base);
- }
- }
- continue;
- case 'p': /* pointer value */
- fmt = 'x';
- base = 16;
- n_s = 15;
- n = 4;
- flags =
- (flags & ~(SFFMT_SIGN | SFFMT_BLANK | SFFMT_ZERO)) |
- SFFMT_ALTER;
- if (sizeof(void*) > sizeof(int)) {
- lv = (long long)(intptr_t)argv.vp;
- goto long_cvt;
- } else {
- v = (int)(intptr_t)argv.vp;
- goto int_cvt;
- }
- case 'o':
- base = 8;
- n_s = 7;
- n = 3;
- flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
- goto int_arg;
- case 'X':
- ssp = "0123456789ABCDEF";
- // fall through
- case 'x':
- base = 16;
- n_s = 15;
- n = 4;
- flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
- goto int_arg;
- case 'i':
- fmt = 'd';
- goto d_format;
- case 'u':
- flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
- // fall through
- case 'd':
- d_format:
- if (base < 2 || base > SF_RADIX)
- base = 10;
- if ((base & (n_s = base - 1)) == 0) {
- if (base < 8)
- n = base < 4 ? 1 : 2;
- else if (base < 32)
- n = base < 16 ? 3 : 4;
- else
- n = base < 64 ? 5 : 6;
- } else
- n_s = base == 10 ? -1 : 0;
- int_arg:
- if ((sizeof(long) > sizeof(int) || sizeof(void*) > sizeof(int))
- && FMTCMP(size, long long, long long)) {
- lv = argv.ll;
- goto long_cvt;
- } else if ((sizeof(long) > sizeof(int) || sizeof(void*) > sizeof(int))
- && FMTCMP(size, long, long long)) {
- if (fmt == 'd')
- lv = (long long)argv.l;
- else
- lv = (long long)(ulong)argv.l;
- long_cvt:
- if (lv == 0 && precis == 0)
- break;
- if (lv < 0 && fmt == 'd') {
- flags |= SFFMT_MINUS;
- if ((unsigned long long)lv == HIGHBITL) { // avoid overflow
- lv = (long long)(HIGHBITL / (unsigned long long)base);
- *--sp = _Sfdigits[HIGHBITL -
- (unsigned long long)lv * (unsigned long long)base];
- } else
- lv = -lv;
- }
- if (n_s < 0) { /* base 10 */
- long long nv;
- sfucvt(lv, sp, nv, ssp, long long, unsigned long long);
- } else if (n_s > 0) { /* base power-of-2 */
- do {
- *--sp = ssp[lv & n_s];
- } while ((lv = (unsigned long long)lv >> n));
- } else { /* general base */
- do {
- *--sp = ssp[(unsigned long long)lv % (unsigned long long)base];
- } while ((lv = (unsigned long long)lv / (unsigned long long)base));
- }
- } else
- if (sizeof(short) < sizeof(int) && FMTCMP(size, short, long long)) {
- if (ft->flags & SFFMT_VALUE) {
- if (fmt == 'd')
- v = (int) ((short) argv.h);
- else
- v = (int) ((ushort) argv.h);
- } else {
- if (fmt == 'd')
- v = (int) ((short) argv.i);
- else
- v = (int) ((ushort) argv.i);
- }
- goto int_cvt;
- } else if (size == sizeof(char)) {
- if (ft->flags & SFFMT_VALUE) {
- if (fmt == 'd')
- v = (int) ((char) argv.c);
- else
- v = (int) ((uchar) argv.c);
- } else {
- if (fmt == 'd')
- v = (int) ((char) argv.i);
- else
- v = (int) ((uchar) argv.i);
- }
- goto int_cvt;
- } else {
- v = argv.i;
- int_cvt:
- if (v == 0 && precis == 0)
- break;
- if (v < 0 && fmt == 'd') {
- flags |= SFFMT_MINUS;
- if ((unsigned)v == HIGHBITI) { // avoid overflow
- v = (int)(HIGHBITI / (unsigned)base);
- *--sp = _Sfdigits[HIGHBITI - (unsigned)v * (unsigned)base];
- } else
- v = -v;
- }
- if (n_s < 0) { /* base 10 */
- sfucvt(v, sp, n, ssp, int, unsigned);
- } else if (n_s > 0) { /* base power-of-2 */
- do {
- *--sp = ssp[v & n_s];
- } while ((v = (unsigned)v >> n));
- } else { /* n_s == 0, general base */
- do {
- *--sp = ssp[(unsigned)v % (unsigned)base];
- } while ((v = (unsigned)v / (unsigned)base));
- }
- }
- if (n_s < 0 && (flags & SFFMT_THOUSAND)
- && (n = endsp - sp) > 3) {
- if ((n %= 3) == 0)
- n = 3;
- for (ep = buf + SLACK, endep = ep + n;;) {
- while (ep < endep)
- *ep++ = *sp++;
- if (sp == endsp)
- break;
- if (sp <= endsp - 3)
- *ep++ = thousand;
- endep = ep + 3;
- }
- sp = buf + SLACK;
- endsp = ep;
- }
- /* zero padding for precision if have room in buffer */
- if (precis > 0 && (precis -= (endsp - sp)) < (sp - buf) - 64)
- while (precis-- > 0)
- *--sp = '0';
- if (flags & SFFMT_ALTER) { /* prefix */
- if (fmt == 'o') {
- if (*sp != '0')
- *--sp = '0';
- } else {
- if (width > 0 && (flags & SFFMT_ZERO)) { /* do 0 padding first */
- if (fmt == 'x' || fmt == 'X')
- n = 0;
- else if (dot < 2)
- n = width;
- else
- n = base < 10 ? 2 : 3;
- n += (flags & (SFFMT_MINUS | SFFMT_SIGN)) ? 1 : 0;
- n = width - (n + (endsp - sp));
- while (n-- > 0)
- *--sp = '0';
- }
- if (fmt == 'x' || fmt == 'X') {
- *--sp = (char) fmt;
- *--sp = '0';
- } else if (dot >= 2) { /* base#value notation */
- *--sp = '#';
- if (base < 10)
- *--sp = (char) ('0' + base);
- else {
- *--sp = _Sfdec[(base <<= 1) + 1];
- *--sp = _Sfdec[base];
- }
- }
- }
- }
- break;
- case 'g':
- case 'G': /* these ultimately become %e or %f */
- case 'e':
- case 'E':
- case 'f':
- if (!(ft->flags & SFFMT_VALUE) || FMTCMP(size, double, long double))
- dval = argv.d;
- else
- dval = (double) argv.f;
- if (fmt == 'e' || fmt == 'E') {
- n = (precis = precis < 0 ? FPRECIS : precis) + 1;
- {
- ep = _sfcvt(&dval, imin(n, SF_FDIGITS),
- &decpt, &sign, SFFMT_EFORMAT);
- }
- goto e_format;
- } else if (fmt == 'f' || fmt == 'F') {
- precis = precis < 0 ? FPRECIS : precis;
- {
- ep = _sfcvt(&dval, imin(precis, SF_FDIGITS),
- &decpt, &sign, 0);
- }
- goto f_format;
- }
- /* 'g' or 'G' format */
- precis = precis < 0 ? FPRECIS : precis == 0 ? 1 : precis;
- {
- ep = _sfcvt(&dval, imin(precis, SF_FDIGITS),
- &decpt, &sign, SFFMT_EFORMAT);
- if (dval == 0.)
- decpt = 1;
- else if (*ep == 'I')
- goto infinite;
- }
- if (!(flags & SFFMT_ALTER)) { /* zap trailing 0s */
- if ((n = sfslen()) > precis)
- n = precis;
- while ((n -= 1) >= 1 && ep[n] == '0');
- n += 1;
- } else
- n = precis;
- if (decpt < -3 || decpt > precis) {
- precis = n - 1;
- goto e_format;
- } else {
- precis = n - decpt;
- goto f_format;
- }
- e_format: /* build the x.yyyy string */
- if (gv_isalpha(*ep))
- goto infinite;
- sp = endsp = buf + 1; /* reserve space for sign */
- *endsp++ = *ep ? *ep++ : '0';
- SFSETLOCALE(decimal, thousand);
- if (precis > 0 || (flags & SFFMT_ALTER))
- *endsp++ = decimal;
- ssp = endsp;
- endep = ep + precis;
- while ((*endsp++ = *ep++) && ep <= endep);
- precis -= (endsp -= 1) - ssp;
- /* build the exponent */
- ep = endep = buf + (sizeof(buf) - 1);
- if (dval != 0.) {
- if ((n = decpt - 1) < 0)
- n = -n;
- while (n > 9) {
- v = n;
- n /= 10;
- *--ep = (char) ('0' + (v - n * 10));
- }
- } else
- n = 0;
- *--ep = (char) ('0' + n);
- if (endep - ep <= 1) /* at least 2 digits */
- *--ep = '0';
- /* the e/Exponent separator and sign */
- *--ep = (decpt > 0 || dval == 0.) ? '+' : '-';
- *--ep = gv_isupper(fmt) ? 'E' : 'e';
- goto end_efg;
- f_format: /* data before the decimal point */
- if (gv_isalpha(*ep)) {
- infinite:
- endsp = (sp = ep) + sfslen();
- ep = endep;
- precis = 0;
- goto end_efg;
- }
- SFSETLOCALE(decimal, thousand);
- endsp = sp = buf + 1; /* save a space for sign */
- endep = ep + decpt;
- if (decpt > 3 && (flags & SFFMT_THOUSAND)) {
- if ((n = decpt % 3) == 0)
- n = 3;
- while (ep < endep && (*endsp++ = *ep++)) {
- if (--n == 0 && (ep <= endep - 3)) {
- *endsp++ = thousand;
- n = 3;
- }
- }
- } else {
- while (ep < endep && (*endsp++ = *ep++));
- }
- if (endsp == sp)
- *endsp++ = '0';
- if (precis > 0 || (flags & SFFMT_ALTER))
- *endsp++ = decimal;
- if ((n = -decpt) > 0) { /* output zeros for negative exponent */
- ssp = endsp + imin(n, precis);
- precis -= n;
- while (endsp < ssp)
- *endsp++ = '0';
- }
- ssp = endsp;
- endep = ep + precis;
- while ((*endsp++ = *ep++) && ep <= endep);
- precis -= (endsp -= 1) - ssp;
- ep = endep;
- end_efg:
- flags |= SFFMT_FLOAT;
- if (sign)
- flags |= SFFMT_MINUS;
- break;
- }
- if (flags == 0 && width <= 0)
- goto do_output;
- if (flags & SFFMT_PREFIX)
- fmt =
- (flags & SFFMT_MINUS) ? '-' : (flags & SFFMT_SIGN) ? '+' :
- ' ';
- n = (endsp - sp) + (endep - ep) + (precis <= 0 ? 0 : precis) +
- ((flags & SFFMT_PREFIX) ? 1 : 0);
- if ((v = width - n) <= 0)
- v = 0;
- else if (!(flags & SFFMT_ZERO)) { /* right padding */
- if (flags & SFFMT_LEFT)
- v = -v;
- else if (flags & SFFMT_PREFIX) { /* blank padding, output prefix now */
- *--sp = fmt;
- flags &= ~SFFMT_PREFIX;
- }
- }
- if (flags & SFFMT_PREFIX) { /* put out the prefix */
- SFputc(f, fmt);
- if (fmt != ' ')
- flags |= SFFMT_ZERO;
- }
- if ((n = v) > 0) { /* left padding */
- v = (flags & SFFMT_ZERO) ? '0' : ' ';
- SFnputc(f, v, n);
- }
- if ((n = precis) > 0 && !(flags & SFFMT_FLOAT)) { /* padding for integer precision */
- SFnputc(f, '0', n);
- precis = 0;
- }
- do_output:
- if ((n = endsp - sp) > 0)
- SFwrite(f, sp, n);
- if (flags & (SFFMT_FLOAT | SFFMT_LEFT)) { /* SFFMT_FLOAT: right padding for float precision */
- if ((n = precis) > 0)
- SFnputc(f, '0', n);
- /* SFFMT_FLOAT: the exponent of %eE */
- if ((n = endep - (sp = ep)) > 0)
- SFwrite(f, sp, n);
- /* SFFMT_LEFT: right padding */
- if ((n = -v) > 0)
- SFnputc(f, ' ', n);
- }
- }
- done:
- return n_output;
- }
|