зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 5 changesets (bug 1794063, bug 1790873
) for causing Linux spidermonkey builds bustages in Printer.h. CLOSED TREE
Backed out changeset c729aa80e73e (bug 1794063) Backed out changeset 442a0de27b61 (bug1790873
) Backed out changeset 6934f2978802 (bug1790873
) Backed out changeset 296f6da7b6ed (bug1790873
) Backed out changeset 01ddb562d770 (bug1790873
)
This commit is contained in:
Родитель
973287f3eb
Коммит
94288d3f1e
|
@ -69,7 +69,6 @@ included_inclnames_to_ignore = set(
|
|||
"jit/LIROpsGenerated.h", # generated in $OBJDIR
|
||||
"jit/MIROpsGenerated.h", # generated in $OBJDIR
|
||||
"js/ProfilingCategoryList.h", # comes from mozglue/baseprofiler
|
||||
"mozilla/glue/Debug.h", # comes from mozglue/misc, shadowed by <mozilla/Debug.h>
|
||||
"jscustomallocator.h", # provided by embedders; allowed to be missing
|
||||
"js-config.h", # generated in $OBJDIR
|
||||
"fdlibm.h", # fdlibm
|
||||
|
|
|
@ -147,10 +147,6 @@ def main():
|
|||
"Decimal.o",
|
||||
# Ignore use of std::string in regexp AST debug output.
|
||||
"regexp-ast.o",
|
||||
# mozglue/misc/Debug.cpp contains a call to `printf_stderr("%s", aStr.str().c_str())`
|
||||
# where `aStr` is a `std::stringstream`. In inlined opt builds, this calls
|
||||
# `operator new()` and `operator delete` for a temporary.
|
||||
"Debug.o",
|
||||
]
|
||||
all_ignored_files = set((f, 1) for f in ignored_files)
|
||||
|
||||
|
|
|
@ -1464,13 +1464,16 @@ void CompositorOGL::InitializeVAO(const GLuint aAttrib, const GLint aComponents,
|
|||
#ifdef MOZ_DUMP_PAINTING
|
||||
template <typename T>
|
||||
void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf) {
|
||||
nsCString string(aObj->Name());
|
||||
string.Append('-');
|
||||
string.AppendInt((uint64_t)aObj);
|
||||
if (gfxUtils::sDumpPaintFile != stderr) {
|
||||
gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
|
||||
} else {
|
||||
nsCString uri = gfxUtils::GetAsDataURI(aSurf);
|
||||
nsPrintfCString string(R"(array["%s-%)" PRIu64 R"("]="%s";\n)",
|
||||
aObj->Name(), uint64_t(aObj), uri.BeginReading());
|
||||
fprintf_stderr(gfxUtils::sDumpPaintFile, "%s", string.get());
|
||||
fprintf_stderr(gfxUtils::sDumpPaintFile, R"(array["%s"]=")",
|
||||
string.BeginReading());
|
||||
}
|
||||
gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
|
||||
if (gfxUtils::sDumpPaintFile != stderr) {
|
||||
fprintf_stderr(gfxUtils::sDumpPaintFile, R"(";)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,20 +126,20 @@ void NS_GetComplexLineBreaks(const char16_t* aText, uint32_t aLength,
|
|||
}
|
||||
|
||||
if (mismatch) {
|
||||
nsCString line("uniscribe: ");
|
||||
// The logging here doesn't handle surrogates, but we only have tests using
|
||||
// Thai currently, which is BMP-only.
|
||||
printf_stderr("uniscribe: ");
|
||||
for (uint32_t i = 0; i < aLength; ++i) {
|
||||
if (aBreakBefore[i]) line.Append('#');
|
||||
line.Append(NS_ConvertUTF16toUTF8(aText + i, 1).get());
|
||||
if (aBreakBefore[i]) printf_stderr("#");
|
||||
printf_stderr("%s", NS_ConvertUTF16toUTF8(aText + i, 1).get());
|
||||
}
|
||||
printf_stderr("%s\n", line.get());
|
||||
line.Assign("brokered : ");
|
||||
printf_stderr("\n");
|
||||
printf_stderr("brokered : ");
|
||||
for (uint32_t i = 0; i < aLength; ++i) {
|
||||
if (brokeredBreaks[i]) line.Append('#');
|
||||
line.Append(NS_ConvertUTF16toUTF8(aText + i, 1).get());
|
||||
if (brokeredBreaks[i]) printf_stderr("#");
|
||||
printf_stderr("%s", NS_ConvertUTF16toUTF8(aText + i, 1).get());
|
||||
}
|
||||
printf_stderr("%s\n", line.get());
|
||||
printf_stderr("\n");
|
||||
MOZ_CRASH("Brokered breaks did not match.");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define js_Printer_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -340,22 +339,7 @@ class JS_PUBLIC_API Fprinter final : public GenericPrinter {
|
|||
|
||||
// Puts |len| characters from |s| at the current position and
|
||||
// return true on success, false on failure.
|
||||
bool put(const char* s, size_t len) override;
|
||||
using GenericPrinter::put; // pick up |inline bool put(const char* s);|
|
||||
};
|
||||
|
||||
// SEprinter, print using printf_stderr (goes to Android log, Windows debug,
|
||||
// else just stderr).
|
||||
class SEprinter final : public GenericPrinter {
|
||||
public:
|
||||
constexpr SEprinter() {}
|
||||
|
||||
// Puts |len| characters from |s| at the current position and
|
||||
// return true on success, false on failure.
|
||||
virtual bool put(const char* s, size_t len) override {
|
||||
printf_stderr("%.*s", int(len), s);
|
||||
return true;
|
||||
}
|
||||
virtual void put(const char* s, size_t len) override;
|
||||
using GenericPrinter::put; // pick up |inline bool put(const char* s);|
|
||||
};
|
||||
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/Fuzzing.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
# include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifndef ANDROID
|
||||
static void vprintf_stderr_buffered(const char* aFmt, va_list aArgs) {
|
||||
// Avoid interleaving by writing to an on-stack buffer and then writing in one
|
||||
// go with fputs, as long as the output fits into the buffer.
|
||||
char buffer[1024];
|
||||
va_list argsCpy;
|
||||
va_copy(argsCpy, aArgs);
|
||||
int n = VsprintfLiteral(buffer, aFmt, aArgs);
|
||||
if (n < int(sizeof(buffer))) {
|
||||
fputs(buffer, stderr);
|
||||
} else {
|
||||
// Message too long for buffer. Just print it, not worrying about
|
||||
// interleaving. (We could malloc, but the underlying write() syscall could
|
||||
// get interleaved if the output is too big anyway.)
|
||||
vfprintf(stderr, aFmt, argsCpy);
|
||||
}
|
||||
va_end(argsCpy);
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
if (IsDebuggerPresent()) {
|
||||
int lengthNeeded = _vscprintf(aFmt, aArgs);
|
||||
if (lengthNeeded) {
|
||||
lengthNeeded++;
|
||||
auto buf = mozilla::MakeUnique<char[]>(lengthNeeded);
|
||||
if (buf) {
|
||||
va_list argsCpy;
|
||||
va_copy(argsCpy, aArgs);
|
||||
vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
|
||||
buf[lengthNeeded - 1] = '\0';
|
||||
va_end(argsCpy);
|
||||
OutputDebugStringA(buf.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vprintf_stderr_buffered(aFmt, aArgs);
|
||||
}
|
||||
|
||||
#elif defined(ANDROID)
|
||||
MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
__android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
|
||||
}
|
||||
#elif defined(FUZZING_SNAPSHOT)
|
||||
MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
if (nyx_puts) {
|
||||
auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs);
|
||||
nyx_puts(msgbuf.get());
|
||||
} else {
|
||||
vprintf_stderr_buffered(aFmt, aArgs);
|
||||
}
|
||||
}
|
||||
#else
|
||||
MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
vprintf_stderr_buffered(aFmt, aArgs);
|
||||
}
|
||||
#endif
|
||||
|
||||
MFBT_API void printf_stderr(const char* aFmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, aFmt);
|
||||
vprintf_stderr(aFmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
MFBT_API void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, aFmt);
|
||||
if (aFile == stderr) {
|
||||
vprintf_stderr(aFmt, args);
|
||||
} else {
|
||||
vfprintf(aFile, aFmt, args);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
MFBT_API void print_stderr(std::stringstream& aStr) {
|
||||
#if defined(ANDROID)
|
||||
// On Android logcat output is truncated to 1024 chars per line, and
|
||||
// we usually use std::stringstream to build up giant multi-line gobs
|
||||
// of output. So to avoid the truncation we find the newlines and
|
||||
// print the lines individually.
|
||||
std::string line;
|
||||
while (std::getline(aStr, line)) {
|
||||
printf_stderr("%s\n", line.c_str());
|
||||
}
|
||||
#else
|
||||
printf_stderr("%s", aStr.str().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
MFBT_API void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
|
||||
if (aFile == stderr) {
|
||||
print_stderr(aStr);
|
||||
} else {
|
||||
fprintf_stderr(aFile, "%s", aStr.str().c_str());
|
||||
}
|
||||
}
|
|
@ -7,12 +7,6 @@
|
|||
#ifndef mozilla_glue_Debug_h
|
||||
#define mozilla_glue_Debug_h
|
||||
|
||||
#include "mozilla/Attributes.h" // For MOZ_FORMAT_PRINTF
|
||||
#include "mozilla/Types.h" // For MFBT_API
|
||||
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
|
||||
/* This header file intends to supply debugging utilities for use in code
|
||||
* that cannot use XPCOM debugging facilities like nsDebug.h.
|
||||
* e.g. mozglue, browser/app
|
||||
|
@ -21,53 +15,52 @@
|
|||
* care; avoid including from header files.
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
#if defined(XP_WIN)
|
||||
# include <windows.h>
|
||||
#endif // defined(XP_WIN)
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
# error Do not include this file from XUL sources.
|
||||
#endif
|
||||
|
||||
// Though this is a separate implementation than nsDebug's, we want to make the
|
||||
// declarations compatible to avoid confusing the linker if both headers are
|
||||
// included.
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
/**
|
||||
* printf_stderr(...) is much like fprintf(stderr, ...), except that:
|
||||
* - on Android and Firefox OS, *instead* of printing to stderr, it
|
||||
* prints to logcat. (Newlines in the string lead to multiple lines
|
||||
* of logcat, but each function call implicitly completes a line even
|
||||
* if the string does not end with a newline.)
|
||||
* - on Windows, if a debugger is present, it calls OutputDebugString
|
||||
* in *addition* to writing to stderr
|
||||
*/
|
||||
MFBT_API void printf_stderr(const char* aFmt, ...) MOZ_FORMAT_PRINTF(1, 2);
|
||||
void printf_stderr(const char* fmt, ...) MOZ_FORMAT_PRINTF(1, 2);
|
||||
inline void printf_stderr(const char* fmt, ...) {
|
||||
#if defined(XP_WIN)
|
||||
if (IsDebuggerPresent()) {
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
VsprintfLiteral(buf, fmt, args);
|
||||
va_end(args);
|
||||
OutputDebugStringA(buf);
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
/**
|
||||
* Same as printf_stderr, but taking va_list instead of varargs
|
||||
*/
|
||||
MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs)
|
||||
MOZ_FORMAT_PRINTF(1, 0);
|
||||
// stderr is unbuffered by default so we open a new FILE (which is buffered)
|
||||
// so that calls to printf_stderr are not as likely to get mixed together.
|
||||
int fd = _fileno(stderr);
|
||||
if (fd == -2) return;
|
||||
|
||||
/**
|
||||
* fprintf_stderr is like fprintf, except that if its file argument
|
||||
* is stderr, it invokes printf_stderr instead.
|
||||
*
|
||||
* This is useful for general debugging code that logs information to a
|
||||
* file, but that you would like to be useful on Android and Firefox OS.
|
||||
* If you use fprintf_stderr instead of fprintf in such debugging code,
|
||||
* then callers can pass stderr to get logging that works on Android and
|
||||
* Firefox OS (and also the other side-effects of using printf_stderr).
|
||||
*
|
||||
* Code that is structured this way needs to be careful not to split a
|
||||
* line of output across multiple calls to fprintf_stderr, since doing
|
||||
* so will cause it to appear in multiple lines in logcat output.
|
||||
* (Producing multiple lines at once is fine.)
|
||||
*/
|
||||
MFBT_API void fprintf_stderr(FILE* aFile, const char* aFmt, ...)
|
||||
MOZ_FORMAT_PRINTF(2, 3);
|
||||
FILE* fp = _fdopen(_dup(fd), "a");
|
||||
if (!fp) return;
|
||||
|
||||
/*
|
||||
* print_stderr and fprint_stderr are like printf_stderr and fprintf_stderr,
|
||||
* except they deal with Android logcat line length limitations. They do this
|
||||
* by printing individual lines out of the provided stringstream using separate
|
||||
* calls to logcat.
|
||||
*/
|
||||
MFBT_API void print_stderr(std::stringstream& aStr);
|
||||
MFBT_API void fprint_stderr(FILE* aFile, std::stringstream& aStr);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(fp, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ if CONFIG["OS_ARCH"] == "WINNT":
|
|||
SOURCES += [
|
||||
"AutoProfilerLabel.cpp",
|
||||
"AwakeTimeStamp.cpp",
|
||||
"Debug.cpp",
|
||||
"MmapFaultHandler.cpp",
|
||||
"Printf.cpp",
|
||||
"SIMD.cpp",
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
#ifdef XP_WIN
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
# include "mozilla/LateWriteChecks.h"
|
||||
# include "mozilla/UniquePtr.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
# include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef FUZZING_SNAPSHOT
|
||||
|
@ -224,3 +230,99 @@ void NS_MakeRandomString(char* aBuf, int32_t aBufLen) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
if (IsDebuggerPresent()) {
|
||||
int lengthNeeded = _vscprintf(aFmt, aArgs);
|
||||
if (lengthNeeded) {
|
||||
lengthNeeded++;
|
||||
auto buf = MakeUnique<char[]>(lengthNeeded);
|
||||
if (buf) {
|
||||
va_list argsCpy;
|
||||
va_copy(argsCpy, aArgs);
|
||||
vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
|
||||
buf[lengthNeeded - 1] = '\0';
|
||||
va_end(argsCpy);
|
||||
OutputDebugStringA(buf.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stderr is unbuffered by default so we open a new FILE (which is buffered)
|
||||
// so that calls to printf_stderr are not as likely to get mixed together.
|
||||
int fd = _fileno(stderr);
|
||||
if (fd == -2) {
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* fp = _fdopen(_dup(fd), "a");
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
|
||||
vfprintf(fp, aFmt, aArgs);
|
||||
|
||||
AutoSuspendLateWriteChecks suspend;
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#elif defined(ANDROID)
|
||||
void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
__android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
|
||||
}
|
||||
#elif defined(FUZZING_SNAPSHOT)
|
||||
void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
if (nyx_puts) {
|
||||
auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs);
|
||||
nyx_puts(msgbuf.get());
|
||||
} else {
|
||||
vfprintf(stderr, aFmt, aArgs);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void vprintf_stderr(const char* aFmt, va_list aArgs) {
|
||||
vfprintf(stderr, aFmt, aArgs);
|
||||
}
|
||||
#endif
|
||||
|
||||
void printf_stderr(const char* aFmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, aFmt);
|
||||
vprintf_stderr(aFmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, aFmt);
|
||||
if (aFile == stderr) {
|
||||
vprintf_stderr(aFmt, args);
|
||||
} else {
|
||||
vfprintf(aFile, aFmt, args);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void print_stderr(std::stringstream& aStr) {
|
||||
#if defined(ANDROID)
|
||||
// On Android logcat output is truncated to 1024 chars per line, and
|
||||
// we usually use std::stringstream to build up giant multi-line gobs
|
||||
// of output. So to avoid the truncation we find the newlines and
|
||||
// print the lines individually.
|
||||
std::string line;
|
||||
while (std::getline(aStr, line)) {
|
||||
printf_stderr("%s\n", line.c_str());
|
||||
}
|
||||
#else
|
||||
printf_stderr("%s", aStr.str().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
|
||||
if (aFile == stderr) {
|
||||
print_stderr(aStr);
|
||||
} else {
|
||||
fprintf_stderr(aFile, "%s", aStr.str().c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "nsXPCOM.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/DbgMacro.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include <stdarg.h>
|
||||
|
@ -327,4 +326,59 @@ void NS_ABORT_OOM(size_t aSize);
|
|||
inline void NS_ABORT_OOM(size_t) { MOZ_CRASH(); }
|
||||
#endif
|
||||
|
||||
/* When compiling the XPCOM Glue on Windows, we pretend that it's going to
|
||||
* be linked with a static CRT (-MT) even when it's not. This means that we
|
||||
* cannot link to data exports from the CRT, only function exports. So,
|
||||
* instead of referencing "stderr" directly, use fdopen.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* printf_stderr(...) is much like fprintf(stderr, ...), except that:
|
||||
* - on Android and Firefox OS, *instead* of printing to stderr, it
|
||||
* prints to logcat. (Newlines in the string lead to multiple lines
|
||||
* of logcat, but each function call implicitly completes a line even
|
||||
* if the string does not end with a newline.)
|
||||
* - on Windows, if a debugger is present, it calls OutputDebugString
|
||||
* in *addition* to writing to stderr
|
||||
*/
|
||||
void printf_stderr(const char* aFmt, ...) MOZ_FORMAT_PRINTF(1, 2);
|
||||
|
||||
/**
|
||||
* Same as printf_stderr, but taking va_list instead of varargs
|
||||
*/
|
||||
void vprintf_stderr(const char* aFmt, va_list aArgs) MOZ_FORMAT_PRINTF(1, 0);
|
||||
|
||||
/**
|
||||
* fprintf_stderr is like fprintf, except that if its file argument
|
||||
* is stderr, it invokes printf_stderr instead.
|
||||
*
|
||||
* This is useful for general debugging code that logs information to a
|
||||
* file, but that you would like to be useful on Android and Firefox OS.
|
||||
* If you use fprintf_stderr instead of fprintf in such debugging code,
|
||||
* then callers can pass stderr to get logging that works on Android and
|
||||
* Firefox OS (and also the other side-effects of using printf_stderr).
|
||||
*
|
||||
* Code that is structured this way needs to be careful not to split a
|
||||
* line of output across multiple calls to fprintf_stderr, since doing
|
||||
* so will cause it to appear in multiple lines in logcat output.
|
||||
* (Producing multiple lines at once is fine.)
|
||||
*/
|
||||
void fprintf_stderr(FILE* aFile, const char* aFmt, ...) MOZ_FORMAT_PRINTF(2, 3);
|
||||
|
||||
/*
|
||||
* print_stderr and fprint_stderr are like printf_stderr and fprintf_stderr,
|
||||
* except they deal with Android logcat line length limitations. They do this
|
||||
* by printing individual lines out of the provided stringstream using separate
|
||||
* calls to logcat.
|
||||
*/
|
||||
void print_stderr(std::stringstream& aStr);
|
||||
void fprint_stderr(FILE* aFile, std::stringstream& aStr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* nsDebug_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче