mirror of https://github.com/ipxe/ipxe.git
Allow vcprintf() to be called by external code such as the curses library.
Also trim another eight bytes from vsprintf.o. :)pull/1/head
parent
f778500739
commit
84a493b88d
|
@ -40,32 +40,6 @@ static uint8_t type_sizes[] = {
|
||||||
[SIZE_T_LEN] = sizeof ( size_t ),
|
[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
|
* Use lower-case for hexadecimal digits
|
||||||
*
|
*
|
||||||
|
@ -163,6 +137,20 @@ static char * format_decimal ( char *end, signed long num, int width ) {
|
||||||
return ptr;
|
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
|
* 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++ ) {
|
for ( ; *fmt ; fmt++ ) {
|
||||||
/* Pass through ordinary characters */
|
/* Pass through ordinary characters */
|
||||||
if ( *fmt != '%' ) {
|
if ( *fmt != '%' ) {
|
||||||
ctx->handler ( ctx, *fmt );
|
cputchar ( ctx, *fmt );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fmt++;
|
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 = tmp_buf + sizeof ( tmp_buf ) - 1;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
if ( *fmt == 'c' ) {
|
if ( *fmt == 'c' ) {
|
||||||
ctx->handler ( ctx, va_arg ( args, unsigned int ) );
|
cputchar ( ctx, va_arg ( args, unsigned int ) );
|
||||||
} else if ( *fmt == 's' ) {
|
} else if ( *fmt == 's' ) {
|
||||||
ptr = va_arg ( args, char * );
|
ptr = va_arg ( args, char * );
|
||||||
} else if ( *fmt == 'p' ) {
|
} 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 */
|
/* Write out conversion result */
|
||||||
for ( ; *ptr ; ptr++ ) {
|
for ( ; *ptr ; ptr++ ) {
|
||||||
ctx->handler ( ctx, *ptr );
|
cputchar ( ctx, *ptr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx->len;
|
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
|
* Write character to buffer
|
||||||
*
|
*
|
||||||
|
@ -277,8 +274,11 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
||||||
* @v c Character
|
* @v c Character
|
||||||
*/
|
*/
|
||||||
static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
|
static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
|
||||||
if ( ++ctx->len < ctx->max_len )
|
struct sputc_context * sctx =
|
||||||
ctx->buf[ctx->len-1] = c;
|
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.
|
* been available.
|
||||||
*/
|
*/
|
||||||
int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) {
|
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 len;
|
||||||
size_t end;
|
size_t end;
|
||||||
|
|
||||||
/* Hand off to vcprintf */
|
/* Hand off to vcprintf */
|
||||||
ctx.handler = printf_sputc;
|
sctx.ctx.handler = printf_sputc;
|
||||||
ctx.buf = buf;
|
sctx.buf = buf;
|
||||||
ctx.max_len = size;
|
sctx.max_len = size;
|
||||||
len = vcprintf ( &ctx, fmt, args );
|
len = vcprintf ( &sctx.ctx, fmt, args );
|
||||||
|
|
||||||
/* Add trailing NUL */
|
/* Add trailing NUL */
|
||||||
if ( size ) {
|
if ( size ) {
|
||||||
|
@ -341,8 +341,8 @@ int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
|
||||||
* @v ctx Context
|
* @v ctx Context
|
||||||
* @v c Character
|
* @v c Character
|
||||||
*/
|
*/
|
||||||
static void printf_putchar ( struct printf_context *ctx, unsigned int c ) {
|
static void printf_putchar ( struct printf_context *ctx __unused,
|
||||||
++ctx->len;
|
unsigned int c ) {
|
||||||
putchar ( c );
|
putchar ( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,35 @@
|
||||||
|
|
||||||
#define PRINTF_NO_LENGTH ( ( size_t ) -1 )
|
#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 vsnprintf ( char *buf, size_t size, const char *fmt, va_list args );
|
||||||
extern int vprintf ( const char *fmt, va_list args );
|
extern int vprintf ( const char *fmt, va_list args );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue