diag-trace 5.0.1
µOS++ Tracing Infrastructure
Loading...
Searching...
No Matches
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 for any
6 * 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 be
9 * 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_INLINES_CPP_API_INLINES_H_
34#define MICRO_OS_PLUS_DIAG_TRACE_INLINES_CPP_API_INLINES_H_
35
36// ----------------------------------------------------------------------------
37
38#if defined(__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#if defined(__GNUC__)
52#pragma GCC diagnostic push
53
54#if defined(__clang__)
55#pragma clang diagnostic ignored "-Wc++98-compat"
56#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
57#endif // defined(__clang__)
58#endif // defined(__GNUC__)
59
61{
62 namespace detail
63 {
64
65 // ------------------------------------------------------------------------
66 // Out-of-class definitions of the tracer<T> member function
67 // templates declared in trace.h. Each is parameterised on the policy
68 // class (`implementation`, or any user-defined policy class)
69 // and shares no state across policy classes, so tracer<implementation> and
70 // tracer<Testing> (or any further user-defined policy class)
71 // can coexist in the same binary.
72 // ------------------------------------------------------------------------
73
74 template <trace_policy T>
75 int
76 tracer<T>::printf (const char* format, ...) noexcept
77 {
78 std::va_list arguments;
79 va_start (arguments, format);
80
81 int ret = vprintf (format, arguments);
82
83 va_end (arguments);
84 return ret;
85 }
86
87 template <trace_policy T>
88 int
89 tracer<T>::vprintf (const char* format, std::va_list arguments) noexcept
90 {
91 // Caution: allocated on the stack!
93
94 // TODO: possibly rewrite it to no longer use newlib,
95 // (although the nano version is no longer very heavy).
96
97#if defined(__GNUC__)
98#pragma GCC diagnostic push
99
100#pragma GCC diagnostic ignored "-Wformat-nonliteral"
101#endif // defined(__GNUC__)
102
103 // Print to the local buffer
104 ssize_t ret = ::vsnprintf (buf, sizeof (buf), format, arguments);
105
106#if defined(__GNUC__)
107#pragma GCC diagnostic pop
108#endif // defined(__GNUC__)
109
110 if (ret > 0)
111 {
112 // Clamp to actual buffer size if output was truncated.
113 // Note: on truncation the return value becomes the byte count
114 // written to the channel, not the total length vsnprintf
115 // computed. Callers cannot use the return value to detect
116 // truncation.
117 ret = write (buf,
118 static_cast<size_t> (std::min (
119 ret, static_cast<ssize_t> (sizeof (buf) - 1))));
120 }
121
122#if defined(__GNUC__)
123#pragma GCC diagnostic push
124
125#if defined(__clang__)
126#elif defined(__GNUC__)
127#pragma GCC diagnostic ignored "-Wuseless-cast"
128#endif // defined(__clang__)
129#endif // defined(__GNUC__)
130
131 // Cast required on 64-bit.
132 return static_cast<int> (ret);
133
134#if defined(__GNUC__)
135#pragma GCC diagnostic pop
136#endif // defined(__GNUC__)
137 }
138
139 template <trace_policy T>
140 int
141 tracer<T>::puts (const char* s) noexcept
142 {
143 std::size_t len = std::strlen (s);
144 ssize_t ret = write (s, len);
145 // Only append the line terminator if the string was written in
146 // full; a partial write (including a zero-byte write, which is
147 // not itself an error) must not be followed by a bare newline.
148 if (ret >= 0 && static_cast<std::size_t> (ret) == len)
149 {
150 ssize_t ret2 = write ("\n", 1); // Add a line terminator
151 if (ret2 < 0)
152 {
153 ret = ret2; // Propagate the error.
154 }
155 else
156 {
157 ret += ret2; // Return total bytes written.
158 }
159 }
160 if (ret > 0)
161 {
162#if defined(__GNUC__)
163#pragma GCC diagnostic push
164
165#if defined(__clang__)
166#elif defined(__GNUC__)
167#pragma GCC diagnostic ignored "-Wuseless-cast"
168#endif // defined(__clang__)
169#endif // defined(__GNUC__)
170
171 // Cast required on 64-bit.
172 return static_cast<int> (ret);
173
174#if defined(__GNUC__)
175#pragma GCC diagnostic pop
176#endif // defined(__GNUC__)
177 }
178 else
179 {
180 return EOF;
181 }
182 }
183
184 template <trace_policy T>
185 int
186 tracer<T>::putchar (int c) noexcept
187 {
188 auto ch = static_cast<unsigned char> (c);
189 ssize_t ret = write (&ch, 1);
190 if (ret > 0)
191 {
192 return c;
193 }
194 else
195 {
196 return EOF;
197 }
198 }
199
200#if defined(__GNUC__)
201#pragma GCC diagnostic push
202
203#if defined(__clang__)
204#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
205#endif // defined(__clang__)
206#endif // defined(__GNUC__)
207
208 template <trace_policy T>
209 void
210 tracer<T>::dump_args (int argc, char* argv[], const char* name) noexcept
211 {
212 printf ("%s(argc=%d, argv=[", name, argc);
213 for (int i = 0; i < argc; ++i)
214 {
215 if (i != 0)
216 {
217 printf (", ");
218 }
219 printf ("\"%s\"", argv[i]);
220 }
221 printf ("])\n");
222 }
223
224#if defined(__GNUC__)
225#pragma GCC diagnostic pop
226#endif // defined(__GNUC__)
227 } // namespace detail
228
229 // --------------------------------------------------------------------------
230 // Non-template free functions bound to `tracer<implementation>`. These
231 // preserve the original call syntax (`micro_os_plus::trace::printf(...)`) so
232 // that existing call sites throughout the codebase do not need to change.
233 // --------------------------------------------------------------------------
234
235 inline void
240
241 inline ssize_t
242 write (const void* buf, std::size_t nbyte) noexcept
243 {
245 }
246
247 inline void
248 flush (void) noexcept
249 {
251 }
252
253 inline int
254 printf (const char* format, ...) noexcept
255 {
256 std::va_list arguments;
257 va_start (arguments, format);
258
259 int ret
261
262 va_end (arguments);
263 return ret;
264 }
265
266 inline int
267 vprintf (const char* format, std::va_list arguments) noexcept
268 {
269 return detail::tracer<detail::implementation>::vprintf (format, arguments);
270 }
271
272 inline int
273 puts (const char* s) noexcept
274 {
276 }
277
278 inline int
279 putchar (int c) noexcept
280 {
282 }
283
284 inline void
285 dump_args (int argc, char* argv[], const char* name) noexcept
286 {
288 }
289
290} // namespace micro_os_plus::trace
291
292#if defined(__GNUC__)
293#pragma GCC diagnostic pop
294#endif // defined(__GNUC__)
295
296// ----------------------------------------------------------------------------
297
298#else // !defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
299
300// ----------------------------------------------------------------------------
301
302#if defined(__GNUC__)
303#pragma GCC diagnostic push
304
305#if defined(__clang__)
306#pragma clang diagnostic ignored "-Wc++98-compat"
307#endif // defined(__clang__)
308#endif // defined(__GNUC__)
309
310namespace micro_os_plus::trace
311{
312 // ------------------------------------------------------------------------
313 // Empty definitions.
314
315 inline __attribute__ ((always_inline)) void
316 initialise (void) noexcept
317 {
318 }
319
320 inline __attribute__ ((always_inline)) ssize_t
321 write (const void* /* buf */, std::size_t nbyte) noexcept
322 {
323 return static_cast<ssize_t> (nbyte);
324 }
325
326 inline __attribute__ ((always_inline)) void
327 flush (void) noexcept
328 {
329 }
330
331 // --------------------------------------------------------------------------
332
333 inline __attribute__ ((always_inline, format (printf, 1, 2))) int
334 printf (const char* /* format */, ...) noexcept
335 {
336 return 0;
337 }
338
339 inline __attribute__ ((always_inline, format (printf, 1, 0))) int
340 vprintf (const char* /* format */, std::va_list /* arguments */) noexcept
341 {
342 return 0;
343 }
344
345 inline __attribute__ ((always_inline)) int
346 puts (const char* /* s */) noexcept
347 {
348 return 0;
349 }
350
351 inline __attribute__ ((always_inline)) int
352 putchar (int c) noexcept
353 {
354 return c;
355 }
356
357 inline __attribute__ ((always_inline)) void
358 dump_args (int /* argc */, char* /* argv */[],
359 const char* /* name */) noexcept
360 {
361 }
362
363} // namespace micro_os_plus::trace
364
365#if defined(__GNUC__)
366#pragma GCC diagnostic pop
367#endif // defined(__GNUC__)
368
369// ----------------------------------------------------------------------------
370
371#endif // defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
372
373// ----------------------------------------------------------------------------
374
375#endif // defined(__cplusplus)
376
377// ----------------------------------------------------------------------------
378
379#endif // MICRO_OS_PLUS_DIAG_TRACE_INLINES_CPP_API_INLINES_H_
380
381// ----------------------------------------------------------------------------
static void initialise(void) noexcept
Initialise the trace output channel.
Definition cpp-api.h:432
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 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
Write the given number of bytes to the trace output channel.
Definition cpp-api.h:453
static void flush(void) noexcept
Flush the trace output channel.
Definition cpp-api.h:477
static int putchar(int c) noexcept
Write the single character to the trace output channel.
#define MICRO_OS_PLUS_DIAG_TRACE_PRINTF_BUFFER_ARRAY_SIZE_INTEGER
The size, in bytes, of the stack buffer used to format trace messages.
Definition trace.h:55
void dump_args(int argc, char *argv[], const char *name="main") 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.
Definition cpp-api.h:286
Tracing support namespace.
Definition cpp-api.h:106