Skip to content

Commit

Permalink
printk: Add APIs to print into strings instead of default output
Browse files Browse the repository at this point in the history
These correspond to the libc snprintf and vsnprintf APIs.

Change-Id: If3944972ed95934a4967756593bb2932c3359b72
Signed-off-by: Johan Hedberg <[email protected]>
  • Loading branch information
Johan Hedberg authored and Anas Nashif committed Dec 5, 2016
1 parent 3ab6046 commit c899cd0
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
23 changes: 23 additions & 0 deletions include/misc/printk.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#define _PRINTK_H_

#include <toolchain.h>
#include <stddef.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -50,12 +52,33 @@ extern "C" {
*/
#ifdef CONFIG_PRINTK
extern __printf_like(1, 2) int printk(const char *fmt, ...);
extern __printf_like(3, 4) int snprintk(char *str, size_t size,
const char *fmt, ...);
extern int vsnprintk(char *str, size_t size, const char *fmt, va_list ap);
#else
static inline __printf_like(1, 2) int printk(const char *fmt, ...)
{
ARG_UNUSED(fmt);
return 0;
}

static inline __printf_like(3, 4) int snprintk(char *str, size_t size,
const char *fmt, ...)
{
ARG_UNUSED(str);
ARG_UNUSED(size);
ARG_UNUSED(fmt);
return 0;
}

static inline int vsnprintk(char *str, size_t size, const char *fmt,
va_list ap)
{
ARG_UNUSED(str);
ARG_UNUSED(size);
ARG_UNUSED(fmt);
return 0;
}
#endif

#ifdef __cplusplus
Expand Down
50 changes: 50 additions & 0 deletions misc/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,53 @@ static void _printk_dec_ulong(out_func_t out, void *ctx,
out((int)(remainder + 48), ctx);
}

struct str_context {
char *str;
int max;
int count;
};

static int str_out(int c, struct str_context *ctx)
{
if (!ctx->str || ctx->count >= ctx->max) {
ctx->count++;
return c;
}

if (ctx->count == ctx->max - 1) {
ctx->str[ctx->count++] = '\0';
} else {
ctx->str[ctx->count++] = c;
}

return c;
}

int snprintk(char *str, size_t size, const char *fmt, ...)
{
struct str_context ctx = { str, size, 0 };
va_list ap;

va_start(ap, fmt);
_vprintk((out_func_t)str_out, &ctx, fmt, ap);
va_end(ap);

if (ctx.count < ctx.max) {
str[ctx.count] = '\0';
}

return ctx.count;
}

int vsnprintk(char *str, size_t size, const char *fmt, va_list ap)
{
struct str_context ctx = { str, size, 0 };

_vprintk((out_func_t)str_out, &ctx, fmt, ap);

if (ctx.count < ctx.max) {
str[ctx.count] = '\0';
}

return ctx.count;
}
28 changes: 28 additions & 0 deletions tests/kernel/test_common/src/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ static int ram_console_out(int character)

void printk_test(void)
{
int count;

_old_char_out = _char_out;
_char_out = ram_console_out;

Expand All @@ -82,4 +84,30 @@ void printk_test(void)

ram_console[pos] = '\0';
assert_true((strcmp(ram_console, expected) == 0), "printk failed");

memset(ram_console, 0, sizeof(ram_console));
count = 0;

count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%zu %hhu %hu %u %lu %llu\n",
stv, uc, usi, ui, ul, ull);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"0x%x %p\n", hex, ptr);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"0x%x 0x%02x 0x%04x 0x%08x\n", 1, 1, 1, 1);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%d %02d %04d %08d\n", 42, 42, 42, 42);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%d %02d %04d %08d\n", -42, -42, -42, -42);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%u %2u %4u %8u\n", 42, 42, 42, 42);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%u %02u %04u %08u\n", 42, 42, 42, 42);

ram_console[count] = '\0';
assert_true((strcmp(ram_console, expected) == 0), "snprintk failed");
}

0 comments on commit c899cd0

Please sign in to comment.