1 /* the ti-x embed operation system
3 * it is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * it is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with it; If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>
16 * Copyright (C) 2009, Ruki All rights reserved.
17 * Home: <a href="http://www.xxx.org">http://www.xxx.org</a>
25 /* ////////////////////////////////////////////////////////////////////////
33 /* ////////////////////////////////////////////////////////////////////////
38 typedef enum __ti_printf_type_t
43 , TI_PRINTF_TYPE_CHAR_PERCENT
44 , TI_PRINTF_TYPE_FLOAT
45 , TI_PRINTF_TYPE_STRING
46 , TI_PRINTF_TYPE_WIDTH
47 , TI_PRINTF_TYPE_PRECISION
48 , TI_PRINTF_TYPE_INVALID
52 // printf format extra info
53 typedef enum __ti_printf_extra_t
55 TI_PRINTF_EXTRA_NONE
= 0
56 , TI_PRINTF_EXTRA_SIGNED
= 1 // signed integer for %d %i
57 , TI_PRINTF_EXTRA_UPPER
= 2 // upper case for %X %B
58 , TI_PRINTF_EXTRA_PERCENT
= 4 // percent char: %
59 , TI_PRINTF_EXTRA_EXP
= 8 // exponent form: [-]d.ddd e[+/-]ddd
63 // printf length qualifier
64 typedef enum __ti_printf_qual_t
76 typedef enum __ti_printf_flag_t
78 TI_PRINTF_FLAG_NONE
= 0
79 , TI_PRINTF_FLAG_PLUS
= 1 // +: denote the sign '+' or '-' of a number
80 , TI_PRINTF_FLAG_LEFT
= 2 // -: left-justified
81 , TI_PRINTF_FLAG_ZERO
= 4 // 0: fill 0 instead of spaces
82 , TI_PRINTF_FLAG_PFIX
= 8 // #: add prefix
87 typedef struct __ti_printf_entry_t
90 ti_printf_type_t type
;
93 ti_printf_extra_t extra
;
96 ti_printf_flag_t flags
;
105 ti_printf_qual_t qual
;
113 /* ////////////////////////////////////////////////////////////////////////
114 * internal declaration
118 ti_int_t
__strlen(ti_char_t
const* s
);
119 ti_int_t
__strnlen(ti_char_t
const* s
, ti_int_t n
);
121 // string comparision
122 ti_int_t
__strcmp(ti_char_t
const* lhs
, ti_char_t
const* rhs
);
123 ti_int_t
__strncmp(ti_char_t
const* lhs
, ti_char_t
const* rhs
, ti_size_t n
);
126 ti_char_t
const* __strcpy(ti_char_t
* pd
, ti_char_t
const* ps
);
127 ti_char_t
const* __strncpy(ti_char_t
* pd
, ti_char_t
const* ps
, ti_size_t n
);
129 ti_int_t
__vsnprintf(ti_char_t
* s
, ti_size_t n
, ti_char_t
const* fmt
, ti_va_list_t args
);
130 ti_int_t
__vsprintf(ti_char_t
* s
, ti_char_t
const* fmt
, ti_va_list_t args
);
132 /* ////////////////////////////////////////////////////////////////////////
136 static ti_int_t
ti_skip_atoi(ti_char_t
const** s
)
139 while (ti_isdigit(**s
) == TI_TRUE
)
140 i
= i
* 10 + *((*s
)++) - '0';
143 static ti_char_t
* ti_printf_string(ti_char_t
* pb
, ti_char_t
* pe
, ti_printf_entry_t e
, ti_char_t
const* s
)
145 ti_int_t n
= ti_strnlen(s
, e
.precision
);
147 // fill space at left side, e.g. " abcd"
148 if (!(e
.flags
& TI_PRINTF_FLAG_LEFT
))
150 while (n
< e
.width
--)
151 if (pb
< pe
) *pb
++ = ' ';
156 for (i
= 0; i
< n
; ++i
)
157 if (pb
< pe
) *pb
++ = *s
++;
159 // fill space at right side, e.g. "abcd "
160 while (n
< e
.width
--)
161 if (pb
< pe
) *pb
++ = ' ';
165 static ti_char_t
* ti_printf_integer(ti_char_t
* pb
, ti_char_t
* pe
, ti_printf_entry_t e
, ti_uint64_t num
)
168 static ti_char_t
const digits_table
[16] = "0123456789ABCDEF";
170 // max: 64-bit binary decimal
171 ti_char_t digits
[64] = {0};
172 ti_int_t digit_i
= 0;
174 // lowercase mask, e.g. 'F' | 0x20 => 'f'
175 ti_int_t lomask
= (e
.extra
& TI_PRINTF_EXTRA_UPPER
)? 0x0 : 0x20;
179 if (e
.extra
& TI_PRINTF_EXTRA_SIGNED
)
181 if ((ti_int64_t
)num
< 0)
186 else if (e
.flags
& TI_PRINTF_FLAG_PLUS
)
193 // convert num => digits string in reverse order
194 if (num
== 0) digits
[digit_i
++] = '0';
197 if ((ti_int64_t
)num
< 0) num
= (ti_uint64_t
)(-(ti_int64_t
)num
);
202 digits
[digit_i
++] = digits_table
[num
% e
.base
] | lomask
;
209 ti_int_t shift_bits
= 4;
210 if (e
.base
== 8) shift_bits
--;
211 else if (e
.base
== 2) shift_bits
-= 3;
214 digits
[digit_i
++] = digits_table
[(ti_uint8_t
)num
& (e
.base
- 1)] | lomask
;
223 digits
[digit_i
++] = digits_table
[num
% e
.base
] | lomask
;
232 if (digit_i
> e
.precision
)
233 e
.precision
= digit_i
;
235 // fill spaces at left side, e.g. " 0x0"
236 e
.width
-= e
.precision
;
237 if (!(e
.flags
& (TI_PRINTF_FLAG_LEFT
+ TI_PRINTF_FLAG_ZERO
)))
239 while (--e
.width
>= 0)
240 if (pb
< pe
) *pb
++ = ' ';
243 // append sign: + / -
244 if (sign
&& (pb
< pe
)) *pb
++ = sign
;
246 // append prefix: 0x..., 0X..., 0b..., 0B...
247 if (e
.flags
& TI_PRINTF_FLAG_PFIX
)
256 *pb
++ = 'X' | lomask
;
275 *pb
++ = 'B' | lomask
;
285 // fill 0 or spaces, e.g. "0x ff"
286 if (!(e
.flags
& TI_PRINTF_FLAG_LEFT
))
288 ti_char_t c
= (e
.flags
& TI_PRINTF_FLAG_ZERO
)? '0' : ' ';
289 while (--e
.width
>= 0)
290 if (pb
< pe
) *pb
++ = c
;
293 // fill 0 if precision is larger, e.g. "0x000ff"
294 while (digit_i
<= --e
.precision
)
295 if (pb
< pe
) *pb
++ = '0';
298 while (--digit_i
>= 0)
299 if (pb
< pe
) *pb
++ = digits
[digit_i
];
301 // trailing space padding for left-justified flags, e.g. "0xff "
302 while (--e
.width
>= 0)
303 if (pb
< pe
) *pb
++ = ' ';
307 #ifdef TI_ARCH_HAVE_FLOAT
308 // only support double float-point
309 static ti_char_t
* ti_printf_float(ti_char_t
* pb
, ti_char_t
* pe
, ti_printf_entry_t e
, ti_float_t num
)
312 ti_char_t ints
[64] = {0};
313 ti_char_t decs
[64] = {0};
314 ti_int_t ints_i
= 0, decs_i
= 0;
318 if (e
.extra
& TI_PRINTF_EXTRA_SIGNED
)
325 else if (e
.flags
& TI_PRINTF_FLAG_PLUS
)
333 if (num
< 0) num
= -num
;
335 // get integer & decimal
336 ti_int64_t integer
= (ti_int64_t
)num
;
337 ti_float_t decimal
= num
- integer
;
339 // convert integer => digits string in reverse order
340 if (integer
== 0) ints
[ints_i
++] = '0';
343 if (integer
< 0) integer
= -integer
;
346 ints
[ints_i
++] = (integer
% 10) + '0';
352 // default precision: 6
353 if (e
.precision
<= 0) e
.precision
= 6;
355 // convert decimal => digits string in positive order
356 if (decimal
== 0) decs
[decs_i
++] = '0';
359 ti_int_t d
= (ti_int_t
)(decimal
* 10);
362 decs
[decs_i
++] = d
+ '0';
363 decimal
= decimal
* 10 - d
;
364 d
= (ti_int_t
)(decimal
* 10);
366 while (decs_i
< e
.precision
);
370 if (decs_i
> e
.precision
)
371 decs_i
= e
.precision
;
373 // fill spaces at left side, e.g. " 0.31415926"
374 e
.width
-= ints_i
+ 1 + e
.precision
;
375 if (!(e
.flags
& (TI_PRINTF_FLAG_LEFT
+ TI_PRINTF_FLAG_ZERO
)))
377 while (--e
.width
>= 0)
378 if (pb
< pe
) *pb
++ = ' ';
381 // append sign: + / -
382 if (sign
&& (pb
< pe
)) *pb
++ = sign
;
384 // fill 0 or spaces, e.g. "00003.1415926"
385 if (!(e
.flags
& TI_PRINTF_FLAG_LEFT
))
387 ti_char_t c
= (e
.flags
& TI_PRINTF_FLAG_ZERO
)? '0' : ' ';
388 while (--e
.width
>= 0)
389 if (pb
< pe
) *pb
++ = c
;
393 while (--ints_i
>= 0)
394 if (pb
< pe
) *pb
++ = ints
[ints_i
];
397 if (pb
< pe
) *pb
++ = '.';
400 ti_int_t decs_n
= decs_i
;
401 while (--decs_i
>= 0)
402 if (pb
< pe
) *pb
++ = decs
[decs_n
- decs_i
- 1];
404 // fill 0 if precision is larger, e.g. "0.3140000"
405 while (decs_n
<= --e
.precision
)
406 if (pb
< pe
) *pb
++ = '0';
408 // trailing space padding for left-justified flags, e.g. "0.31415926 "
409 while (--e
.width
>= 0)
410 if (pb
< pe
) *pb
++ = ' ';
415 // get a printf format entry
416 static ti_int_t
ti_printf_entry(ti_char_t
const* fmt
, ti_printf_entry_t
* e
)
418 ti_char_t
const* p
= fmt
;
420 // get field width for *
421 if (e
->type
== TI_PRINTF_TYPE_WIDTH
)
425 e
->width
= -e
->width
;
426 e
->flags
|= TI_PRINTF_FLAG_LEFT
;
428 e
->type
= TI_PRINTF_TYPE_NONE
;
432 // get precision for *
433 if (e
->type
== TI_PRINTF_TYPE_PRECISION
)
435 if (e
->precision
< 0) e
->precision
= 0;
436 e
->type
= TI_PRINTF_TYPE_NONE
;
441 e
->type
= TI_PRINTF_TYPE_NONE
;
445 if (*p
== '%') break;
447 // return non-format string
455 e
->flags
= TI_PRINTF_FLAG_NONE
;
458 ti_bool_t is_found
= TI_TRUE
;
461 case '+': e
->flags
|= TI_PRINTF_FLAG_PLUS
; break;
462 case '-': e
->flags
|= TI_PRINTF_FLAG_LEFT
; break;
463 case '0': e
->flags
|= TI_PRINTF_FLAG_ZERO
; break;
464 case '#': e
->flags
|= TI_PRINTF_FLAG_PFIX
; break;
465 default: is_found
= TI_FALSE
; break;
467 if (is_found
== TI_FALSE
) break;
473 if (ti_isdigit(*p
) == TI_TRUE
) e
->width
= ti_skip_atoi(&p
);
476 // it's the next argument
477 e
->type
= TI_PRINTF_TYPE_WIDTH
;
487 if (ti_isdigit(*p
) == TI_TRUE
)
489 e
->precision
= ti_skip_atoi(&p
);
490 if (e
->precision
< 0) e
->precision
= 0;
494 // it's the next argument
495 e
->type
= TI_PRINTF_TYPE_PRECISION
;
501 // get length qualifier
502 e
->qual
= TI_PRINTF_QUAL_NONE
;
505 // short & long => int
511 e
->qual
= TI_PRINTF_QUAL_I64
;
514 else e
->qual
= TI_PRINTF_QUAL_I
;
519 ti_int_t n
= ti_skip_atoi(&p
);
522 case 8: e
->qual
= TI_PRINTF_QUAL_I8
; break;
523 case 16: e
->qual
= TI_PRINTF_QUAL_I16
; break;
524 case 32: e
->qual
= TI_PRINTF_QUAL_I32
; break;
525 case 64: e
->qual
= TI_PRINTF_QUAL_I64
; break;
526 default: e
->qual
= TI_PRINTF_QUAL_I
; break;
531 e
->qual
= TI_PRINTF_QUAL_NONE
;
537 e
->type
= TI_PRINTF_TYPE_INVALID
;
538 e
->extra
= TI_PRINTF_EXTRA_NONE
;
542 e
->type
= TI_PRINTF_TYPE_STRING
;
545 e
->extra
|= TI_PRINTF_EXTRA_PERCENT
;
547 e
->type
= TI_PRINTF_TYPE_CHAR
;
551 e
->extra
|= TI_PRINTF_EXTRA_SIGNED
;
554 e
->type
= TI_PRINTF_TYPE_INT
;
557 e
->extra
|= TI_PRINTF_EXTRA_UPPER
;
560 e
->type
= TI_PRINTF_TYPE_INT
;
564 e
->type
= TI_PRINTF_TYPE_INT
;
567 e
->extra
|= TI_PRINTF_EXTRA_UPPER
;
570 e
->type
= TI_PRINTF_TYPE_INT
;
572 #ifdef TI_CONFIG_FLOAT
574 e
->extra
|= TI_PRINTF_EXTRA_UPPER
;
576 e
->type
= TI_PRINTF_TYPE_FLOAT
;
577 e
->extra
|= TI_PRINTF_EXTRA_SIGNED
;
580 e
->extra
|= TI_PRINTF_EXTRA_UPPER
;
582 e
->type
= TI_PRINTF_TYPE_FLOAT
;
583 e
->extra
|= TI_PRINTF_EXTRA_SIGNED
;
584 e
->extra
|= TI_PRINTF_EXTRA_EXP
;
588 e
->type
= TI_PRINTF_TYPE_INVALID
;
595 /* ////////////////////////////////////////////////////////////////////////
596 * interface implemetion
599 ti_int_t
ti_strlen(ti_char_t
const* s
)
601 #ifndef TI_ARCH_SPEC_HAVE_STRLEN
603 for (ps
= s
; *ps
!= '\0'; ++ps
) ;
609 ti_int_t
ti_strnlen(ti_char_t
const* s
, ti_int_t n
)
611 #ifndef TI_ARCH_SPEC_HAVE_STRNLEN
613 for (ps
= s
; n
-- && *ps
!= '\0'; ++ps
) ;
616 return __strnlen(s
, n
);
619 ti_char_t
const* ti_strcpy(ti_char_t
* pd
, ti_char_t
const* ps
)
621 #ifndef TI_ARCH_SPEC_HAVE_STRCPY
622 ti_char_t
const* p
= pd
;
623 while ((*pd
++ = *ps
++) != '\0') ;
626 return __strcpy(pd
, ps
);
629 ti_char_t
const* ti_strncpy(ti_char_t
* pd
, ti_char_t
const* ps
, ti_size_t n
)
631 #ifndef TI_ARCH_SPEC_HAVE_STRNCPY
632 ti_char_t
const* p
= pd
;
635 if ((*pd
= *ps
) != 0) ps
++;
641 return __strncpy(pd
, ps
, n
);
644 ti_bool_t
ti_strcmp(ti_char_t
const* lhs
, ti_char_t
const* rhs
)
646 #ifndef TI_ARCH_SPEC_HAVE_STRCMP
650 if ((ret
= *lhs
- *rhs
++) != 0 || !*lhs
++)
653 return ((ret
== 0)? TI_TRUE
: TI_FALSE
);
655 return ((__strcmp(lhs
, rhs
) == 0)? TI_TRUE
: TI_FALSE
);
658 ti_bool_t
ti_strncmp(ti_char_t
const* lhs
, ti_char_t
const* rhs
, ti_size_t n
)
660 #ifndef TI_ARCH_SPEC_HAVE_STRNCMP
664 if ((ret
= *lhs
- *rhs
++) != 0 || !*lhs
++)
668 return ((ret
== 0)? TI_TRUE
: TI_FALSE
);
670 return ((__strncmp(lhs
, rhs
, n
) == 0)? TI_TRUE
: TI_FALSE
);
674 /*! format a string and place it in a buffer
676 * \param s: the buffer to place the result into
677 * \param n: the size of the buffer, including the trailing null space
678 * \param fmt: the format string to use
679 * \param args: arguments for the format string
681 * return the number of characters which would be generated for the given input,
682 * excluding the trailing '\0'.
684 * format: %[flags][width][.precision][qualifier]type
687 * - default: right-justified, left-pad the output with spaces until the required length of output is attained.
688 * If combined with '0' (see below),
689 * it will cause the sign to become a space when positive,
690 * but the remaining characters will be zero-padded
691 * - -: left-justified, e.g. %-d
692 * - +: denote the sign '+' or '-' of a number
693 * - 0: use 0 instead of spaces to left-fill a fixed-length field
694 * - #: add prefix or suffix
695 * - %#o => add prefix: 0...
696 * - %#x => add prefix: 0x...
697 * - %#X => add prefix: 0X...
698 * - %#b => add prefix: 0b...
699 * - %#B => add prefix: 0B...
700 * - %#f => add prefix: 0f...
701 * - %#F => add prefix: 0F...
704 * - n: n = 1, 2, 3, ..., fill spaces
705 * - 0n: n = 1, 2, 3, ..., fill 0
706 * - *: causes printf to pad the output until it is n characters wide,
707 * where n is an integer value stored in the a function argument just preceding
708 * that represented by the modified type.
709 * e.g. printf("%*d", 5, 10) will result in "10" being printed with a width of 5.
712 * - .n: for non-integral numeric types, causes the decimal portion of the output to be expressed in at least number digits.
713 * for the string type, causes the output to be truncated at number characters.
714 * if the precision is zero, nothing is printed for the corresponding argument.
715 * - *: same as the above, but uses an integer value in the intaken argument to
716 * determine the number of decimal places or maximum string length.
717 * e.g. printf("%.*s", 3, "abcdef") will result in "abc" being printed.
720 * - h: short integer or single float-point
721 * - l: long integer or double float-point
722 * - I8: 8-bit integer
723 * - I16: 16-bit integer
724 * - I32: 32-bit integer
725 * - I64/ll: 64-bit integer
728 * support: h, l, I8, I16, I32, I64, ll
731 * - type(e.g. %d %x %u %% ...):
732 * - d, i: print an int as a signed decimal number.
733 * '%d' and '%i' are synonymous for output, but are different when used with scanf() for input.
734 * - u: print decimal unsigned int.
735 * - o: print an unsigned int in octal.
736 * - x/X: print an unsigned int as a hexadecimal number. 'x' uses lower-case letters and 'X' uses upper-case.
737 * - b/B: print an unsigned binary interger
738 * - e/E: print a double value in standard form ([-]d.ddd e[+/-]ddd).
739 * An E conversion uses the letter E (rather than e) to introduce the exponent.
740 * The exponent always contains at least two digits; if the value is zero, the exponent is 00.
742 * - f/F: Print a double in normal (fixed-point) notation.
743 * 'f' and 'F' only differs in how the strings for an infinite number or NaN are printed
744 * ('inf', 'infinity' and 'nan' for 'f', 'INF', 'INFINITY' and 'NAN' for 'F').
745 * - g/G: print a double in either normal or exponential notation, whichever is more appropriate for its magnitude.
746 * 'g' uses lower-case letters, 'G' uses upper-case letters.
747 * This type differs slightly from fixed-point notation in
748 * that insignificant zeroes to the right of the decimal point are not included.
749 * Also, the decimal point is not included on whole numbers.
750 * - c: print a char (character).
751 * - s: print a character string
752 * - p: print a void * (pointer to void) in an implementation-defined format.
753 * - n: print nothing, but write number of characters successfully written so far into an integer pointer parameter.
757 * support: d, i, u, o, u, x/X, b/B, f/F, c, s, %
758 * not support: e/E, g/G, p, n
762 * ti_printf("|hello world|\n");
763 ti_printf("|%-10s|%%|%10s|\n", "hello", "world");
764 ti_printf("|%#2c|%2.5c|%*c|\n", 'A', 'B', 5, 'C');
765 ti_printf("|%#2d|%#8.3o|%*.*d|\n", -56, 56, 10, 5, 56);
766 ti_printf("|%#-8.5x|%#2.9X|\n", 0x1f, 0x1f);
767 ti_printf("|%#-8.5b|%#2.9B|\n", 0x1f, 0x1f);
768 ti_printf("|%-6Id|%5I8u|%#I64x|%#llx|\n", 256, 255, (ti_int64_t)0x8fffffffffff, (ti_int64_t)0x8fffffffffff);
769 ti_printf("|%f|\n", -3.1415926535897932384626433832795);
770 ti_printf("|%f|%f|%f|\n", 3.14, 0, -0);
771 ti_printf("|%0.9f|\n", 3.1415926535897932384626433832795);
772 ti_printf("|%16.9f|\n", 3.1415926535897932384626433832795);
773 ti_printf("|%016.9f|\n", 3.14159);
774 ti_printf("|%lf|\n", 1.0 / 6.0);
775 ti_printf("|%f|\n", 0.0003141596);
778 ti_int_t
ti_vsnprintf(ti_char_t
* s
, ti_size_t n
, ti_char_t
const* fmt
, ti_va_list_t args
)
780 #ifndef TI_ARCH_SPEC_HAVE_VSNPRINTF
781 if ((ti_int_t
)n
< 0 || !s
|| !fmt
) return 0;
784 ti_char_t
* pe
= s
+ n
;
786 // pe must be larger than pb
789 pe
= ((ti_char_t
*)-1);
790 n
= (ti_size_t
)(pe
- pb
);
794 ti_printf_entry_t e
= {0};
798 ti_char_t
const* ofmt
= fmt
;
801 en
= ti_printf_entry(fmt
, &e
);
806 // copy it if none type
807 case TI_PRINTF_TYPE_NONE
:
809 ti_int_t copy_n
= en
;
812 if (copy_n
> pe
- pb
) copy_n
= pe
- pb
;
813 ti_memcpy((ti_byte_t
*)pb
, (ti_byte_t
const*)ofmt
, copy_n
);
818 // get a character for %c
819 case TI_PRINTF_TYPE_CHAR
:
822 if (e
.extra
& TI_PRINTF_EXTRA_PERCENT
)
824 if (pb
< pe
) *pb
++ = '%';
829 // fill space at left side, e.g. " a"
830 if (!(e
.flags
& TI_PRINTF_FLAG_LEFT
))
832 while (--e
.width
> 0)
834 if (pb
< pe
) *pb
++ = ' ';
838 if (pb
< pe
) *pb
++ = (ti_char_t
)TI_VA_ARG(args
, ti_int_t
);
840 // fill space at right side, e.g. "a "
841 while (--e
.width
> 0)
843 if (pb
< pe
) *pb
++ = ' ';
848 // get field width for *
849 case TI_PRINTF_TYPE_WIDTH
:
850 e
.width
= TI_VA_ARG(args
, ti_int_t
);
852 // get precision for *
853 case TI_PRINTF_TYPE_PRECISION
:
854 e
.precision
= TI_VA_ARG(args
, ti_int_t
);
857 case TI_PRINTF_TYPE_STRING
:
859 pb
= ti_printf_string(pb
, pe
, e
, TI_VA_ARG(args
, ti_char_t
const*));
862 // get an integer for %d %u %x ...
863 case TI_PRINTF_TYPE_INT
:
866 if (e
.extra
& TI_PRINTF_EXTRA_SIGNED
)
870 case TI_PRINTF_QUAL_I
: num
= TI_VA_ARG(args
, ti_int_t
); break;
871 case TI_PRINTF_QUAL_I8
: num
= (ti_int8_t
)TI_VA_ARG(args
, ti_int_t
); break;
872 case TI_PRINTF_QUAL_I16
: num
= (ti_int16_t
)TI_VA_ARG(args
, ti_int_t
); break;
873 case TI_PRINTF_QUAL_I32
: num
= TI_VA_ARG(args
, ti_int32_t
); break;
874 case TI_PRINTF_QUAL_I64
: num
= TI_VA_ARG(args
, ti_int64_t
); break;
875 default: num
= TI_VA_ARG(args
, ti_int_t
); break;
882 case TI_PRINTF_QUAL_I
: num
= TI_VA_ARG(args
, ti_uint_t
); break;
883 case TI_PRINTF_QUAL_I8
: num
= (ti_uint8_t
)TI_VA_ARG(args
, ti_uint_t
); break;
884 case TI_PRINTF_QUAL_I16
: num
= (ti_uint16_t
)TI_VA_ARG(args
, ti_uint_t
); break;
885 case TI_PRINTF_QUAL_I32
: num
= TI_VA_ARG(args
, ti_uint32_t
); break;
886 case TI_PRINTF_QUAL_I64
: num
= TI_VA_ARG(args
, ti_uint64_t
); break;
887 default: num
= TI_VA_ARG(args
, ti_uint_t
); break;
890 pb
= ti_printf_integer(pb
, pe
, e
, num
);
893 #ifdef TI_CONFIG_FLOAT
894 case TI_PRINTF_TYPE_FLOAT
:
896 ti_float_t num
= TI_VA_ARG(args
, ti_float_t
);
897 pb
= ti_printf_float(pb
, pe
, e
, num
);
901 case TI_PRINTF_TYPE_INVALID
:
903 if (pb
< pe
) *pb
++ = '%';
911 // != 0, the string is null-truncated
914 if (pb
< pe
) *pb
= '\0';
918 // the trailing null byte doesn't count towards the total
921 return __vsnprintf(s
, n
, fmt
, args
);
924 ti_int_t
ti_vsprintf(ti_char_t
* s
, ti_char_t
const* fmt
, ti_va_list_t args
)
926 #ifndef TI_ARCH_SPEC_HAVE_VSPRINTF
927 return ti_vsnprintf(s
, TI_INT_MAX
, fmt
, args
);
929 return __vsprintf(s
, fmt
, args
);
932 ti_int_t
ti_snprintf(ti_char_t
* s
, ti_size_t n
, ti_char_t
const* fmt
, ...)
937 TI_VA_START(args
, fmt
);
938 i
= ti_vsnprintf(s
, n
, fmt
, args
);
943 ti_int_t
ti_sprintf(ti_char_t
* s
, ti_char_t
const* fmt
, ...)
948 TI_VA_START(args
, fmt
);
949 i
= ti_vsnprintf(s
, TI_INT_MAX
, fmt
, args
);