From 84a493b88d88268dd0387d7d281a1c40fcc98680 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 May 2006 15:41:01 +0000 Subject: [PATCH] Allow vcprintf() to be called by external code such as the curses library. Also trim another eight bytes from vsprintf.o. :) --- src/core/vsprintf.c | 76 +++++++++++++++++++++--------------------- src/include/vsprintf.h | 29 ++++++++++++++++ 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/core/vsprintf.c b/src/core/vsprintf.c index a8f7af61..a80c62ef 100644 --- a/src/core/vsprintf.c +++ b/src/core/vsprintf.c @@ -40,32 +40,6 @@ static uint8_t type_sizes[] = { [SIZE_T_LEN] = sizeof ( size_t ), }; -/** - * A printf context - * - * Contexts are used in order to be able to share code between - * vprintf() and vsnprintf(), without requiring the allocation of a - * buffer for vprintf(). - */ -struct printf_context { - /** - * Character handler - * - * @v ctx Context - * @v c Character - * - * This method is called for each character written to the - * formatted string. It must increment @len. - */ - void ( * handler ) ( struct printf_context *ctx, unsigned int c ); - /** Length of formatted string */ - size_t len; - /** Buffer for formatted string (used by printf_sputc()) */ - char *buf; - /** Buffer length (used by printf_sputc()) */ - size_t max_len; -}; - /** * Use lower-case for hexadecimal digits * @@ -163,6 +137,20 @@ static char * format_decimal ( char *end, signed long num, int width ) { return ptr; } +/** + * Print character via a printf context + * + * @v ctx Context + * @v c Character + * + * Call's the printf_context::handler() method and increments + * printf_context::len. + */ +static inline void cputchar ( struct printf_context *ctx, unsigned int c ) { + ctx->handler ( ctx, c ); + ++ctx->len; +} + /** * Write a formatted string to a printf context * @@ -185,7 +173,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { for ( ; *fmt ; fmt++ ) { /* Pass through ordinary characters */ if ( *fmt != '%' ) { - ctx->handler ( ctx, *fmt ); + cputchar ( ctx, *fmt ); continue; } fmt++; @@ -228,7 +216,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { ptr = tmp_buf + sizeof ( tmp_buf ) - 1; *ptr = '\0'; if ( *fmt == 'c' ) { - ctx->handler ( ctx, va_arg ( args, unsigned int ) ); + cputchar ( ctx, va_arg ( args, unsigned int ) ); } else if ( *fmt == 's' ) { ptr = va_arg ( args, char * ); } else if ( *fmt == 'p' ) { @@ -263,13 +251,22 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { } /* Write out conversion result */ for ( ; *ptr ; ptr++ ) { - ctx->handler ( ctx, *ptr ); + cputchar ( ctx, *ptr ); } } return ctx->len; } +/** Context used by vsnprintf() and friends */ +struct sputc_context { + struct printf_context ctx; + /** Buffer for formatted string (used by printf_sputc()) */ + char *buf; + /** Buffer length (used by printf_sputc()) */ + size_t max_len; +}; + /** * Write character to buffer * @@ -277,8 +274,11 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { * @v c Character */ static void printf_sputc ( struct printf_context *ctx, unsigned int c ) { - if ( ++ctx->len < ctx->max_len ) - ctx->buf[ctx->len-1] = c; + struct sputc_context * sctx = + container_of ( ctx, struct sputc_context, ctx ); + + if ( ctx->len <= sctx->max_len ) + sctx->buf[ctx->len] = c; } /** @@ -295,15 +295,15 @@ static void printf_sputc ( struct printf_context *ctx, unsigned int c ) { * been available. */ int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) { - struct printf_context ctx; + struct sputc_context sctx; size_t len; size_t end; /* Hand off to vcprintf */ - ctx.handler = printf_sputc; - ctx.buf = buf; - ctx.max_len = size; - len = vcprintf ( &ctx, fmt, args ); + sctx.ctx.handler = printf_sputc; + sctx.buf = buf; + sctx.max_len = size; + len = vcprintf ( &sctx.ctx, fmt, args ); /* Add trailing NUL */ if ( size ) { @@ -341,8 +341,8 @@ int snprintf ( char *buf, size_t size, const char *fmt, ... ) { * @v ctx Context * @v c Character */ -static void printf_putchar ( struct printf_context *ctx, unsigned int c ) { - ++ctx->len; +static void printf_putchar ( struct printf_context *ctx __unused, + unsigned int c ) { putchar ( c ); } diff --git a/src/include/vsprintf.h b/src/include/vsprintf.h index 99d6683e..d5018d7c 100644 --- a/src/include/vsprintf.h +++ b/src/include/vsprintf.h @@ -35,6 +35,35 @@ #define PRINTF_NO_LENGTH ( ( size_t ) -1 ) +/** + * A printf context + * + * Contexts are used in order to be able to share code between + * vprintf() and vsnprintf(), without requiring the allocation of a + * buffer for vprintf(). + */ +struct printf_context { + /** + * Character handler + * + * @v ctx Context + * @v c Character + * + * This method is called for each character written to the + * formatted string. + */ + void ( * handler ) ( struct printf_context *ctx, unsigned int c ); + /** Length of formatted string + * + * When handler() is called, @len will be set to the number of + * characters written so far (i.e. zero for the first call to + * handler()). + */ + size_t len; +}; + +extern size_t vcprintf ( struct printf_context *ctx, const char *fmt, + va_list args ); extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ); extern int vprintf ( const char *fmt, va_list args );