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