1 /*
2 * Copyright (c) 2014-2017, Siemens AG. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <assert.h>
31
32 #include <embb/base/c/log.h>
33
34 #include <embb/base/c/internal/config.h>
35 #include <embb/base/c/internal/unused.h>
36
embb_log_write_file(void * context,char const * message)37 void embb_log_write_file(
38 void * context,
39 char const * message) {
40 assert(context != NULL);
41 FILE * ff = (FILE*)context;
42 fprintf(ff, "%s", message);
43 fflush(ff);
44 }
45
46 static embb_log_level_t embb_log_global_log_level =
47 EMBB_LOG_LEVEL_NONE;
48
49 static void * embb_log_global_log_context = NULL;
50
51 static embb_log_function_t embb_log_global_log_function = embb_log_write_file;
52
embb_log_set_log_level(embb_log_level_t log_level)53 void embb_log_set_log_level(
54 embb_log_level_t log_level) {
55 embb_log_global_log_level = log_level;
56 }
57
embb_log_set_log_function(void * context,embb_log_function_t func)58 void embb_log_set_log_function(
59 void * context,
60 embb_log_function_t func) {
61 embb_log_global_log_context = context;
62 embb_log_global_log_function = func;
63 }
64
embb_log_write_internal(char const * channel,embb_log_level_t log_level,char const * message,va_list argp)65 void embb_log_write_internal(
66 char const * channel,
67 embb_log_level_t log_level,
68 char const * message,
69 va_list argp) {
70 if (log_level <= embb_log_global_log_level) {
71 char * log_level_str = " ";
72 char const * channel_str = channel;
73 void * log_context = embb_log_global_log_context;
74 if (NULL == channel_str) {
75 channel_str = " global ";
76 }
77 if (NULL == log_context) {
78 log_context = (void*)stdout;
79 }
80 switch (log_level) {
81 case EMBB_LOG_LEVEL_ERROR:
82 log_level_str = "ERROR";
83 break;
84 case EMBB_LOG_LEVEL_WARNING:
85 log_level_str = "WARN ";
86 break;
87 case EMBB_LOG_LEVEL_INFO:
88 log_level_str = "INFO ";
89 break;
90 case EMBB_LOG_LEVEL_TRACE:
91 log_level_str = "TRACE";
92 break;
93
94 case EMBB_LOG_LEVEL_NONE:
95 default:
96 break;
97 }
98 #if defined(EMBB_PLATFORM_COMPILER_MSVC)
99 char msg_buffer[400];
100 char buffer[500];
101 vsprintf_s(msg_buffer, sizeof(msg_buffer), message, argp);
102 sprintf_s(buffer, sizeof(buffer), "[%s] - [%s] %s",
103 channel_str, log_level_str, msg_buffer);
104 embb_log_global_log_function(log_context, buffer);
105 #elif defined(EMBB_PLATFORM_COMPILER_GNUC)
106 char msg_buffer[400];
107 char buffer[500];
108 vsnprintf(msg_buffer, sizeof(msg_buffer), message, argp);
109 snprintf(buffer, sizeof(buffer), "[%s] - [%s] %s",
110 channel_str, log_level_str, msg_buffer);
111 embb_log_global_log_function(log_context, buffer);
112 #else
113 embb_log_global_log_function(log_context, "[");
114 embb_log_global_log_function(log_context, channel_str);
115 embb_log_global_log_function(log_context, "] - [");
116 embb_log_global_log_function(log_context, log_level_str);
117 embb_log_global_log_function(log_context, "] ");
118 /* no secure formatting possible, sorry */
119 embb_log_global_log_function(log_context, message);
120 #endif
121 }
122 }
123
embb_log_write(char const * channel,embb_log_level_t log_level,char const * message,...)124 void embb_log_write(
125 char const * channel,
126 embb_log_level_t log_level,
127 char const * message,
128 ...) {
129 va_list argp;
130 va_start(argp, message);
131 embb_log_write_internal(channel, log_level, message, argp);
132 va_end(argp);
133 }
134
135 #ifdef EMBB_DEBUG
embb_log_trace(char const * channel,char const * message,...)136 void embb_log_trace(
137 char const * channel,
138 char const * message,
139 ...) {
140 va_list argp;
141 va_start(argp, message);
142 embb_log_write_internal(channel, EMBB_LOG_LEVEL_TRACE, message, argp);
143 va_end(argp);
144 }
145
embb_log_info(char const * channel,char const * message,...)146 void embb_log_info(
147 char const * channel,
148 char const * message,
149 ...) {
150 va_list argp;
151 va_start(argp, message);
152 embb_log_write_internal(channel, EMBB_LOG_LEVEL_INFO, message, argp);
153 va_end(argp);
154 }
155 #else
156 #undef embb_log_trace
embb_log_trace(char const * channel,char const * message,...)157 void embb_log_trace(
158 char const * channel,
159 char const * message,
160 ...) {
161 EMBB_UNUSED(channel);
162 EMBB_UNUSED(message);
163 }
164
165 #undef embb_log_info
embb_log_info(char const * channel,char const * message,...)166 void embb_log_info(
167 char const * channel,
168 char const * message,
169 ...) {
170 EMBB_UNUSED(channel);
171 EMBB_UNUSED(message);
172 }
173 #endif
174
embb_log_warning(char const * channel,char const * message,...)175 void embb_log_warning(
176 char const * channel,
177 char const * message,
178 ...) {
179 va_list argp;
180 va_start(argp, message);
181 embb_log_write_internal(channel, EMBB_LOG_LEVEL_WARNING, message, argp);
182 va_end(argp);
183 }
184
embb_log_error(char const * channel,char const * message,...)185 void embb_log_error(
186 char const * channel,
187 char const * message,
188 ...) {
189 va_list argp;
190 va_start(argp, message);
191 embb_log_write_internal(channel, EMBB_LOG_LEVEL_ERROR, message, argp);
192 va_end(argp);
193 }
194