sfprint.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <assert.h>
  11. #include <cgraph/gv_ctype.h>
  12. #include <cgraph/gv_math.h>
  13. #include <inttypes.h>
  14. #include <sfio/sfhdr.h>
  15. #include <stddef.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. /* The engine for formatting data
  19. **
  20. ** Written by Kiem-Phong Vo.
  21. */
  22. #define HIGHBITI (~((~0u) >> 1))
  23. #define HIGHBITL (~((~0ull) >> 1))
  24. #define SFFMT_PREFIX (SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK)
  25. #define FPRECIS 6 /* default precision for floats */
  26. /**
  27. * @param f file to print to
  28. * @param format Structure describing how to print
  29. */
  30. int sfprint(FILE *f, Sffmt_t *format) {
  31. int v = 0, n_s, base, fmt, flags;
  32. long long lv;
  33. char *sp, *ssp, *endsp, *ep, *endep;
  34. int dot, width, precis, n, n_output = 0;
  35. int sign, decpt;
  36. ssize_t size;
  37. double dval;
  38. char *tls[2], **ls; /* for %..[separ]s */
  39. const char *t_str; /* stuff between () */
  40. ssize_t n_str; /* its length */
  41. Argv_t argv; /* for extf to return value */
  42. Sffmt_t *ft; /* format environment */
  43. int argp, argn; /* arg position and number */
  44. #define SLACK 1024
  45. char buf[SF_MAXDIGITS + SLACK];
  46. char decimal = 0, thousand = 0;
  47. #define SFputc(f,c) do { \
  48. if (putc((c), (f)) == EOF) { \
  49. goto done; \
  50. } \
  51. } while (0)
  52. #define SFnputc(f,c,n) do { \
  53. for (int i_ = 0; i_ < (n); ++i_) { \
  54. if (putc((c), (f)) == EOF) { \
  55. goto done; \
  56. } \
  57. } \
  58. (n) = 0; \
  59. } while (0)
  60. #define SFwrite(f,s,n) do { \
  61. if ((n) > 0 && fwrite((s), (size_t)(n), 1, (f)) < 1) { \
  62. goto done; \
  63. } \
  64. } while (0)
  65. tls[1] = NULL;
  66. ft = NULL;
  67. argn = -1;
  68. // stack a new environment
  69. argv.ft = format;
  70. assert(argv.ft != NULL);
  71. assert(argv.ft->form != NULL);
  72. const char *form = argv.ft->form;
  73. ft = argv.ft;
  74. while ((n = *form)) {
  75. if (n != '%') { /* collect the non-pattern chars */
  76. sp = (char *) form++;
  77. while (*form && *form != '%')
  78. form += 1;
  79. n = form - sp;
  80. SFwrite(f, sp, n);
  81. continue;
  82. } else
  83. form += 1;
  84. flags = 0;
  85. size = width = precis = base = n_s = argp = -1;
  86. ssp = _Sfdigits;
  87. endep = ep = NULL;
  88. endsp = sp = buf + (sizeof(buf) - 1);
  89. t_str = NULL;
  90. n_str = dot = 0;
  91. loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
  92. switch ((fmt = *form++)) {
  93. case '\0':
  94. SFputc(f, '%');
  95. goto done;
  96. case '%':
  97. SFputc(f, '%');
  98. continue;
  99. case LEFTP: /* get the type enclosed in balanced parens */
  100. t_str = form;
  101. for (v = 1;;) {
  102. switch (*form++) {
  103. case 0: /* not balancable, retract */
  104. form = t_str;
  105. t_str = NULL;
  106. n_str = 0;
  107. goto loop_flags;
  108. case LEFTP: /* increasing nested level */
  109. v += 1;
  110. continue;
  111. case RIGHTP: /* decreasing nested level */
  112. if ((v -= 1) != 0)
  113. continue;
  114. if (*t_str != '*')
  115. n_str = (form - 1) - t_str;
  116. else {
  117. t_str = _Sffmtintf(t_str + 1, &n);
  118. FP_SET(-1, argn);
  119. FMTSET(ft, form, LEFTP, 0, 0, 0, 0, 0, NULL, 0);
  120. n = ft->extf(&argv, ft);
  121. if (n < 0)
  122. goto done;
  123. assert(ft->flags & SFFMT_VALUE);
  124. if ((t_str = argv.s) && (n_str = (int)ft->size) < 0)
  125. n_str = (ssize_t)strlen(t_str);
  126. }
  127. goto loop_flags;
  128. default:
  129. // skip over
  130. break;
  131. }
  132. }
  133. case '-':
  134. flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;
  135. goto loop_flags;
  136. case '0':
  137. if (!(flags & SFFMT_LEFT))
  138. flags |= SFFMT_ZERO;
  139. goto loop_flags;
  140. case ' ':
  141. if (!(flags & SFFMT_SIGN))
  142. flags |= SFFMT_BLANK;
  143. goto loop_flags;
  144. case '+':
  145. flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN;
  146. goto loop_flags;
  147. case '#':
  148. flags |= SFFMT_ALTER;
  149. goto loop_flags;
  150. case QUOTE:
  151. SFSETLOCALE(decimal, thousand);
  152. if (thousand)
  153. flags |= SFFMT_THOUSAND;
  154. goto loop_flags;
  155. case '.':
  156. dot += 1;
  157. if (dot == 1) { /* so base can be defined without setting precis */
  158. if (*form != '.')
  159. precis = 0;
  160. } else if (dot == 2) {
  161. base = 0; /* for %s,%c */
  162. if (*form == 'c' || *form == 's')
  163. goto loop_flags;
  164. if (*form && !gv_isalnum(*form) &&
  165. (form[1] == 'c' || form[1] == 's')) {
  166. if (*form == '*')
  167. goto do_star;
  168. else {
  169. base = *form++;
  170. goto loop_flags;
  171. }
  172. }
  173. }
  174. if (gv_isdigit(*form)) {
  175. fmt = *form++;
  176. goto dot_size;
  177. } else if (*form != '*')
  178. goto loop_flags;
  179. do_star:
  180. form += 1; /* fall through */
  181. case '*':
  182. form = _Sffmtintf(form, &n);
  183. n = FP_SET(-1, argn);
  184. FMTSET(ft, form, '.', dot, 0, 0, 0, 0, NULL, 0);
  185. if (ft->extf(&argv, ft) < 0)
  186. goto done;
  187. assert(ft->flags & SFFMT_VALUE);
  188. v = argv.i;
  189. goto dot_set;
  190. case '1':
  191. case '2':
  192. case '3':
  193. case '4':
  194. case '5':
  195. case '6':
  196. case '7':
  197. case '8':
  198. case '9':
  199. dot_size:
  200. for (v = fmt - '0'; gv_isdigit(*form); ++form)
  201. v = v * 10 + (*form - '0');
  202. dot_set:
  203. if (dot == 0) {
  204. if ((width = v) < 0) {
  205. width = -width;
  206. flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;
  207. }
  208. } else if (dot == 1)
  209. precis = v;
  210. else if (dot == 2)
  211. base = v;
  212. goto loop_flags;
  213. case 'I': /* object length */
  214. size = 0;
  215. flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
  216. if (gv_isdigit(*form)) {
  217. for (n = *form; gv_isdigit(n); n = *++form)
  218. size = size * 10 + (n - '0');
  219. } else if (*form == '*') {
  220. form = _Sffmtintf(form + 1, &n);
  221. n = FP_SET(-1, argn);
  222. FMTSET(ft, form, 'I', sizeof(int), 0, 0, 0, 0, NULL, 0);
  223. if (ft->extf(&argv, ft) < 0)
  224. goto done;
  225. assert(ft->flags & SFFMT_VALUE);
  226. size = argv.i;
  227. }
  228. goto loop_flags;
  229. case 'l':
  230. size = -1;
  231. flags &= ~SFFMT_TYPES;
  232. if (*form == 'l') {
  233. form += 1;
  234. flags |= SFFMT_LLONG;
  235. } else
  236. flags |= SFFMT_LONG;
  237. goto loop_flags;
  238. case 'h':
  239. size = -1;
  240. flags &= ~SFFMT_TYPES;
  241. if (*form == 'h') {
  242. form += 1;
  243. flags |= SFFMT_SSHORT;
  244. } else
  245. flags |= SFFMT_SHORT;
  246. goto loop_flags;
  247. case 'L':
  248. size = -1;
  249. flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
  250. goto loop_flags;
  251. case 'j':
  252. size = -1;
  253. flags = (flags & ~SFFMT_TYPES) | SFFMT_JFLAG;
  254. goto loop_flags;
  255. case 'z':
  256. size = -1;
  257. flags = (flags & ~SFFMT_TYPES) | SFFMT_ZFLAG;
  258. goto loop_flags;
  259. case 't':
  260. size = -1;
  261. flags = (flags & ~SFFMT_TYPES) | SFFMT_TFLAG;
  262. goto loop_flags;
  263. default: // continue with logic below
  264. break;
  265. }
  266. /* set the correct size */
  267. if (flags & (SFFMT_TYPES & ~SFFMT_IFLAG)) {
  268. if (_Sftype[fmt] & (SFFMT_INT | SFFMT_UINT)) {
  269. size = (flags & SFFMT_LLONG) ? (ssize_t)sizeof(long long) :
  270. (flags & SFFMT_LONG) ? (ssize_t)sizeof(long) :
  271. (flags & SFFMT_SHORT) ? (ssize_t)sizeof(short) :
  272. (flags & SFFMT_SSHORT) ? (ssize_t)sizeof(char) :
  273. (flags & SFFMT_JFLAG) ? (ssize_t)sizeof(long long) :
  274. (flags & SFFMT_TFLAG) ? (ssize_t)sizeof(ptrdiff_t) :
  275. (flags & SFFMT_ZFLAG) ? (ssize_t)sizeof(size_t) : -1;
  276. } else if (_Sftype[fmt] & SFFMT_FLOAT) {
  277. size = (flags & SFFMT_LDOUBLE) ? (ssize_t)sizeof(long double) :
  278. (flags & (SFFMT_LONG | SFFMT_LLONG)) ? (ssize_t)sizeof(double) : -1;
  279. }
  280. }
  281. argp = FP_SET(argp, argn);
  282. FMTSET(ft, form, fmt, size, flags, width, precis, base, t_str, n_str);
  283. v = ft->extf(&argv, ft);
  284. if (v < 0)
  285. goto done;
  286. else if (v == 0) { // extf did not output
  287. FMTGET(ft, form, fmt, size, flags, width, precis, base);
  288. assert(ft->flags & SFFMT_VALUE);
  289. } else if (v > 0) { // extf output v bytes
  290. n_output += v;
  291. continue;
  292. }
  293. switch (fmt) { /* PRINTF DIRECTIVES */
  294. default: /* unknown directive */
  295. form -= 1;
  296. argn -= 1;
  297. continue;
  298. case 's':
  299. if (base >= 0) { /* list of strings */
  300. if (!(ls = argv.sp) || !ls[0])
  301. continue;
  302. } else {
  303. if (!(sp = argv.s))
  304. sp = "(null)";
  305. ls = tls;
  306. tls[0] = sp;
  307. }
  308. for (sp = *ls;;) {
  309. if ((v = size) >= 0) {
  310. if (precis >= 0 && v > precis)
  311. v = precis;
  312. } else if (precis < 0)
  313. v = strlen(sp);
  314. else { /* precis >= 0 means min(strlen,precis) */
  315. for (v = 0; v < precis; ++v)
  316. if (sp[v] == 0)
  317. break;
  318. }
  319. if ((n = width - v) > 0) {
  320. if (flags & SFFMT_ZERO) {
  321. SFnputc(f, '0', n);
  322. } else if (!(flags & SFFMT_LEFT)) {
  323. SFnputc(f, ' ', n);
  324. }
  325. }
  326. SFwrite(f, sp, v);
  327. if (n > 0) {
  328. SFnputc(f, ' ', n);
  329. }
  330. if (!(sp = *++ls))
  331. break;
  332. else if (base > 0) {
  333. SFputc(f, base);
  334. }
  335. }
  336. continue;
  337. case 'c': /* an array of characters */
  338. if (base >= 0) {
  339. if (!(sp = argv.s) || !sp[0])
  340. continue;
  341. } else {
  342. fmt = (int) argv.c;
  343. sp = buf;
  344. buf[0] = fmt;
  345. buf[1] = 0;
  346. }
  347. if (precis <= 0)
  348. precis = 1;
  349. for (fmt = *sp;;) {
  350. if ((n = width - precis) > 0 && !(flags & SFFMT_LEFT)) {
  351. SFnputc(f, ' ', n);
  352. }
  353. v = precis;
  354. SFnputc(f, fmt, v);
  355. if (n > 0) {
  356. SFnputc(f, ' ', n);
  357. }
  358. if (!(fmt = *++sp))
  359. break;
  360. else if (base > 0) {
  361. SFputc(f, base);
  362. }
  363. }
  364. continue;
  365. case 'p': /* pointer value */
  366. fmt = 'x';
  367. base = 16;
  368. n_s = 15;
  369. n = 4;
  370. flags =
  371. (flags & ~(SFFMT_SIGN | SFFMT_BLANK | SFFMT_ZERO)) |
  372. SFFMT_ALTER;
  373. if (sizeof(void*) > sizeof(int)) {
  374. lv = (long long)(intptr_t)argv.vp;
  375. goto long_cvt;
  376. } else {
  377. v = (int)(intptr_t)argv.vp;
  378. goto int_cvt;
  379. }
  380. case 'o':
  381. base = 8;
  382. n_s = 7;
  383. n = 3;
  384. flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
  385. goto int_arg;
  386. case 'X':
  387. ssp = "0123456789ABCDEF";
  388. // fall through
  389. case 'x':
  390. base = 16;
  391. n_s = 15;
  392. n = 4;
  393. flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
  394. goto int_arg;
  395. case 'i':
  396. fmt = 'd';
  397. goto d_format;
  398. case 'u':
  399. flags &= ~(SFFMT_SIGN | SFFMT_BLANK);
  400. // fall through
  401. case 'd':
  402. d_format:
  403. if (base < 2 || base > SF_RADIX)
  404. base = 10;
  405. if ((base & (n_s = base - 1)) == 0) {
  406. if (base < 8)
  407. n = base < 4 ? 1 : 2;
  408. else if (base < 32)
  409. n = base < 16 ? 3 : 4;
  410. else
  411. n = base < 64 ? 5 : 6;
  412. } else
  413. n_s = base == 10 ? -1 : 0;
  414. int_arg:
  415. if ((sizeof(long) > sizeof(int) || sizeof(void*) > sizeof(int))
  416. && FMTCMP(size, long long, long long)) {
  417. lv = argv.ll;
  418. goto long_cvt;
  419. } else if ((sizeof(long) > sizeof(int) || sizeof(void*) > sizeof(int))
  420. && FMTCMP(size, long, long long)) {
  421. if (fmt == 'd')
  422. lv = (long long)argv.l;
  423. else
  424. lv = (long long)(ulong)argv.l;
  425. long_cvt:
  426. if (lv == 0 && precis == 0)
  427. break;
  428. if (lv < 0 && fmt == 'd') {
  429. flags |= SFFMT_MINUS;
  430. if ((unsigned long long)lv == HIGHBITL) { // avoid overflow
  431. lv = (long long)(HIGHBITL / (unsigned long long)base);
  432. *--sp = _Sfdigits[HIGHBITL -
  433. (unsigned long long)lv * (unsigned long long)base];
  434. } else
  435. lv = -lv;
  436. }
  437. if (n_s < 0) { /* base 10 */
  438. long long nv;
  439. sfucvt(lv, sp, nv, ssp, long long, unsigned long long);
  440. } else if (n_s > 0) { /* base power-of-2 */
  441. do {
  442. *--sp = ssp[lv & n_s];
  443. } while ((lv = (unsigned long long)lv >> n));
  444. } else { /* general base */
  445. do {
  446. *--sp = ssp[(unsigned long long)lv % (unsigned long long)base];
  447. } while ((lv = (unsigned long long)lv / (unsigned long long)base));
  448. }
  449. } else
  450. if (sizeof(short) < sizeof(int) && FMTCMP(size, short, long long)) {
  451. if (ft->flags & SFFMT_VALUE) {
  452. if (fmt == 'd')
  453. v = (int) ((short) argv.h);
  454. else
  455. v = (int) ((ushort) argv.h);
  456. } else {
  457. if (fmt == 'd')
  458. v = (int) ((short) argv.i);
  459. else
  460. v = (int) ((ushort) argv.i);
  461. }
  462. goto int_cvt;
  463. } else if (size == sizeof(char)) {
  464. if (ft->flags & SFFMT_VALUE) {
  465. if (fmt == 'd')
  466. v = (int) ((char) argv.c);
  467. else
  468. v = (int) ((uchar) argv.c);
  469. } else {
  470. if (fmt == 'd')
  471. v = (int) ((char) argv.i);
  472. else
  473. v = (int) ((uchar) argv.i);
  474. }
  475. goto int_cvt;
  476. } else {
  477. v = argv.i;
  478. int_cvt:
  479. if (v == 0 && precis == 0)
  480. break;
  481. if (v < 0 && fmt == 'd') {
  482. flags |= SFFMT_MINUS;
  483. if ((unsigned)v == HIGHBITI) { // avoid overflow
  484. v = (int)(HIGHBITI / (unsigned)base);
  485. *--sp = _Sfdigits[HIGHBITI - (unsigned)v * (unsigned)base];
  486. } else
  487. v = -v;
  488. }
  489. if (n_s < 0) { /* base 10 */
  490. sfucvt(v, sp, n, ssp, int, unsigned);
  491. } else if (n_s > 0) { /* base power-of-2 */
  492. do {
  493. *--sp = ssp[v & n_s];
  494. } while ((v = (unsigned)v >> n));
  495. } else { /* n_s == 0, general base */
  496. do {
  497. *--sp = ssp[(unsigned)v % (unsigned)base];
  498. } while ((v = (unsigned)v / (unsigned)base));
  499. }
  500. }
  501. if (n_s < 0 && (flags & SFFMT_THOUSAND)
  502. && (n = endsp - sp) > 3) {
  503. if ((n %= 3) == 0)
  504. n = 3;
  505. for (ep = buf + SLACK, endep = ep + n;;) {
  506. while (ep < endep)
  507. *ep++ = *sp++;
  508. if (sp == endsp)
  509. break;
  510. if (sp <= endsp - 3)
  511. *ep++ = thousand;
  512. endep = ep + 3;
  513. }
  514. sp = buf + SLACK;
  515. endsp = ep;
  516. }
  517. /* zero padding for precision if have room in buffer */
  518. if (precis > 0 && (precis -= (endsp - sp)) < (sp - buf) - 64)
  519. while (precis-- > 0)
  520. *--sp = '0';
  521. if (flags & SFFMT_ALTER) { /* prefix */
  522. if (fmt == 'o') {
  523. if (*sp != '0')
  524. *--sp = '0';
  525. } else {
  526. if (width > 0 && (flags & SFFMT_ZERO)) { /* do 0 padding first */
  527. if (fmt == 'x' || fmt == 'X')
  528. n = 0;
  529. else if (dot < 2)
  530. n = width;
  531. else
  532. n = base < 10 ? 2 : 3;
  533. n += (flags & (SFFMT_MINUS | SFFMT_SIGN)) ? 1 : 0;
  534. n = width - (n + (endsp - sp));
  535. while (n-- > 0)
  536. *--sp = '0';
  537. }
  538. if (fmt == 'x' || fmt == 'X') {
  539. *--sp = (char) fmt;
  540. *--sp = '0';
  541. } else if (dot >= 2) { /* base#value notation */
  542. *--sp = '#';
  543. if (base < 10)
  544. *--sp = (char) ('0' + base);
  545. else {
  546. *--sp = _Sfdec[(base <<= 1) + 1];
  547. *--sp = _Sfdec[base];
  548. }
  549. }
  550. }
  551. }
  552. break;
  553. case 'g':
  554. case 'G': /* these ultimately become %e or %f */
  555. case 'e':
  556. case 'E':
  557. case 'f':
  558. if (!(ft->flags & SFFMT_VALUE) || FMTCMP(size, double, long double))
  559. dval = argv.d;
  560. else
  561. dval = (double) argv.f;
  562. if (fmt == 'e' || fmt == 'E') {
  563. n = (precis = precis < 0 ? FPRECIS : precis) + 1;
  564. {
  565. ep = _sfcvt(&dval, imin(n, SF_FDIGITS),
  566. &decpt, &sign, SFFMT_EFORMAT);
  567. }
  568. goto e_format;
  569. } else if (fmt == 'f' || fmt == 'F') {
  570. precis = precis < 0 ? FPRECIS : precis;
  571. {
  572. ep = _sfcvt(&dval, imin(precis, SF_FDIGITS),
  573. &decpt, &sign, 0);
  574. }
  575. goto f_format;
  576. }
  577. /* 'g' or 'G' format */
  578. precis = precis < 0 ? FPRECIS : precis == 0 ? 1 : precis;
  579. {
  580. ep = _sfcvt(&dval, imin(precis, SF_FDIGITS),
  581. &decpt, &sign, SFFMT_EFORMAT);
  582. if (dval == 0.)
  583. decpt = 1;
  584. else if (*ep == 'I')
  585. goto infinite;
  586. }
  587. if (!(flags & SFFMT_ALTER)) { /* zap trailing 0s */
  588. if ((n = sfslen()) > precis)
  589. n = precis;
  590. while ((n -= 1) >= 1 && ep[n] == '0');
  591. n += 1;
  592. } else
  593. n = precis;
  594. if (decpt < -3 || decpt > precis) {
  595. precis = n - 1;
  596. goto e_format;
  597. } else {
  598. precis = n - decpt;
  599. goto f_format;
  600. }
  601. e_format: /* build the x.yyyy string */
  602. if (gv_isalpha(*ep))
  603. goto infinite;
  604. sp = endsp = buf + 1; /* reserve space for sign */
  605. *endsp++ = *ep ? *ep++ : '0';
  606. SFSETLOCALE(decimal, thousand);
  607. if (precis > 0 || (flags & SFFMT_ALTER))
  608. *endsp++ = decimal;
  609. ssp = endsp;
  610. endep = ep + precis;
  611. while ((*endsp++ = *ep++) && ep <= endep);
  612. precis -= (endsp -= 1) - ssp;
  613. /* build the exponent */
  614. ep = endep = buf + (sizeof(buf) - 1);
  615. if (dval != 0.) {
  616. if ((n = decpt - 1) < 0)
  617. n = -n;
  618. while (n > 9) {
  619. v = n;
  620. n /= 10;
  621. *--ep = (char) ('0' + (v - n * 10));
  622. }
  623. } else
  624. n = 0;
  625. *--ep = (char) ('0' + n);
  626. if (endep - ep <= 1) /* at least 2 digits */
  627. *--ep = '0';
  628. /* the e/Exponent separator and sign */
  629. *--ep = (decpt > 0 || dval == 0.) ? '+' : '-';
  630. *--ep = gv_isupper(fmt) ? 'E' : 'e';
  631. goto end_efg;
  632. f_format: /* data before the decimal point */
  633. if (gv_isalpha(*ep)) {
  634. infinite:
  635. endsp = (sp = ep) + sfslen();
  636. ep = endep;
  637. precis = 0;
  638. goto end_efg;
  639. }
  640. SFSETLOCALE(decimal, thousand);
  641. endsp = sp = buf + 1; /* save a space for sign */
  642. endep = ep + decpt;
  643. if (decpt > 3 && (flags & SFFMT_THOUSAND)) {
  644. if ((n = decpt % 3) == 0)
  645. n = 3;
  646. while (ep < endep && (*endsp++ = *ep++)) {
  647. if (--n == 0 && (ep <= endep - 3)) {
  648. *endsp++ = thousand;
  649. n = 3;
  650. }
  651. }
  652. } else {
  653. while (ep < endep && (*endsp++ = *ep++));
  654. }
  655. if (endsp == sp)
  656. *endsp++ = '0';
  657. if (precis > 0 || (flags & SFFMT_ALTER))
  658. *endsp++ = decimal;
  659. if ((n = -decpt) > 0) { /* output zeros for negative exponent */
  660. ssp = endsp + imin(n, precis);
  661. precis -= n;
  662. while (endsp < ssp)
  663. *endsp++ = '0';
  664. }
  665. ssp = endsp;
  666. endep = ep + precis;
  667. while ((*endsp++ = *ep++) && ep <= endep);
  668. precis -= (endsp -= 1) - ssp;
  669. ep = endep;
  670. end_efg:
  671. flags |= SFFMT_FLOAT;
  672. if (sign)
  673. flags |= SFFMT_MINUS;
  674. break;
  675. }
  676. if (flags == 0 && width <= 0)
  677. goto do_output;
  678. if (flags & SFFMT_PREFIX)
  679. fmt =
  680. (flags & SFFMT_MINUS) ? '-' : (flags & SFFMT_SIGN) ? '+' :
  681. ' ';
  682. n = (endsp - sp) + (endep - ep) + (precis <= 0 ? 0 : precis) +
  683. ((flags & SFFMT_PREFIX) ? 1 : 0);
  684. if ((v = width - n) <= 0)
  685. v = 0;
  686. else if (!(flags & SFFMT_ZERO)) { /* right padding */
  687. if (flags & SFFMT_LEFT)
  688. v = -v;
  689. else if (flags & SFFMT_PREFIX) { /* blank padding, output prefix now */
  690. *--sp = fmt;
  691. flags &= ~SFFMT_PREFIX;
  692. }
  693. }
  694. if (flags & SFFMT_PREFIX) { /* put out the prefix */
  695. SFputc(f, fmt);
  696. if (fmt != ' ')
  697. flags |= SFFMT_ZERO;
  698. }
  699. if ((n = v) > 0) { /* left padding */
  700. v = (flags & SFFMT_ZERO) ? '0' : ' ';
  701. SFnputc(f, v, n);
  702. }
  703. if ((n = precis) > 0 && !(flags & SFFMT_FLOAT)) { /* padding for integer precision */
  704. SFnputc(f, '0', n);
  705. precis = 0;
  706. }
  707. do_output:
  708. if ((n = endsp - sp) > 0)
  709. SFwrite(f, sp, n);
  710. if (flags & (SFFMT_FLOAT | SFFMT_LEFT)) { /* SFFMT_FLOAT: right padding for float precision */
  711. if ((n = precis) > 0)
  712. SFnputc(f, '0', n);
  713. /* SFFMT_FLOAT: the exponent of %eE */
  714. if ((n = endep - (sp = ep)) > 0)
  715. SFwrite(f, sp, n);
  716. /* SFFMT_LEFT: right padding */
  717. if ((n = -v) > 0)
  718. SFnputc(f, ' ', n);
  719. }
  720. }
  721. done:
  722. return n_output;
  723. }