[RFC,v2,11/14] log: add a per line log helper
Commit Message
gcc builtin __builtin_strchr can be used as a static assertion to check
whether passed format strings contain a \n.
This can be useful to detect double \n in log messages.
Signed-off-by: David Marchand <david.marchand@redhat.com>
---
Changes since RFC v1:
- added a check in checkpatches.sh,
---
devtools/checkpatches.sh | 8 ++++++++
lib/log/rte_log.h | 21 +++++++++++++++++++++
2 files changed, 29 insertions(+)
Comments
On Fri, 8 Dec 2023 15:59:45 +0100
David Marchand <david.marchand@redhat.com> wrote:
> gcc builtin __builtin_strchr can be used as a static assertion to check
> whether passed format strings contain a \n.
> This can be useful to detect double \n in log messages.
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>
Good idea.
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Chengwen Feng <fengchengwen@huawei.com>
On 2023/12/8 22:59, David Marchand wrote:
> gcc builtin __builtin_strchr can be used as a static assertion to check
> whether passed format strings contain a \n.
> This can be useful to detect double \n in log messages.
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
> Changes since RFC v1:
> - added a check in checkpatches.sh,
>
> ---
> devtools/checkpatches.sh | 8 ++++++++
> lib/log/rte_log.h | 21 +++++++++++++++++++++
> 2 files changed, 29 insertions(+)
>
> diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
> index 10b79ca2bc..10d1bf490b 100755
> --- a/devtools/checkpatches.sh
> +++ b/devtools/checkpatches.sh
> @@ -53,6 +53,14 @@ print_usage () {
> check_forbidden_additions() { # <patch>
> res=0
>
> + # refrain from new calls to RTE_LOG
> + awk -v FOLDERS="lib" \
> + -v EXPRESSIONS="RTE_LOG\\\(" \
> + -v RET_ON_FAIL=1 \
> + -v MESSAGE='Prefer RTE_LOG_LINE' \
> + -f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
> + "$1" || res=1
> +
> # refrain from new additions of rte_panic() and rte_exit()
> # multiple folders and expressions are separated by spaces
> awk -v FOLDERS="lib drivers" \
> diff --git a/lib/log/rte_log.h b/lib/log/rte_log.h
> index 27fb6129a7..da7e672e81 100644
> --- a/lib/log/rte_log.h
> +++ b/lib/log/rte_log.h
> @@ -17,6 +17,7 @@
> extern "C" {
> #endif
>
> +#include <assert.h>
> #include <stdint.h>
> #include <stdio.h>
> #include <stdarg.h>
> @@ -358,6 +359,26 @@ int rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
> RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__) : \
> 0)
>
> +#ifdef RTE_TOOLCHAIN_GCC
> +#define RTE_LOG_CHECK_NO_NEWLINE(fmt) \
> + static_assert(!__builtin_strchr(fmt, '\n'), \
> + "This log format string contains a \\n")
> +#else
> +#define RTE_LOG_CHECK_NO_NEWLINE(...)
> +#endif
> +
> +#define RTE_LOG_LINE(l, t, ...) do { \
> + RTE_LOG_CHECK_NO_NEWLINE(RTE_FMT_HEAD(__VA_ARGS__,)); \
> + RTE_LOG(l, t, RTE_FMT(RTE_FMT_HEAD(__VA_ARGS__,) "\n", \
> + RTE_FMT_TAIL(__VA_ARGS__ ,))); \
> +} while (0)
> +
> +#define RTE_LOG_DP_LINE(l, t, ...) do { \
> + RTE_LOG_CHECK_NO_NEWLINE(RTE_FMT_HEAD(__VA_ARGS__,)); \
> + RTE_LOG_DP(l, t, RTE_FMT(RTE_FMT_HEAD(__VA_ARGS__,) "\n", \
> + RTE_FMT_TAIL(__VA_ARGS__ ,))); \
> +} while (0)
> +
> #define RTE_LOG_REGISTER_IMPL(type, name, level) \
> int type; \
> RTE_INIT(__##type) \
>
@@ -53,6 +53,14 @@ print_usage () {
check_forbidden_additions() { # <patch>
res=0
+ # refrain from new calls to RTE_LOG
+ awk -v FOLDERS="lib" \
+ -v EXPRESSIONS="RTE_LOG\\\(" \
+ -v RET_ON_FAIL=1 \
+ -v MESSAGE='Prefer RTE_LOG_LINE' \
+ -f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
+ "$1" || res=1
+
# refrain from new additions of rte_panic() and rte_exit()
# multiple folders and expressions are separated by spaces
awk -v FOLDERS="lib drivers" \
@@ -17,6 +17,7 @@
extern "C" {
#endif
+#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
@@ -358,6 +359,26 @@ int rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__) : \
0)
+#ifdef RTE_TOOLCHAIN_GCC
+#define RTE_LOG_CHECK_NO_NEWLINE(fmt) \
+ static_assert(!__builtin_strchr(fmt, '\n'), \
+ "This log format string contains a \\n")
+#else
+#define RTE_LOG_CHECK_NO_NEWLINE(...)
+#endif
+
+#define RTE_LOG_LINE(l, t, ...) do { \
+ RTE_LOG_CHECK_NO_NEWLINE(RTE_FMT_HEAD(__VA_ARGS__,)); \
+ RTE_LOG(l, t, RTE_FMT(RTE_FMT_HEAD(__VA_ARGS__,) "\n", \
+ RTE_FMT_TAIL(__VA_ARGS__ ,))); \
+} while (0)
+
+#define RTE_LOG_DP_LINE(l, t, ...) do { \
+ RTE_LOG_CHECK_NO_NEWLINE(RTE_FMT_HEAD(__VA_ARGS__,)); \
+ RTE_LOG_DP(l, t, RTE_FMT(RTE_FMT_HEAD(__VA_ARGS__,) "\n", \
+ RTE_FMT_TAIL(__VA_ARGS__ ,))); \
+} while (0)
+
#define RTE_LOG_REGISTER_IMPL(type, name, level) \
int type; \
RTE_INIT(__##type) \