xref: /aosp_15_r20/external/cpuinfo/deps/clog/src/clog.c (revision 2b54f0db79fd8303838913b20ff3780cddaa909f)
1 #include <stdarg.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #ifdef _WIN32
6 	#include <windows.h>
7 #else
8 	#include <unistd.h>
9 #endif
10 #ifdef __ANDROID__
11 	#include <android/log.h>
12 #endif
13 #ifdef __hexagon__
14 	#include <qurt_printf.h>
15 #endif
16 
17 #ifndef CLOG_LOG_TO_STDIO
18 	#ifdef __ANDROID__
19 		#define CLOG_LOG_TO_STDIO 0
20 	#else
21 		#define CLOG_LOG_TO_STDIO 1
22 	#endif
23 #endif
24 
25 #include <clog.h>
26 
27 
28 /* Messages up to this size are formatted entirely on-stack, and don't allocate heap memory */
29 #define CLOG_STACK_BUFFER_SIZE 1024
30 
31 #define CLOG_FATAL_PREFIX "Fatal error: "
32 #define CLOG_FATAL_PREFIX_LENGTH 13
33 #define CLOG_FATAL_PREFIX_FORMAT "Fatal error in %s: "
34 #define CLOG_ERROR_PREFIX "Error: "
35 #define CLOG_ERROR_PREFIX_LENGTH 7
36 #define CLOG_ERROR_PREFIX_FORMAT "Error in %s: "
37 #define CLOG_WARNING_PREFIX "Warning: "
38 #define CLOG_WARNING_PREFIX_LENGTH 9
39 #define CLOG_WARNING_PREFIX_FORMAT "Warning in %s: "
40 #define CLOG_INFO_PREFIX "Note: "
41 #define CLOG_INFO_PREFIX_LENGTH 6
42 #define CLOG_INFO_PREFIX_FORMAT "Note (%s): "
43 #define CLOG_DEBUG_PREFIX "Debug: "
44 #define CLOG_DEBUG_PREFIX_LENGTH 7
45 #define CLOG_DEBUG_PREFIX_FORMAT "Debug (%s): "
46 #define CLOG_SUFFIX_LENGTH 1
47 
clog_vlog_fatal(const char * module,const char * format,va_list args)48 void clog_vlog_fatal(const char* module, const char* format, va_list args) {
49 	#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
50 		__android_log_vprint(ANDROID_LOG_FATAL, module, format, args);
51 	#else
52 		char stack_buffer[CLOG_STACK_BUFFER_SIZE];
53 		char* heap_buffer = NULL;
54 		char* out_buffer = &stack_buffer[0];
55 
56 		/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
57 		va_list args_copy;
58 		va_copy(args_copy, args);
59 
60 		int prefix_chars = CLOG_FATAL_PREFIX_LENGTH;
61 		if (module == NULL) {
62 			memcpy(stack_buffer, CLOG_FATAL_PREFIX, CLOG_FATAL_PREFIX_LENGTH);
63 		} else {
64 			prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_FATAL_PREFIX_FORMAT, module);
65 			if (prefix_chars < 0) {
66 				/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
67 				prefix_chars = 0;
68 			}
69 		}
70 
71 		int format_chars;
72 		if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
73 			/*
74 			 * Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
75 			 * Do not even try to format the string into on-stack buffer.
76 			 */
77 			format_chars = vsnprintf(NULL, 0, format, args);
78 		} else {
79 			format_chars =
80 				vsnprintf(
81 					&stack_buffer[prefix_chars],
82 					CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
83 					format,
84 					args);
85 		}
86 		if (format_chars < 0) {
87 			/* Format error in the message: silently ignore this particular message. */
88 			goto cleanup;
89 		}
90 		if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
91 			/* Allocate a buffer on heap, and vsnprintf to this buffer */
92 			heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
93 			if (heap_buffer == NULL) {
94 				goto cleanup;
95 			}
96 
97 			if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
98 				/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
99 				snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_FATAL_PREFIX_FORMAT, module);
100 			} else {
101 				/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
102 				memcpy(heap_buffer, stack_buffer, prefix_chars);
103 			}
104 			vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
105 			out_buffer = heap_buffer;
106 		}
107 		out_buffer[prefix_chars + format_chars] = '\n';
108 		#if defined(_WIN32)
109 			DWORD bytes_written;
110 			WriteFile(
111 				GetStdHandle(STD_ERROR_HANDLE),
112 				out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
113 				&bytes_written, NULL);
114 		#elif defined(__hexagon__)
115 			qurt_printf("%s", out_buffer);
116 		#else
117 			write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
118 		#endif
119 
120 cleanup:
121 		free(heap_buffer);
122 		va_end(args_copy);
123 	#endif
124 }
125 
clog_vlog_error(const char * module,const char * format,va_list args)126 void clog_vlog_error(const char* module, const char* format, va_list args) {
127 	#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
128 		__android_log_vprint(ANDROID_LOG_ERROR, module, format, args);
129 	#else
130 		char stack_buffer[CLOG_STACK_BUFFER_SIZE];
131 		char* heap_buffer = NULL;
132 		char* out_buffer = &stack_buffer[0];
133 
134 		/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
135 		va_list args_copy;
136 		va_copy(args_copy, args);
137 
138 		int prefix_chars = CLOG_ERROR_PREFIX_LENGTH;
139 		if (module == NULL) {
140 			memcpy(stack_buffer, CLOG_ERROR_PREFIX, CLOG_ERROR_PREFIX_LENGTH);
141 		} else {
142 			prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_ERROR_PREFIX_FORMAT, module);
143 			if (prefix_chars < 0) {
144 				/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
145 				prefix_chars = 0;
146 			}
147 		}
148 
149 		int format_chars;
150 		if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
151 			/*
152 			 * Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
153 			 * Do not even try to format the string into on-stack buffer.
154 			 */
155 			format_chars = vsnprintf(NULL, 0, format, args);
156 		} else {
157 			format_chars =
158 				vsnprintf(
159 					&stack_buffer[prefix_chars],
160 					CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
161 					format,
162 					args);
163 		}
164 		if (format_chars < 0) {
165 			/* Format error in the message: silently ignore this particular message. */
166 			goto cleanup;
167 		}
168 		if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
169 			/* Allocate a buffer on heap, and vsnprintf to this buffer */
170 			heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
171 			if (heap_buffer == NULL) {
172 				goto cleanup;
173 			}
174 
175 			if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
176 				/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
177 				snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_ERROR_PREFIX_FORMAT, module);
178 			} else {
179 				/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
180 				memcpy(heap_buffer, stack_buffer, prefix_chars);
181 			}
182 			vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
183 			out_buffer = heap_buffer;
184 		}
185 		out_buffer[prefix_chars + format_chars] = '\n';
186 		#if defined(_WIN32)
187 			DWORD bytes_written;
188 			WriteFile(
189 				GetStdHandle(STD_ERROR_HANDLE),
190 				out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
191 				&bytes_written, NULL);
192 		#elif defined(__hexagon__)
193 			qurt_printf("%s", out_buffer);
194 		#else
195 			write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
196 		#endif
197 
198 cleanup:
199 		free(heap_buffer);
200 		va_end(args_copy);
201 	#endif
202 }
203 
clog_vlog_warning(const char * module,const char * format,va_list args)204 void clog_vlog_warning(const char* module, const char* format, va_list args) {
205 	#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
206 		__android_log_vprint(ANDROID_LOG_WARN, module, format, args);
207 	#else
208 		char stack_buffer[CLOG_STACK_BUFFER_SIZE];
209 		char* heap_buffer = NULL;
210 		char* out_buffer = &stack_buffer[0];
211 
212 		/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
213 		va_list args_copy;
214 		va_copy(args_copy, args);
215 
216 		int prefix_chars = CLOG_WARNING_PREFIX_LENGTH;
217 		if (module == NULL) {
218 			memcpy(stack_buffer, CLOG_WARNING_PREFIX, CLOG_WARNING_PREFIX_LENGTH);
219 		} else {
220 			prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_WARNING_PREFIX_FORMAT, module);
221 			if (prefix_chars < 0) {
222 				/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
223 				prefix_chars = 0;
224 			}
225 		}
226 
227 		int format_chars;
228 		if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
229 			/*
230 			 * Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
231 			 * Do not even try to format the string into on-stack buffer.
232 			 */
233 			format_chars = vsnprintf(NULL, 0, format, args);
234 		} else {
235 			format_chars =
236 				vsnprintf(
237 					&stack_buffer[prefix_chars],
238 					CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
239 					format,
240 					args);
241 		}
242 		if (format_chars < 0) {
243 			/* Format error in the message: silently ignore this particular message. */
244 			goto cleanup;
245 		}
246 		if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
247 			/* Allocate a buffer on heap, and vsnprintf to this buffer */
248 			heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
249 			if (heap_buffer == NULL) {
250 				goto cleanup;
251 			}
252 
253 			if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
254 				/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
255 				snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_WARNING_PREFIX_FORMAT, module);
256 			} else {
257 				/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
258 				memcpy(heap_buffer, stack_buffer, prefix_chars);
259 			}
260 			vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
261 			out_buffer = heap_buffer;
262 		}
263 		out_buffer[prefix_chars + format_chars] = '\n';
264 		#if defined(_WIN32)
265 			DWORD bytes_written;
266 			WriteFile(
267 				GetStdHandle(STD_ERROR_HANDLE),
268 				out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
269 				&bytes_written, NULL);
270 		#elif defined(__hexagon__)
271 			qurt_printf("%s", out_buffer);
272 		#else
273 			write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
274 		#endif
275 
276 cleanup:
277 		free(heap_buffer);
278 		va_end(args_copy);
279 	#endif
280 }
281 
clog_vlog_info(const char * module,const char * format,va_list args)282 void clog_vlog_info(const char* module, const char* format, va_list args) {
283 	#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
284 		__android_log_vprint(ANDROID_LOG_INFO, module, format, args);
285 	#else
286 		char stack_buffer[CLOG_STACK_BUFFER_SIZE];
287 		char* heap_buffer = NULL;
288 		char* out_buffer = &stack_buffer[0];
289 
290 		/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
291 		va_list args_copy;
292 		va_copy(args_copy, args);
293 
294 		int prefix_chars = CLOG_INFO_PREFIX_LENGTH;
295 		if (module == NULL) {
296 			memcpy(stack_buffer, CLOG_INFO_PREFIX, CLOG_INFO_PREFIX_LENGTH);
297 		} else {
298 			prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_INFO_PREFIX_FORMAT, module);
299 			if (prefix_chars < 0) {
300 				/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
301 				prefix_chars = 0;
302 			}
303 		}
304 
305 		int format_chars;
306 		if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
307 			/*
308 			 * Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
309 			 * Do not even try to format the string into on-stack buffer.
310 			 */
311 			format_chars = vsnprintf(NULL, 0, format, args);
312 		} else {
313 			format_chars =
314 				vsnprintf(
315 					&stack_buffer[prefix_chars],
316 					CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
317 					format,
318 					args);
319 		}
320 		if (format_chars < 0) {
321 			/* Format error in the message: silently ignore this particular message. */
322 			goto cleanup;
323 		}
324 		if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
325 			/* Allocate a buffer on heap, and vsnprintf to this buffer */
326 			heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
327 			if (heap_buffer == NULL) {
328 				goto cleanup;
329 			}
330 
331 			if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
332 				/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
333 				snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_INFO_PREFIX_FORMAT, module);
334 			} else {
335 				/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
336 				memcpy(heap_buffer, stack_buffer, prefix_chars);
337 			}
338 			vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
339 			out_buffer = heap_buffer;
340 		}
341 		out_buffer[prefix_chars + format_chars] = '\n';
342 		#if defined(_WIN32)
343 			DWORD bytes_written;
344 			WriteFile(
345 				GetStdHandle(STD_OUTPUT_HANDLE),
346 				out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
347 				&bytes_written, NULL);
348 		#elif defined(__hexagon__)
349 			qurt_printf("%s", out_buffer);
350 		#else
351 			write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
352 		#endif
353 
354 cleanup:
355 		free(heap_buffer);
356 		va_end(args_copy);
357 	#endif
358 }
359 
clog_vlog_debug(const char * module,const char * format,va_list args)360 void clog_vlog_debug(const char* module, const char* format, va_list args) {
361 	#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
362 		__android_log_vprint(ANDROID_LOG_DEBUG, module, format, args);
363 	#else
364 		char stack_buffer[CLOG_STACK_BUFFER_SIZE];
365 		char* heap_buffer = NULL;
366 		char* out_buffer = &stack_buffer[0];
367 
368 		/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
369 		va_list args_copy;
370 		va_copy(args_copy, args);
371 
372 		int prefix_chars = CLOG_DEBUG_PREFIX_LENGTH;
373 		if (module == NULL) {
374 			memcpy(stack_buffer, CLOG_DEBUG_PREFIX, CLOG_DEBUG_PREFIX_LENGTH);
375 		} else {
376 			prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_DEBUG_PREFIX_FORMAT, module);
377 			if (prefix_chars < 0) {
378 				/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
379 				prefix_chars = 0;
380 			}
381 		}
382 
383 		int format_chars;
384 		if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
385 			/*
386 			 * Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
387 			 * Do not even try to format the string into on-stack buffer.
388 			 */
389 			format_chars = vsnprintf(NULL, 0, format, args);
390 		} else {
391 			format_chars =
392 				vsnprintf(
393 					&stack_buffer[prefix_chars],
394 					CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
395 					format,
396 					args);
397 		}
398 		if (format_chars < 0) {
399 			/* Format error in the message: silently ignore this particular message. */
400 			goto cleanup;
401 		}
402 		if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
403 			/* Allocate a buffer on heap, and vsnprintf to this buffer */
404 			heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
405 			if (heap_buffer == NULL) {
406 				goto cleanup;
407 			}
408 
409 			if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
410 				/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
411 				snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_DEBUG_PREFIX_FORMAT, module);
412 			} else {
413 				/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
414 				memcpy(heap_buffer, stack_buffer, prefix_chars);
415 			}
416 			vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
417 			out_buffer = heap_buffer;
418 		}
419 		out_buffer[prefix_chars + format_chars] = '\n';
420 		#if defined(_WIN32)
421 			DWORD bytes_written;
422 			WriteFile(
423 				GetStdHandle(STD_OUTPUT_HANDLE),
424 				out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
425 				&bytes_written, NULL);
426 		#elif defined(__hexagon__)
427 			qurt_printf("%s", out_buffer);
428 		#else
429 			write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
430 		#endif
431 
432 cleanup:
433 		free(heap_buffer);
434 		va_end(args_copy);
435 	#endif
436 }
437