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@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9262>
This commit is contained in:
Emma Anholt 2021-06-16 10:20:35 -07:00 committed by Marge Bot
parent 3863008c22
commit 250c127c20
2 changed files with 84 additions and 0 deletions

View file

@ -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);
}

View file

@ -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 */