summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/stdio.h61
-rw-r--r--builtin/stdlib.c68
-rw-r--r--common/printf.c56
-rw-r--r--include/printf.h46
-rw-r--r--test/printf.c10
-rw-r--r--zephyr/shim/src/console.c6
6 files changed, 145 insertions, 102 deletions
diff --git a/builtin/stdio.h b/builtin/stdio.h
new file mode 100644
index 0000000000..b8b6949c45
--- /dev/null
+++ b/builtin/stdio.h
@@ -0,0 +1,61 @@
+/* Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_STDIO_H__
+#define __CROS_EC_STDIO_H__
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#include "common.h"
+
+/**
+ * Print formatted outut to a string.
+ *
+ * Guarantees null-termination if size!=0.
+ *
+ * @param str Destination string
+ * @param size Size of destination in bytes
+ * @param format Format string
+ * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated.
+ */
+__attribute__((__format__(__printf__, 3, 4)))
+__warn_unused_result __stdlib_compat int
+crec_snprintf(char *str, size_t size, const char *format, ...);
+
+/**
+ * Print formatted output to a string.
+ *
+ * Guarantees null-termination if size!=0.
+ *
+ * @param str Destination string
+ * @param size Size of destination in bytes
+ * @param format Format string
+ * @param args Parameters
+ * @return The string length written to str, or a negative value on error.
+ * The negative values can be -EC_ERROR_INVAL or -EC_ERROR_OVERFLOW.
+ */
+__warn_unused_result __stdlib_compat int
+crec_vsnprintf(char *str, size_t size, const char *format, va_list args);
+
+/*
+ * Create weak aliases to the crec_* printf functions. This lets us call the
+ * crec_* printf functions in tests that link the C standard library.
+ */
+
+/**
+ * Alias to crec_snprintf.
+ */
+__attribute__((__format__(__printf__, 3, 4)))
+__warn_unused_result __stdlib_compat int
+snprintf(char *str, size_t size, const char *format, ...);
+
+/**
+ * Alias to crec_vsnprintf.
+ */
+__warn_unused_result __stdlib_compat int
+vsnprintf(char *str, size_t size, const char *format, va_list args);
+
+#endif /* __CROS_EC_STDIO_H__ */
diff --git a/builtin/stdlib.c b/builtin/stdlib.c
index 1d07b64869..b3229f4f63 100644
--- a/builtin/stdlib.c
+++ b/builtin/stdlib.c
@@ -7,7 +7,11 @@
#include "common.h"
#include "console.h"
+#include "printf.h"
#include "util.h"
+
+#include <stdio.h>
+
/*
* The following macros are defined in stdlib.h in the C standard library, which
* conflict with the definitions in this file.
@@ -19,6 +23,70 @@
#undef isprint
#undef tolower
+/* Context for snprintf() */
+struct snprintf_context {
+ char *str;
+ int size;
+};
+
+/**
+ * Add a character to the string context.
+ *
+ * @param context Context receiving character
+ * @param c Character to add
+ * @return 0 if character added, 1 if character dropped because no space.
+ */
+static int snprintf_addchar(void *context, int c)
+{
+ struct snprintf_context *ctx = (struct snprintf_context *)context;
+
+ if (!ctx->size)
+ return 1;
+
+ *(ctx->str++) = c;
+ ctx->size--;
+ return 0;
+}
+
+int crec_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ struct snprintf_context ctx;
+ int rv;
+
+ if (!str || !format || size <= 0)
+ return -EC_ERROR_INVAL;
+
+ ctx.str = str;
+ ctx.size = size - 1; /* Reserve space for terminating '\0' */
+
+ rv = vfnprintf(snprintf_addchar, &ctx, format, args);
+
+ /* Terminate string */
+ *ctx.str = '\0';
+
+ return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv;
+}
+#ifndef CONFIG_ZEPHYR
+int vsnprintf(char *str, size_t size, const char *format, va_list args)
+ __attribute__((weak, alias("crec_vsnprintf")));
+#endif /* CONFIG_ZEPHYR */
+
+int crec_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list args;
+ int rv;
+
+ va_start(args, format);
+ rv = crec_vsnprintf(str, size, format, args);
+ va_end(args);
+
+ return rv;
+}
+#ifndef CONFIG_ZEPHYR
+int snprintf(char *str, size_t size, const char *format, ...)
+ __attribute__((weak, alias("crec_snprintf")));
+#endif /* CONFIG_ZEPHYR */
+
/*
* TODO(b/237712836): Zephyr's libc should provide strcasecmp. For now we'll
* use the EC implementation.
diff --git a/common/printf.c b/common/printf.c
index 9a3e593cba..91e4e722b0 100644
--- a/common/printf.c
+++ b/common/printf.c
@@ -488,59 +488,3 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context,
/* If we're still here, we consumed all output */
return EC_SUCCESS;
}
-
-/* Context for snprintf() */
-struct snprintf_context {
- char *str;
- int size;
-};
-
-/**
- * Add a character to the string context.
- *
- * @param context Context receiving character
- * @param c Character to add
- * @return 0 if character added, 1 if character dropped because no space.
- */
-static int snprintf_addchar(void *context, int c)
-{
- struct snprintf_context *ctx = (struct snprintf_context *)context;
-
- if (!ctx->size)
- return 1;
-
- *(ctx->str++) = c;
- ctx->size--;
- return 0;
-}
-
-int crec_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list args;
- int rv;
-
- va_start(args, format);
- rv = crec_vsnprintf(str, size, format, args);
- va_end(args);
-
- return rv;
-}
-
-int crec_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
- struct snprintf_context ctx;
- int rv;
-
- if (!str || !format || size <= 0)
- return -EC_ERROR_INVAL;
-
- ctx.str = str;
- ctx.size = size - 1; /* Reserve space for terminating '\0' */
-
- rv = vfnprintf(snprintf_addchar, &ctx, format, args);
-
- /* Terminate string */
- *ctx.str = '\0';
-
- return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv;
-}
diff --git a/include/printf.h b/include/printf.h
index b63208f84d..f6330ff9c3 100644
--- a/include/printf.h
+++ b/include/printf.h
@@ -11,15 +11,9 @@
#include <stdarg.h> /* For va_list */
#include <stdbool.h>
#include <stddef.h> /* For size_t */
-#include "common.h"
#include "console.h"
-
-/* The declaration of snprintf is changed to crec_snprintf for Zephyr,
- * so include stdio.h from Zephyr.
- */
-#ifdef CONFIG_ZEPHYR
#include <stdio.h>
-#endif
+#include "common.h"
/**
* Buffer size in bytes large enough to hold the largest possible timestamp.
@@ -66,8 +60,6 @@
* - 'p' - pointer
*/
-#ifndef HIDE_EC_STDLIB
-
/**
* Print formatted output to a function, like vfprintf()
*
@@ -84,42 +76,6 @@
__stdlib_compat int vfnprintf(int (*addchar)(void *context, int c),
void *context, const char *format, va_list args);
-#ifndef CONFIG_ZEPHYR
-#define snprintf crec_snprintf
-#define vsnprintf crec_vsnprintf
-#endif
-
-/**
- * Print formatted outut to a string.
- *
- * Guarantees null-termination if size!=0.
- *
- * @param str Destination string
- * @param size Size of destination in bytes
- * @param format Format string
- * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated.
- */
-__attribute__((__format__(__printf__, 3, 4)))
-__warn_unused_result __stdlib_compat int
-crec_snprintf(char *str, size_t size, const char *format, ...);
-
-/**
- * Print formatted output to a string.
- *
- * Guarantees null-termination if size!=0.
- *
- * @param str Destination string
- * @param size Size of destination in bytes
- * @param format Format string
- * @param args Parameters
- * @return The string length written to str, or a negative value on error.
- * The negative values can be -EC_ERROR_INVAL or -EC_ERROR_OVERFLOW.
- */
-__warn_unused_result __stdlib_compat int
-crec_vsnprintf(char *str, size_t size, const char *format, va_list args);
-
-#endif /* !HIDE_EC_STDLIB */
-
#ifdef TEST_BUILD
/**
* Converts @val to a string written in @buf. The value is converted from
diff --git a/test/printf.c b/test/printf.c
index 3928185918..69c0d76281 100644
--- a/test/printf.c
+++ b/test/printf.c
@@ -12,6 +12,13 @@
#include "test_util.h"
#include "util.h"
+/*
+ * This file is intended to test the EC printf implementation. We need to
+ * include the builtin header file directly so that we can call the EC
+ * version (crec_vsnprintf) when linking with the standard library on the host.
+ */
+#include "builtin/stdio.h"
+
#define INIT_VALUE 0x5E
#define NO_BYTES_TOUCHED NULL
@@ -33,7 +40,8 @@ int run(int expect_ret, const char *expect, bool output_null, size_t size_limit,
TEST_ASSERT(expect_size <= size_limit);
memset(output, INIT_VALUE, sizeof(output));
- rv = vsnprintf(output_null ? NULL : output, size_limit, format, args);
+ rv = crec_vsnprintf(output_null ? NULL : output, size_limit, format,
+ args);
ccprintf("received='%.*s' | ret =%d\n", 30, output, rv);
TEST_ASSERT_ARRAY_EQ(output, expect, expect_size);
diff --git a/zephyr/shim/src/console.c b/zephyr/shim/src/console.c
index 8dafaf9803..e9b0c72790 100644
--- a/zephyr/shim/src/console.c
+++ b/zephyr/shim/src/console.c
@@ -17,6 +17,12 @@
#include <zephyr/zephyr.h>
#include <zephyr/logging/log.h>
+/*
+ * TODO(b/238433667): Include EC printf functions
+ * (crec_vsnprintf/crec_snprintf) until we switch to the standard
+ * vsnprintf/snprintf.
+ */
+#include "builtin/stdio.h"
#include "console.h"
#include "printf.h"
#include "task.h"