no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / mozglue / misc / Debug.cpp
blobc3a2ca89e079bf25851c57a7c89f8cbb8bf87abd
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/glue/Debug.h"
8 #include "mozilla/Fuzzing.h"
9 #include "mozilla/Sprintf.h"
11 #include <stdarg.h>
12 #include <stdio.h>
14 #ifdef XP_WIN
15 # include <io.h>
16 # include <windows.h>
17 #endif
19 #ifdef ANDROID
20 # include <android/log.h>
21 #endif
23 #ifndef ANDROID
24 static void vprintf_stderr_buffered(const char* aFmt, va_list aArgs) {
25 // Avoid interleaving by writing to an on-stack buffer and then writing in one
26 // go with fputs, as long as the output fits into the buffer.
27 char buffer[1024];
28 va_list argsCpy;
29 va_copy(argsCpy, aArgs);
30 int n = VsprintfLiteral(buffer, aFmt, aArgs);
31 if (n < int(sizeof(buffer))) {
32 fputs(buffer, stderr);
33 } else {
34 // Message too long for buffer. Just print it, not worrying about
35 // interleaving. (We could malloc, but the underlying write() syscall could
36 // get interleaved if the output is too big anyway.)
37 vfprintf(stderr, aFmt, argsCpy);
39 va_end(argsCpy);
40 fflush(stderr);
42 #endif
44 #if defined(XP_WIN)
45 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
46 if (IsDebuggerPresent()) {
47 int lengthNeeded = _vscprintf(aFmt, aArgs);
48 if (lengthNeeded) {
49 lengthNeeded++;
50 auto buf = mozilla::MakeUnique<char[]>(lengthNeeded);
51 if (buf) {
52 va_list argsCpy;
53 va_copy(argsCpy, aArgs);
54 vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
55 buf[lengthNeeded - 1] = '\0';
56 va_end(argsCpy);
57 OutputDebugStringA(buf.get());
62 vprintf_stderr_buffered(aFmt, aArgs);
65 #elif defined(ANDROID)
66 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
67 __android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
69 #elif defined(FUZZING_SNAPSHOT)
70 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
71 if (nyx_puts) {
72 auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs);
73 nyx_puts(msgbuf.get());
74 } else {
75 vprintf_stderr_buffered(aFmt, aArgs);
78 #else
79 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
80 vprintf_stderr_buffered(aFmt, aArgs);
82 #endif
84 MFBT_API void printf_stderr(const char* aFmt, ...) {
85 va_list args;
86 va_start(args, aFmt);
87 vprintf_stderr(aFmt, args);
88 va_end(args);
91 MFBT_API void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
92 va_list args;
93 va_start(args, aFmt);
94 if (aFile == stderr) {
95 vprintf_stderr(aFmt, args);
96 } else {
97 vfprintf(aFile, aFmt, args);
99 va_end(args);
102 MFBT_API void print_stderr(std::stringstream& aStr) {
103 #if defined(ANDROID)
104 // On Android logcat output is truncated to 1024 chars per line, and
105 // we usually use std::stringstream to build up giant multi-line gobs
106 // of output. So to avoid the truncation we find the newlines and
107 // print the lines individually.
108 std::string line;
109 while (std::getline(aStr, line)) {
110 printf_stderr("%s\n", line.c_str());
112 #else
113 printf_stderr("%s", aStr.str().c_str());
114 #endif
117 MFBT_API void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
118 if (aFile == stderr) {
119 print_stderr(aStr);
120 } else {
121 fprintf_stderr(aFile, "%s", aStr.str().c_str());