µOS++ IIIe Reference  v6.3.15
“Perfekt ist nicht gut genug”
The third edition of µOS++, a POSIX inspired open source system, written in C++.
trace.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the µOS++ distribution.
3  * (https://github.com/micro-os-plus)
4  * Copyright (c) 2015 Liviu Ionescu.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #if defined(TRACE)
29 
30 #include <cmsis-plus/os-app-config.h>
31 #include <cmsis-plus/diag/trace.h>
32 
33 #include <cstdarg>
34 #include <cstdio>
35 #include <cstring>
36 
37 #ifndef OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE
38 #define OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE (200)
39 #endif
40 
41 // ----------------------------------------------------------------------------
42 
43 namespace os
44 {
45  namespace trace
46  {
47  // ----------------------------------------------------------------------
48 
49  void __attribute__((weak))
50  initialize (void)
51  {
52  ;
53  }
54 
59  ssize_t __attribute__((weak))
60  write (const void* buf __attribute__((unused)), std::size_t nbyte)
61  {
62  return static_cast<ssize_t> (nbyte);
63  }
64 
65  void __attribute__((weak))
66  flush (void)
67  {
68  ;
69  }
70 
71  // ----------------------------------------------------------------------
72 
73  int __attribute__((weak))
74  printf (const char* format, ...)
75  {
76  std::va_list args;
77  va_start(args, format);
78 
79  int ret = vprintf (format, args);
80 
81  va_end(args);
82  return ret;
83  }
84 
85  int __attribute__((weak))
86  vprintf (const char* format, std::va_list args)
87  {
88  // Caution: allocated on the stack!
90 
91  // TODO: possibly rewrite it to no longer use newlib,
92  // (although the nano version is no longer very heavy).
93 
94  // Print to the local buffer
95 #pragma GCC diagnostic push
96 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
97  int ret = ::vsnprintf (buf, sizeof(buf), format, args);
98 #pragma GCC diagnostic pop
99  if (ret > 0)
100  {
101  // Transfer the buffer to the device.
102  ret = static_cast<int> (write (buf, static_cast<size_t> (ret)));
103  }
104  return ret;
105  }
106 
107  int __attribute__((weak))
108  puts (const char* s)
109  {
110  int ret = static_cast<int> (write (s, strlen (s)));
111  if (ret >= 0)
112  {
113  ret = static_cast<int> (write ("\n", 1)); // Add a line terminator
114  }
115  if (ret > 0)
116  {
117  return ret;
118  }
119  else
120  {
121  return EOF;
122  }
123  }
124 
125  int __attribute__((weak))
126  putchar (int c)
127  {
128  int ret = static_cast<int> (write (reinterpret_cast<const char*> (&c), 1));
129  if (ret > 0)
130  {
131  return c;
132  }
133  else
134  {
135  return EOF;
136  }
137  }
138 
139  void __attribute__((weak))
140  dump_args (int argc, char* argv[])
141  {
142  printf ("main(argc=%d, argv=[", argc);
143  for (int i = 0; i < argc; ++i)
144  {
145  if (i != 0)
146  {
147  printf (", ");
148  }
149  printf ("\"%s\"", argv[i]);
150  }
151  printf ("]);\n");
152  }
153 
154  } /* namespace trace */
155 } /* namespace os */
156 
157 // ----------------------------------------------------------------------------
158 
159 using namespace os;
160 
161 // These cannot be aliased, since they might be defined
162 // in a different translation units (and usually they are).
163 
164 void __attribute__((weak))
166 {
168 }
169 
170 ssize_t __attribute__((weak))
171 trace_write (const void* buf, std::size_t nbyte)
172 {
173  return trace::write (buf, nbyte);
174 }
175 
176 void __attribute__((weak))
178 {
179  return trace::flush ();
180 }
181 
182 // ----------------------------------------------------------------------------
183 
184 #if defined(__ARM_EABI__)
185 
186 // For embedded platforms, optimise with aliases.
187 //
188 // Aliases can only refer symbols defined in the same translation unit
189 // and C++ de-mangling must be done manually.
190 
191 int __attribute__((weak, alias ("_ZN2os5trace6printfEPKcz")))
192 trace_printf (const char* format, ...);
193 
194 int __attribute__((weak, alias ("_ZN2os5trace7vprintfEPKcSt9__va_list")))
195 trace_vprintf (const char* format, ...);
196 
197 int __attribute__((weak, alias("_ZN2os5trace4putsEPKc")))
198 trace_puts (const char *s);
199 
200 int __attribute__((weak, alias("_ZN2os5trace7putcharEi")))
201 trace_putchar (int c);
202 
203 void __attribute__((weak, alias("_ZN2os5trace9dump_argsEiPPc")))
204 trace_dump_args (int argc, char* argv[]);
205 
206 #else
207 
208 // For non-embedded platforms, to remain compatible with OS X which does
209 // not support aliases, redefine the C functions to call the C++ versions.
210 
211 int
212 trace_printf (const char* format, ...)
213 {
214  std::va_list args;
215  va_start(args, format);
216 
217  int ret = trace::vprintf (format, args);
218 
219  va_end(args);
220  return ret;
221 }
222 
223 int
224 trace_vprintf (const char* format, va_list args)
225 {
226  return trace::vprintf (format, args);
227 }
228 
229 int
230 trace_puts (const char* s)
231 {
232  return trace::puts (s);
233 }
234 
235 int
236 trace_putchar (int c)
237 {
238  return trace::putchar (c);
239 }
240 
241 void
242 trace_dump_args (int argc, char* argv[])
243 {
244  trace::dump_args (argc, argv);
245 }
246 
247 #endif
248 
249 // ----------------------------------------------------------------------------
250 
251 #endif // defined(TRACE)
int puts(const char *s)
Write the string and a line terminator to the trace device.
Definition: trace.cpp:108
ssize_t trace_write(const void *buf, std::size_t nbyte)
Definition: trace.cpp:171
void initialize(void)
Definition: trace.cpp:50
void trace_flush(void)
Definition: trace.cpp:177
int trace_puts(const char *s)
int trace_putchar(int c)
Standard std namespace.
System namespace.
int putchar(int c)
Write the single character to the trace device.
Definition: trace.cpp:126
int trace_vprintf(const char *format,...)
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
void trace_initialize(void)
Definition: trace.cpp:165
#define OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE
Definition: trace.cpp:38
void dump_args(int argc, char *argv[])
Write the argv[] array to the trace device.
Definition: trace.cpp:140
void flush(void)
Flush the output.
Definition: trace.cpp:66
ssize_t write(const void *buf, std::size_t nbyte)
Write the given number of bytes to the trace output channel.
Definition: trace.cpp:60
int vprintf(const char *format, std::va_list args)
Write a formatted variable arguments list to the trace device.
Definition: trace.cpp:86
int trace_printf(const char *format,...)
void trace_dump_args(int argc, char *argv[])