From ec9ed8deb79a9fd508a11b122453bb39d3b587a9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 23 Jul 2017 15:28:13 +0200 Subject: added snprintf and a test for it --- src/libc/stdio.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++ src/libc/stdio.h | 2 + tests/libc/Makefile | 11 ++++- tests/libc/test_sprintf.c | 19 +++++++++ 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 tests/libc/test_sprintf.c diff --git a/src/libc/stdio.c b/src/libc/stdio.c index 9fdf510..e0b87a8 100644 --- a/src/libc/stdio.c +++ b/src/libc/stdio.c @@ -150,6 +150,107 @@ int vprintf( const char *format, va_list args ) return n; } +int snprintf( char *buf, size_t n, const char *format, ... ) +{ + va_list args; + + va_start( args, format ); + int res = vsnprintf( buf, n, format, args ); + va_end( args ); + + return res; +} + +#define EMIT( x ) if( len < n ) { *buf = ( x ); buf++; *buf = '\0'; len++; } + +#define APPEND_STRING( s, s2 ) \ + strlcat( s, s2, n - len ); \ + s += strlen( s2 ); \ + len += strlen( s2 ); \ + if( len < n ) { \ + *s = '\0'; \ + } + +int vsnprintf( char *buf, size_t n, const char *format, va_list args ) +{ + const char *s = format; + int len = 0; + + *buf = '\0'; + while( *s != '\0' && len < n ) { + switch( *s ) { + case '\n': + EMIT( '\n' ); + break; + + case '%': + s++; + if( *s == '\0' ) { + strlcpy( buf, "", n - len ); + strlcat( buf, "\n", n - len - 1 ); + return -1; + } + + switch( *s ) { + case '%': + EMIT( '%' ); + break; + + case 'X': { + char buf2[19]; + itoa( va_arg( args, int ), (char *)buf2, 16 ); + APPEND_STRING( buf, buf2 ); + } + break; + + case 'd': { + char buf2[19]; + itoa( va_arg( args, int ), (char *)buf2, 10 ); + APPEND_STRING( buf, buf2 ); + } + break; + + case 'c': { + char buf2[2]; + buf2[0] = (char)va_arg( args, int ); + buf2[1] = '\0'; + APPEND_STRING( buf, buf2 ); + } + break; + + case 's': { + const char *s = va_arg( args, const char * ); + APPEND_STRING( buf, s ); + } + break; + + default: { + APPEND_STRING( buf, "