Mesa (main): util/log: Add a streaming printf interface.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 18 18:42:26 UTC 2021


Module: Mesa
Branch: main
Commit: 250c127c200f6ccd5463c0af6bc5cd9eb607de94
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=250c127c200f6ccd5463c0af6bc5cd9eb607de94

Author: Emma Anholt <emma at anholt.net>
Date:   Wed Jun 16 10:20:35 2021 -0700

util/log: Add a streaming printf interface.

Often disassemblers and things in our drivers want to be able to
incrementally printf together a line, but that gets in the way of
Android's logging that wants to see a whole line all at once.  Make a
little wrapper to do the ralloc_asprintf_rewrite_tail() and flushing lines
as they appear.

Reviewed-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9262>

---

 src/util/log.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/log.h | 16 ++++++++++++++
 2 files changed, 84 insertions(+)

diff --git a/src/util/log.c b/src/util/log.c
index 7dfe11cb704..e0f2a900c27 100644
--- a/src/util/log.c
+++ b/src/util/log.c
@@ -29,8 +29,11 @@
 #include <stdio.h>
 #endif
 
+#include <stdlib.h>
+#include <string.h>
 #include "util/detect_os.h"
 #include "util/log.h"
+#include "util/ralloc.h"
 
 #ifdef ANDROID
 static inline android_LogPriority
@@ -90,3 +93,68 @@ mesa_log_v(enum mesa_log_level level, const char *tag, const char *format,
 #endif
 #endif
 }
+
+struct log_stream *
+_mesa_log_stream_create(enum mesa_log_level level, char *tag)
+{
+   struct log_stream *stream = ralloc(NULL, struct log_stream);
+   stream->level = level;
+   stream->tag = tag;
+   stream->msg = ralloc_strdup(stream, "");
+   stream->pos = 0;
+   return stream;
+}
+
+void
+mesa_log_stream_destroy(struct log_stream *stream)
+{
+   /* If you left trailing stuff in the log stream, flush it out as a line. */
+   if (stream->pos != 0)
+      mesa_log(stream->level, stream->tag, "%s", stream->msg);
+
+   ralloc_free(stream);
+}
+
+static void
+mesa_log_stream_flush(struct log_stream *stream, size_t scan_offset)
+{
+   char *end;
+   char *next = stream->msg;
+   while ((end = strchr(stream->msg + scan_offset, '\n'))) {
+      *end = 0;
+      mesa_log(stream->level, stream->tag, "%s", next);
+      next = end + 1;
+      scan_offset = next - stream->msg;
+   }
+   if (next != stream->msg) {
+      /* Clear out the lines we printed and move any trailing chars to the start. */
+      size_t remaining = stream->msg + stream->pos - next;
+      memmove(stream->msg, next, remaining);
+      stream->pos = remaining;
+   }
+}
+
+void mesa_log_stream_printf(struct log_stream *stream, const char *format, ...)
+{
+   size_t old_pos = stream->pos;
+
+   va_list va;
+   va_start(va, format);
+   ralloc_vasprintf_rewrite_tail(&stream->msg, &stream->pos, format, va);
+   va_end(va);
+
+   mesa_log_stream_flush(stream, old_pos);
+}
+
+void
+_mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines)
+{
+   struct log_stream tmp = {
+      .level = level,
+      .tag = tag,
+      .msg = strdup(lines),
+      .pos = strlen(lines),
+   };
+   mesa_log_stream_flush(&tmp, 0);
+   free(tmp.msg);
+}
diff --git a/src/util/log.h b/src/util/log.h
index b1190f4068b..ccd00d627c0 100644
--- a/src/util/log.h
+++ b/src/util/log.h
@@ -68,6 +68,22 @@ mesa_log_v(enum mesa_log_level, const char *tag, const char *format,
 #define mesa_logd_v(fmt, va) __mesa_log_use_args((fmt), (va))
 #endif
 
+struct log_stream {
+   char *msg;
+   const char *tag;
+   size_t pos;
+   enum mesa_log_level level;
+};
+
+struct log_stream *_mesa_log_stream_create(enum mesa_log_level level, char *tag);
+#define mesa_log_streame() _mesa_log_stream_create(MESA_LOG_ERROR, (MESA_LOG_TAG))
+#define mesa_log_streamw() _mesa_log_stream_create(MESA_LOG_WARN, (MESA_LOG_TAG))
+#define mesa_log_streami() _mesa_log_stream_create(MESA_LOG_INFO, (MESA_LOG_TAG))
+void mesa_log_stream_destroy(struct log_stream *stream);
+void mesa_log_stream_printf(struct log_stream *stream, const char *format, ...);
+
+void _mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines);
+#define mesa_log_multiline(level, lines) _mesa_log_multiline(level, (MESA_LOG_TAG), lines)
 
 #ifndef DEBUG
 /* Suppres -Wunused */



More information about the mesa-commit mailing list