initial import
[vuplus_webkit] / Source / JavaScriptCore / wtf / Assertions.cpp
1 /*
2  * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007-2009 Torch Mobile, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 // The vprintf_stderr_common function triggers this error in the Mac build.
28 // Feel free to remove this pragma if this file builds on Mac.
29 // According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
30 // we need to place this directive before any data or functions are defined.
31 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
32
33 #include "config.h"
34 #include "Assertions.h"
35
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <string.h>
39
40 #if PLATFORM(MAC)
41 #include <CoreFoundation/CFString.h>
42 #endif
43
44 #if COMPILER(MSVC) && !OS(WINCE) && !PLATFORM(BREWMP)
45 #include <crtdbg.h>
46 #endif
47
48 #if OS(WINDOWS)
49 #include <windows.h>
50 #endif
51
52 #if PLATFORM(BREWMP)
53 #include <AEEdbg.h>
54 #include <wtf/Vector.h>
55 #endif
56
57 #if PLATFORM(MAC)
58 #include <cxxabi.h>
59 #include <dlfcn.h>
60 #include <execinfo.h>
61 #endif
62
63 extern "C" {
64
65 #if PLATFORM(BREWMP)
66
67 static void printLog(const Vector<char>& buffer)
68 {
69     // Each call to DBGPRINTF generates at most 128 bytes of output on the Windows SDK.
70     // On Qualcomm chipset targets, DBGPRINTF() comes out the diag port (though this may change).
71     // The length of each output string is constrained even more than on the Windows SDK.
72 #if COMPILER(MSVC)
73     const int printBufferSize = 128;
74 #else
75     const int printBufferSize = 32;
76 #endif
77
78     char printBuffer[printBufferSize + 1];
79     printBuffer[printBufferSize] = 0; // to guarantee null termination
80
81     const char* p = buffer.data();
82     const char* end = buffer.data() + buffer.size();
83     while (p < end) {
84         strncpy(printBuffer, p, printBufferSize);
85         dbg_Message(printBuffer, DBG_MSG_LEVEL_HIGH, __FILE__, __LINE__);
86         p += printBufferSize;
87     }
88 }
89
90 #endif
91
92 WTF_ATTRIBUTE_PRINTF(1, 0)
93 static void vprintf_stderr_common(const char* format, va_list args)
94 {
95 #if PLATFORM(MAC)
96     if (strstr(format, "%@")) {
97         CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
98         CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args);
99
100         int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
101         char* buffer = (char*)malloc(length + 1);
102
103         CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8);
104
105         fputs(buffer, stderr);
106
107         free(buffer);
108         CFRelease(str);
109         CFRelease(cfFormat);
110         return;
111     }
112 #elif PLATFORM(BREWMP)
113     // When str is 0, the return value is the number of bytes needed
114     // to accept the result including null termination.
115     int size = vsnprintf(0, 0, format, args);
116     if (size > 0) {
117         Vector<char> buffer(size);
118         vsnprintf(buffer.data(), size, format, args);
119         printLog(buffer);
120     }
121
122 #elif HAVE(ISDEBUGGERPRESENT)
123     if (IsDebuggerPresent()) {
124         size_t size = 1024;
125
126         do {
127             char* buffer = (char*)malloc(size);
128
129             if (buffer == NULL)
130                 break;
131
132             if (_vsnprintf(buffer, size, format, args) != -1) {
133 #if OS(WINCE)
134                 // WinCE only supports wide chars
135                 wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t));
136                 if (wideBuffer == NULL)
137                     break;
138                 for (unsigned int i = 0; i < size; ++i) {
139                     if (!(wideBuffer[i] = buffer[i]))
140                         break;
141                 }
142                 OutputDebugStringW(wideBuffer);
143                 free(wideBuffer);
144 #else
145                 OutputDebugStringA(buffer);
146 #endif
147                 free(buffer);
148                 break;
149             }
150
151             free(buffer);
152             size *= 2;
153         } while (size > 1024);
154     }
155 #endif
156 #if OS(SYMBIAN)
157     vfprintf(stdout, format, args);
158 #else
159     vfprintf(stderr, format, args);
160 #endif
161 }
162
163 WTF_ATTRIBUTE_PRINTF(1, 2)
164 static void printf_stderr_common(const char* format, ...)
165 {
166     va_list args;
167     va_start(args, format);
168     vprintf_stderr_common(format, args);
169     va_end(args);
170 }
171
172 static void printCallSite(const char* file, int line, const char* function)
173 {
174 #if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG)
175     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
176 #else
177     // By using this format, which matches the format used by MSVC for compiler errors, developers
178     // using Visual Studio can double-click the file/line number in the Output Window to have the
179     // editor navigate to that line of code. It seems fine for other developers, too.
180     printf_stderr_common("%s(%d) : %s\n", file, line, function);
181 #endif
182 }
183
184 void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
185 {
186     if (assertion)
187         printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
188     else
189         printf_stderr_common("SHOULD NEVER BE REACHED\n");
190     printCallSite(file, line, function);
191 }
192
193 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
194 {
195     printf_stderr_common("ASSERTION FAILED: ");
196     va_list args;
197     va_start(args, format);
198     vprintf_stderr_common(format, args);
199     va_end(args);
200     printf_stderr_common("\n%s\n", assertion);
201     printCallSite(file, line, function);
202 }
203
204 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
205 {
206     printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
207     printCallSite(file, line, function);
208 }
209
210 void WTFReportBacktrace()
211 {
212 #if PLATFORM(MAC)
213     static const int maxFrames = 32;
214     void* samples[maxFrames];
215     int frames = backtrace(samples, maxFrames);
216
217     for (int i = 1; i < frames; ++i) {
218         void* pointer = samples[i];
219
220         // Try to get a symbol name from the dynamic linker.
221         Dl_info info;
222         if (dladdr(pointer, &info) && info.dli_sname) {
223             const char* mangledName = info.dli_sname;
224
225             // Assume c++ & try to demangle the name.
226             char* demangledName = abi::__cxa_demangle(mangledName, 0, 0, 0);
227             if (demangledName) {
228                 fprintf(stderr, "%-3d %s\n", i, demangledName);
229                 free(demangledName);
230             } else
231                 fprintf(stderr, "%-3d %s\n", i, mangledName);
232         } else
233             fprintf(stderr, "%-3d %p\n", i, pointer);
234     }
235 #endif
236 }
237
238 void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
239 {
240     printf_stderr_common("FATAL ERROR: ");
241     va_list args;
242     va_start(args, format);
243     vprintf_stderr_common(format, args);
244     va_end(args);
245     printf_stderr_common("\n");
246     printCallSite(file, line, function);
247 }
248
249 void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
250 {
251     printf_stderr_common("ERROR: ");
252     va_list args;
253     va_start(args, format);
254     vprintf_stderr_common(format, args);
255     va_end(args);
256     printf_stderr_common("\n");
257     printCallSite(file, line, function);
258 }
259
260 void WTFLog(WTFLogChannel* channel, const char* format, ...)
261 {
262     if (channel->state != WTFLogChannelOn)
263         return;
264
265     va_list args;
266     va_start(args, format);
267     vprintf_stderr_common(format, args);
268     va_end(args);
269     
270     size_t formatLength = strlen(format);
271     if (formatLength && format[formatLength - 1] != '\n')
272         printf_stderr_common("\n");
273 }
274
275 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
276 {
277     if (channel->state != WTFLogChannelOn)
278         return;
279
280     va_list args;
281     va_start(args, format);
282     vprintf_stderr_common(format, args);
283     va_end(args);
284
285     size_t formatLength = strlen(format);
286     if (formatLength && format[formatLength - 1] != '\n')
287         printf_stderr_common("\n");
288
289     printCallSite(file, line, function);
290 }
291
292 } // extern "C"