Debug.cpp (3387B)
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/. */ 6 7 #include "mozilla/glue/Debug.h" 8 #include "mozilla/Sprintf.h" 9 10 #include <stdarg.h> 11 #include <stdio.h> 12 13 #ifdef XP_WIN 14 # include <io.h> 15 # include <windows.h> 16 #endif 17 18 #ifdef ANDROID 19 # include <android/log.h> 20 #endif 21 22 #ifndef ANDROID 23 static void vprintf_stderr_buffered(const char* aFmt, va_list aArgs) { 24 // Avoid interleaving by writing to an on-stack buffer and then writing in one 25 // go with fputs, as long as the output fits into the buffer. 26 char buffer[1024]; 27 va_list argsCpy; 28 va_copy(argsCpy, aArgs); 29 int n = VsprintfLiteral(buffer, aFmt, aArgs); 30 if (n < int(sizeof(buffer))) { 31 fputs(buffer, stderr); 32 } else { 33 // Message too long for buffer. Just print it, not worrying about 34 // interleaving. (We could malloc, but the underlying write() syscall could 35 // get interleaved if the output is too big anyway.) 36 vfprintf(stderr, aFmt, argsCpy); 37 } 38 va_end(argsCpy); 39 fflush(stderr); 40 } 41 #endif 42 43 #if defined(XP_WIN) 44 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) { 45 if (IsDebuggerPresent()) { 46 int lengthNeeded = _vscprintf(aFmt, aArgs); 47 if (lengthNeeded) { 48 lengthNeeded++; 49 auto buf = mozilla::MakeUnique<char[]>(lengthNeeded); 50 if (buf) { 51 va_list argsCpy; 52 va_copy(argsCpy, aArgs); 53 vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy); 54 buf[lengthNeeded - 1] = '\0'; 55 va_end(argsCpy); 56 OutputDebugStringA(buf.get()); 57 } 58 } 59 } 60 61 vprintf_stderr_buffered(aFmt, aArgs); 62 } 63 64 #elif defined(ANDROID) 65 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) { 66 __android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs); 67 } 68 #elif defined(FUZZING_SNAPSHOT) 69 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) { 70 if (nyx_puts) { 71 auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs); 72 nyx_puts(msgbuf.get()); 73 } else { 74 vprintf_stderr_buffered(aFmt, aArgs); 75 } 76 } 77 #else 78 MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) { 79 vprintf_stderr_buffered(aFmt, aArgs); 80 } 81 #endif 82 83 MFBT_API void printf_stderr(const char* aFmt, ...) { 84 va_list args; 85 va_start(args, aFmt); 86 vprintf_stderr(aFmt, args); 87 va_end(args); 88 } 89 90 MFBT_API void fprintf_stderr(FILE* aFile, const char* aFmt, ...) { 91 va_list args; 92 va_start(args, aFmt); 93 if (aFile == stderr) { 94 vprintf_stderr(aFmt, args); 95 } else { 96 vfprintf(aFile, aFmt, args); 97 } 98 va_end(args); 99 } 100 101 MFBT_API void print_stderr(std::stringstream& aStr) { 102 #if defined(ANDROID) 103 // On Android logcat output is truncated to 1024 chars per line, and 104 // we usually use std::stringstream to build up giant multi-line gobs 105 // of output. So to avoid the truncation we find the newlines and 106 // print the lines individually. 107 std::string line; 108 while (std::getline(aStr, line)) { 109 printf_stderr("%s\n", line.c_str()); 110 } 111 #else 112 printf_stderr("%s", aStr.str().c_str()); 113 #endif 114 } 115 116 MFBT_API void fprint_stderr(FILE* aFile, std::stringstream& aStr) { 117 if (aFile == stderr) { 118 print_stderr(aStr); 119 } else { 120 fprintf_stderr(aFile, "%s", aStr.str().c_str()); 121 } 122 }