david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Allow vcprintf() to be called by external code such as the curses library.

Also trim another eight bytes from vsprintf.o.  :)
This commit is contained in:
Michael Brown 2006-05-22 15:41:01 +00:00
parent f778500739
commit 84a493b88d
2 changed files with 67 additions and 38 deletions

View File

@ -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 );
}

View File

@ -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 );