diag-trace 5.0.0
µOS++ Tracing Infrastructure
Loading...
Searching...
No Matches
trace-cpp-api-inlines.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2015-2026 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12// ----------------------------------------------------------------------------
13
24
25// ----------------------------------------------------------------------------
26
27#if !defined(MICRO_OS_PLUS_DIAG_TRACE_H_)
28#error "Do not include this file directly; use <micro-os-plus/diag/trace.h>."
29#endif // MICRO_OS_PLUS_DIAG_TRACE_H_
30
31// ----------------------------------------------------------------------------
32
33#ifndef MICRO_OS_PLUS_DIAG_TRACE_CPP_API_INLINES_H_
34#define MICRO_OS_PLUS_DIAG_TRACE_CPP_API_INLINES_H_
35
36// ----------------------------------------------------------------------------
37
38#ifdef __cplusplus
39
40// ----------------------------------------------------------------------------
41
42#if defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
43
44// ----------------------------------------------------------------------------
45
46#include <cstring>
47#include <algorithm>
48
49// ----------------------------------------------------------------------------
50
51#ifndef MICRO_OS_PLUS_DIAG_TRACE_PRINTF_BUFFER_ARRAY_SIZE_INTEGER
52#define MICRO_OS_PLUS_DIAG_TRACE_PRINTF_BUFFER_ARRAY_SIZE_INTEGER (200)
53#endif
54
55// ----------------------------------------------------------------------------
56
57#pragma GCC diagnostic push
58#if defined(__clang__)
59#pragma clang diagnostic ignored "-Wc++98-compat"
60#pragma clang diagnostic ignored "-Wpre-c++17-compat"
61#endif
62
64{
65 namespace detail
66 {
67
68 // ------------------------------------------------------------------------
69 // Out-of-class definitions of the tracer<T> member function
70 // templates declared in trace.h. Each is parameterised on the policy
71 // class (`implementation`, or any user-defined policy class)
72 // and shares no state across policy classes, so tracer<implementation> and
73 // tracer<Testing> (or any further user-defined policy class)
74 // can coexist in the same binary.
75 // ------------------------------------------------------------------------
76
77 template <trace_policy T>
78 int
79 tracer<T>::printf (const char* format, ...) noexcept
80 {
81 std::va_list arguments;
82 va_start (arguments, format);
83
84#pragma GCC diagnostic push
85#if defined(__clang__)
86#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
87#endif
88 int ret = vprintf (format, arguments);
89#pragma GCC diagnostic pop
90
91 va_end (arguments);
92 return ret;
93 }
94
95 template <trace_policy T>
96 int
97 tracer<T>::vprintf (const char* format, std::va_list arguments) noexcept
98 {
99 // Caution: allocated on the stack!
101
102 // TODO: possibly rewrite it to no longer use newlib,
103 // (although the nano version is no longer very heavy).
104
105 // Print to the local buffer
106#pragma GCC diagnostic push
107#pragma GCC diagnostic ignored "-Wformat-nonliteral"
108#if defined(__clang__)
109#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
110#endif
111 ssize_t ret = ::vsnprintf (buf, sizeof (buf), format, arguments);
112#pragma GCC diagnostic pop
113 if (ret > 0)
114 {
115 // Clamp to actual buffer size if output was truncated.
116 // Note: on truncation the return value becomes the byte count
117 // written to the channel, not the total length vsnprintf
118 // computed. Callers cannot use the return value to detect
119 // truncation.
120 ret = write (buf,
121 static_cast<size_t> (std::min (
122 ret, static_cast<ssize_t> (sizeof (buf) - 1))));
123 }
124#pragma GCC diagnostic push
125#if defined(__GNUC__) && !defined(__clang__)
126#pragma GCC diagnostic ignored "-Wuseless-cast"
127#endif
128 // Cast required on 64-bit.
129 return static_cast<int> (ret);
130#pragma GCC diagnostic pop
131 }
132
133 template <trace_policy T>
134 int
135 tracer<T>::puts (const char* s) noexcept
136 {
137#pragma GCC diagnostic push
138#if defined(__clang__)
139#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
140#endif
141 ssize_t ret = write (s, std::strlen (s));
142#pragma GCC diagnostic pop
143 if (ret >= 0)
144 {
145 ssize_t ret2 = write ("\n", 1); // Add a line terminator
146 if (ret2 < 0)
147 {
148 ret = ret2; // Propagate the error.
149 }
150 else
151 {
152 ret += ret2; // Return total bytes written.
153 }
154 }
155 if (ret > 0)
156 {
157#pragma GCC diagnostic push
158#if defined(__GNUC__) && !defined(__clang__)
159#pragma GCC diagnostic ignored "-Wuseless-cast"
160#endif
161 // Cast required on 64-bit.
162 return static_cast<int> (ret);
163#pragma GCC diagnostic pop
164 }
165 else
166 {
167 return EOF;
168 }
169 }
170
171 template <trace_policy T>
172 int
173 tracer<T>::putchar (int c) noexcept
174 {
175 char ch = static_cast<char> (c);
176 ssize_t ret = write (&ch, 1);
177 if (ret > 0)
178 {
179 return c;
180 }
181 else
182 {
183 return EOF;
184 }
185 }
186
187#pragma GCC diagnostic push
188#if defined(__clang__)
189#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
190#endif
191 template <trace_policy T>
192 void
193 tracer<T>::dump_args (int argc, char* argv[], const char* name) noexcept
194 {
195 printf ("%s(argc=%d, argv=[", name, argc);
196 for (int i = 0; i < argc; ++i)
197 {
198 if (i != 0)
199 {
200 printf (", ");
201 }
202 printf ("\"%s\"", argv[i]);
203 }
204 printf ("])\n");
205 }
206#pragma GCC diagnostic pop
207
208 } // namespace detail
209
210 // --------------------------------------------------------------------------
211 // Non-template free functions bound to `tracer<implementation>`. These
212 // preserve the original call syntax (`micro_os_plus::trace::printf(...)`) so
213 // that existing call sites throughout the codebase do not need to change.
214 // --------------------------------------------------------------------------
215
216 inline void
221
222 inline ssize_t
223 write (const void* buf, std::size_t nbyte) noexcept
224 {
226 }
227
228 inline void
229 flush (void) noexcept
230 {
232 }
233
234 inline int
235 printf (const char* format, ...) noexcept
236 {
237 std::va_list arguments;
238 va_start (arguments, format);
239#pragma GCC diagnostic push
240#if defined(__clang__)
241#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
242#endif
243 int ret
245#pragma GCC diagnostic pop
246 va_end (arguments);
247 return ret;
248 }
249
250 inline int
251 vprintf (const char* format, std::va_list arguments) noexcept
252 {
253#pragma GCC diagnostic push
254#if defined(__clang__)
255#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
256#endif
257 return detail::tracer<detail::implementation>::vprintf (format, arguments);
258#pragma GCC diagnostic pop
259 }
260
261 inline int
262 puts (const char* s) noexcept
263 {
264#pragma GCC diagnostic push
265#if defined(__clang__)
266#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
267#endif
269#pragma GCC diagnostic pop
270 }
271
272 inline int
273 putchar (int c) noexcept
274 {
276 }
277
278 inline void
279 dump_args (int argc, char* argv[], const char* name) noexcept
280 {
282 }
283
284} // namespace micro_os_plus::trace
285
286#pragma GCC diagnostic pop
287
288// ----------------------------------------------------------------------------
289
290#else // !defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
291
292// ----------------------------------------------------------------------------
293
294#pragma GCC diagnostic push
295#if defined(__clang__)
296#pragma clang diagnostic ignored "-Wc++98-compat"
297#pragma clang diagnostic ignored "-Wpre-c++17-compat"
298#endif
299
300namespace micro_os_plus::trace
301{
302 // ------------------------------------------------------------------------
303 // Empty definitions.
304
305 inline __attribute__ ((always_inline)) void
306 initialise (void) noexcept
307 {
308 }
309
310 inline __attribute__ ((always_inline)) ssize_t
311 write (const void* /* buf */, std::size_t nbyte) noexcept
312 {
313 return static_cast<ssize_t> (nbyte);
314 }
315
316 inline __attribute__ ((always_inline)) void
317 flush (void) noexcept
318 {
319 }
320
321 // --------------------------------------------------------------------------
322
323 inline __attribute__ ((always_inline)) int
324 printf (const char* /* format */, ...) noexcept
325 {
326 return 0;
327 }
328
329 inline __attribute__ ((always_inline)) int
330 vprintf (const char* /* format */, std::va_list /* arguments */) noexcept
331 {
332 return 0;
333 }
334
335 inline __attribute__ ((always_inline)) int
336 puts (const char* /* s */) noexcept
337 {
338 return 0;
339 }
340
341 inline __attribute__ ((always_inline)) int
342 putchar (int c) noexcept
343 {
344 return c;
345 }
346
347 inline __attribute__ ((always_inline)) void
348 dump_args (int /* argc */, char* /* argv */[],
349 const char* /* name */) noexcept
350 {
351 }
352
353} // namespace micro_os_plus::trace
354
355#pragma GCC diagnostic pop
356
357// ----------------------------------------------------------------------------
358
359#endif // defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
360
361// ----------------------------------------------------------------------------
362
363#endif // __cplusplus
364
365// ----------------------------------------------------------------------------
366
367#endif // MICRO_OS_PLUS_DIAG_TRACE_CPP_API_INLINES_H_
368
369// ----------------------------------------------------------------------------
static int puts(const char *s="") noexcept
Write the string and a line terminator to the trace output channel.
static int vprintf(const char *format, std::va_list arguments) noexcept
Write a formatted variable arguments list to the trace output channel.
static void dump_args(int argc, char *argv[], const char *name="main") noexcept
Send the argv[] array to the trace output channel.
static void flush(void) noexcept(noexcept(T::flush()))
Flush the trace output channel.
static int printf(const char *format,...) noexcept
Write a formatted string to the trace output channel.
static ssize_t write(const void *buf, std::size_t nbyte) noexcept(noexcept(T::write(buf, nbyte)))
Write the given number of bytes to the trace output channel.
static void initialise(void) noexcept(noexcept(T::initialise()))
Initialise the trace output channel.
static int putchar(int c) noexcept
Write the single character to the trace output channel.
void dump_args(int argc, char *argv[], const char *name) noexcept
Send the argv[] array to the trace output channel.
void initialise(void) noexcept
Initialise the trace output channel.
ssize_t write(const void *buf, std::size_t nbyte) noexcept
Write the given number of bytes to the trace output channel.
void flush(void) noexcept
Flush the trace output channel.
int printf(const char *format,...) noexcept
Write a formatted string to the trace output channel.
int puts(const char *s) noexcept
Write the string and a line terminator to the trace output channel.
int putchar(int c) noexcept
Write the single character to the trace output channel.
int vprintf(const char *format, std::va_list arguments) noexcept
Write a formatted variable arguments list to the trace output channel.
Implementation details namespace.
Tracing support namespace.
#define MICRO_OS_PLUS_DIAG_TRACE_PRINTF_BUFFER_ARRAY_SIZE_INTEGER