1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2017 Google, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <stdarg.h>
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#ifdef ANDROID
27bf215546Sopenharmony_ci#include <android/log.h>
28bf215546Sopenharmony_ci#else
29bf215546Sopenharmony_ci#include <stdio.h>
30bf215546Sopenharmony_ci#endif
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include <stdlib.h>
33bf215546Sopenharmony_ci#include <string.h>
34bf215546Sopenharmony_ci#include "util/detect_os.h"
35bf215546Sopenharmony_ci#include "util/log.h"
36bf215546Sopenharmony_ci#include "util/ralloc.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#ifdef ANDROID
39bf215546Sopenharmony_cistatic inline android_LogPriority
40bf215546Sopenharmony_cilevel_to_android(enum mesa_log_level l)
41bf215546Sopenharmony_ci{
42bf215546Sopenharmony_ci   switch (l) {
43bf215546Sopenharmony_ci   case MESA_LOG_ERROR: return ANDROID_LOG_ERROR;
44bf215546Sopenharmony_ci   case MESA_LOG_WARN: return ANDROID_LOG_WARN;
45bf215546Sopenharmony_ci   case MESA_LOG_INFO: return ANDROID_LOG_INFO;
46bf215546Sopenharmony_ci   case MESA_LOG_DEBUG: return ANDROID_LOG_DEBUG;
47bf215546Sopenharmony_ci   }
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   unreachable("bad mesa_log_level");
50bf215546Sopenharmony_ci}
51bf215546Sopenharmony_ci#endif
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci#ifndef ANDROID
54bf215546Sopenharmony_cistatic inline const char *
55bf215546Sopenharmony_cilevel_to_str(enum mesa_log_level l)
56bf215546Sopenharmony_ci{
57bf215546Sopenharmony_ci   switch (l) {
58bf215546Sopenharmony_ci   case MESA_LOG_ERROR: return "error";
59bf215546Sopenharmony_ci   case MESA_LOG_WARN: return "warning";
60bf215546Sopenharmony_ci   case MESA_LOG_INFO: return "info";
61bf215546Sopenharmony_ci   case MESA_LOG_DEBUG: return "debug";
62bf215546Sopenharmony_ci   }
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   unreachable("bad mesa_log_level");
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci#endif
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_civoid
69bf215546Sopenharmony_cimesa_log(enum mesa_log_level level, const char *tag, const char *format, ...)
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   va_list va;
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci   va_start(va, format);
74bf215546Sopenharmony_ci   mesa_log_v(level, tag, format, va);
75bf215546Sopenharmony_ci   va_end(va);
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_civoid
79bf215546Sopenharmony_cimesa_log_v(enum mesa_log_level level, const char *tag, const char *format,
80bf215546Sopenharmony_ci            va_list va)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci#ifdef ANDROID
83bf215546Sopenharmony_ci   __android_log_vprint(level_to_android(level), tag, format, va);
84bf215546Sopenharmony_ci#else
85bf215546Sopenharmony_ci#if !DETECT_OS_WINDOWS
86bf215546Sopenharmony_ci   flockfile(stderr);
87bf215546Sopenharmony_ci#endif
88bf215546Sopenharmony_ci   fprintf(stderr, "%s: %s: ", tag, level_to_str(level));
89bf215546Sopenharmony_ci   vfprintf(stderr, format, va);
90bf215546Sopenharmony_ci   if (format[strlen(format) - 1] != '\n')
91bf215546Sopenharmony_ci      fprintf(stderr, "\n");
92bf215546Sopenharmony_ci#if !DETECT_OS_WINDOWS
93bf215546Sopenharmony_ci   funlockfile(stderr);
94bf215546Sopenharmony_ci#endif
95bf215546Sopenharmony_ci#endif
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_cistruct log_stream *
99bf215546Sopenharmony_ci_mesa_log_stream_create(enum mesa_log_level level, char *tag)
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci   struct log_stream *stream = ralloc(NULL, struct log_stream);
102bf215546Sopenharmony_ci   stream->level = level;
103bf215546Sopenharmony_ci   stream->tag = tag;
104bf215546Sopenharmony_ci   stream->msg = ralloc_strdup(stream, "");
105bf215546Sopenharmony_ci   stream->pos = 0;
106bf215546Sopenharmony_ci   return stream;
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_civoid
110bf215546Sopenharmony_cimesa_log_stream_destroy(struct log_stream *stream)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   /* If you left trailing stuff in the log stream, flush it out as a line. */
113bf215546Sopenharmony_ci   if (stream->pos != 0)
114bf215546Sopenharmony_ci      mesa_log(stream->level, stream->tag, "%s", stream->msg);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   ralloc_free(stream);
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_cistatic void
120bf215546Sopenharmony_cimesa_log_stream_flush(struct log_stream *stream, size_t scan_offset)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   char *end;
123bf215546Sopenharmony_ci   char *next = stream->msg;
124bf215546Sopenharmony_ci   while ((end = strchr(stream->msg + scan_offset, '\n'))) {
125bf215546Sopenharmony_ci      *end = 0;
126bf215546Sopenharmony_ci      mesa_log(stream->level, stream->tag, "%s", next);
127bf215546Sopenharmony_ci      next = end + 1;
128bf215546Sopenharmony_ci      scan_offset = next - stream->msg;
129bf215546Sopenharmony_ci   }
130bf215546Sopenharmony_ci   if (next != stream->msg) {
131bf215546Sopenharmony_ci      /* Clear out the lines we printed and move any trailing chars to the start. */
132bf215546Sopenharmony_ci      size_t remaining = stream->msg + stream->pos - next;
133bf215546Sopenharmony_ci      memmove(stream->msg, next, remaining);
134bf215546Sopenharmony_ci      stream->pos = remaining;
135bf215546Sopenharmony_ci   }
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_civoid mesa_log_stream_printf(struct log_stream *stream, const char *format, ...)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci   size_t old_pos = stream->pos;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   va_list va;
143bf215546Sopenharmony_ci   va_start(va, format);
144bf215546Sopenharmony_ci   ralloc_vasprintf_rewrite_tail(&stream->msg, &stream->pos, format, va);
145bf215546Sopenharmony_ci   va_end(va);
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   mesa_log_stream_flush(stream, old_pos);
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_civoid
151bf215546Sopenharmony_ci_mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines)
152bf215546Sopenharmony_ci{
153bf215546Sopenharmony_ci   struct log_stream tmp = {
154bf215546Sopenharmony_ci      .level = level,
155bf215546Sopenharmony_ci      .tag = tag,
156bf215546Sopenharmony_ci      .msg = strdup(lines),
157bf215546Sopenharmony_ci      .pos = strlen(lines),
158bf215546Sopenharmony_ci   };
159bf215546Sopenharmony_ci   mesa_log_stream_flush(&tmp, 0);
160bf215546Sopenharmony_ci   free(tmp.msg);
161bf215546Sopenharmony_ci}
162