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