• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation.   All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 ****************************************************************************/
23 
24 #include "common/os.h"
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <assert.h>
28 #include <algorithm>
29 #include <mutex>
30 
31 #if SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS
32 
33 #if defined(_WIN32)
34 #pragma comment(lib, "user32.lib")
35 #endif // _WIN32
36 
37 namespace ConsoleUtils
38 {
39     enum class TextColor
40     {
41         BLACK      = 0,
42 #if defined(_WIN32)
43         RED        = 4,
44         GREEN      = 2,
45         BLUE       = 1,
46 #else
47         RED        = 1,
48         GREEN      = 2,
49         BLUE       = 4,
50 #endif // _WIN32
51         PURPLE     = static_cast<uint32_t>(RED) | static_cast<uint32_t>(BLUE),
52         CYAN       = static_cast<uint32_t>(GREEN) | static_cast<uint32_t>(BLUE),
53         YELLOW     = static_cast<uint32_t>(RED) | static_cast<uint32_t>(GREEN),
54         WHITE      = static_cast<uint32_t>(RED) | static_cast<uint32_t>(GREEN) | static_cast<uint32_t>(BLUE),
55     };
56 
57     enum class TextStyle
58     {
59         NORMAL     = 0,
60         INTENSITY  = 1,
61     };
62 
SetTextColor(FILE * stream,TextColor color=TextColor::WHITE,TextStyle style=TextStyle::NORMAL)63     void SetTextColor(FILE* stream, TextColor color = TextColor::WHITE, TextStyle style = TextStyle::NORMAL)
64     {
65 #if defined(_WIN32)
66 
67         HANDLE hConsoleHandle = nullptr;
68         if (stream == stderr)
69         {
70             hConsoleHandle = GetStdHandle(STD_ERROR_HANDLE);
71         }
72         else if (stream == stdout)
73         {
74             hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
75         }
76         else
77         {
78             // Not a console stream, do nothing
79             return;
80         }
81 
82         WORD textAttributes = static_cast<WORD>(color);
83         if (style == TextStyle::INTENSITY)
84         {
85             textAttributes |= FOREGROUND_INTENSITY;
86         }
87         SetConsoleTextAttribute(hConsoleHandle, textAttributes);
88 
89 #else // !_WIN32
90 
91         // Print ANSI codes
92         uint32_t cc = 30 + ((style == TextStyle::INTENSITY) ? 60 : 0) + static_cast<uint32_t>(color);
93         fprintf(stream, "\033[0m\033[%d;%dm", static_cast<uint32_t>(style), cc);
94 
95 #endif
96     }
97 
ResetTextColor(FILE * stream)98     void ResetTextColor(FILE* stream)
99     {
100 #if defined(_WIN32)
101 
102         SetTextColor(stream);
103 
104 #else // !_WIN32
105 
106         // Print ANSI codes
107         fprintf(stream, "\033[0m");
108 
109 #endif
110     }
111 
112     static std::mutex g_stderrMutex;
113 } // ns ConsoleUtils
114 
SwrAssert(bool chkDebugger,bool & enabled,const char * pExpression,const char * pFileName,uint32_t lineNum,const char * pFunction,const char * pFmtString,...)115 bool SwrAssert(
116         bool        chkDebugger,
117         bool&       enabled,
118         const char* pExpression,
119         const char* pFileName,
120         uint32_t    lineNum,
121         const char* pFunction,
122         const char* pFmtString,
123         ...)
124 {
125     using namespace ConsoleUtils;
126     std::lock_guard<std::mutex> l(g_stderrMutex);
127 
128     SetTextColor(stderr, TextColor::CYAN, TextStyle::NORMAL);
129 
130     fprintf(stderr, "%s(%d): ", pFileName, lineNum);
131 
132     SetTextColor(stderr, TextColor::RED, TextStyle::INTENSITY);
133 
134     fprintf(stderr, "ASSERT: %s\n", pExpression);
135 
136     SetTextColor(stderr, TextColor::CYAN, TextStyle::INTENSITY);
137     fprintf(stderr, "\t%s\n", pFunction);
138 
139     if (pFmtString)
140     {
141         SetTextColor(stderr, TextColor::YELLOW, TextStyle::INTENSITY);
142         fprintf(stderr, "\t");
143         va_list args;
144         va_start(args, pFmtString);
145         vfprintf(stderr, pFmtString, args);
146         va_end(args);
147         fprintf(stderr, "\n");
148     }
149     ResetTextColor(stderr);
150     fflush(stderr);
151 
152 #if defined(_WIN32)
153     static const int MAX_MESSAGE_LEN = 2048;
154     char msgBuf[MAX_MESSAGE_LEN];
155 
156     sprintf_s(msgBuf, "%s(%d): ASSERT: %s\n", pFileName, lineNum, pExpression);
157     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
158     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
159     OutputDebugStringA(msgBuf);
160 
161     sprintf_s(msgBuf, "\t%s\n", pFunction);
162     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
163     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
164     OutputDebugStringA(msgBuf);
165 
166     int offset = 0;
167 
168     if (pFmtString)
169     {
170         va_list args;
171         va_start(args, pFmtString);
172         offset = _vsnprintf_s(
173                 msgBuf,
174                 sizeof(msgBuf),
175                 sizeof(msgBuf),
176                 pFmtString,
177                 args);
178         va_end(args);
179 
180         if (offset < 0) { return true; }
181 
182         OutputDebugStringA("\t");
183         OutputDebugStringA(msgBuf);
184         OutputDebugStringA("\n");
185     }
186 
187     if (enabled && KNOB_ENABLE_ASSERT_DIALOGS)
188     {
189         int retval = sprintf_s(
190                 &msgBuf[offset],
191                 MAX_MESSAGE_LEN - offset,
192                 "\n\n"
193                 "File: %s\n"
194                 "Line: %d\n"
195                 "\n"
196                 "Expression: %s\n\n"
197                 "Cancel: Disable this assert for the remainder of the process\n"
198                 "Try Again: Break into the debugger\n"
199                 "Continue: Continue execution (but leave assert enabled)",
200                 pFileName,
201                 lineNum,
202                 pExpression);
203 
204         if (retval < 0) { return true; }
205 
206         offset += retval;
207 
208         if (!IsDebuggerPresent())
209         {
210             sprintf_s(
211                     &msgBuf[offset],
212                     MAX_MESSAGE_LEN - offset,
213                     "\n\n*** NO DEBUGGER DETECTED ***\n\nPressing \"Try Again\" will cause a program crash!");
214         }
215 
216         retval = MessageBoxA(nullptr, msgBuf, "Assert Failed", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
217 
218         switch (retval)
219         {
220             case IDCANCEL:
221                 enabled = false;
222                 return false;
223 
224             case IDTRYAGAIN:
225                 return true;
226 
227             case IDCONTINUE:
228                 return false;
229         }
230     }
231     else
232     {
233         return (IsDebuggerPresent() || !chkDebugger) && enabled;
234     }
235 #endif // _WIN32
236 
237     return enabled;
238 }
239 
SwrTrace(const char * pFileName,uint32_t lineNum,const char * pFunction,const char * pFmtString,...)240 void SwrTrace(
241         const char* pFileName,
242         uint32_t    lineNum,
243         const char* pFunction,
244         const char* pFmtString,
245         ...)
246 {
247     using namespace ConsoleUtils;
248     std::lock_guard<std::mutex> l(g_stderrMutex);
249 
250     SetTextColor(stderr, TextColor::CYAN, TextStyle::NORMAL);
251 
252     fprintf(stderr, "%s(%d): TRACE in %s:\n", pFileName, lineNum, pFunction);
253 
254     if (pFmtString)
255     {
256         SetTextColor(stderr, TextColor::PURPLE, TextStyle::INTENSITY);
257         fprintf(stderr, "\t");
258         va_list args;
259         va_start(args, pFmtString);
260         vfprintf(stderr, pFmtString, args);
261         va_end(args);
262         fprintf(stderr, "\n");
263     }
264     ResetTextColor(stderr);
265     fflush(stderr);
266 
267 #if defined(_WIN32)
268     static const int MAX_MESSAGE_LEN = 2048;
269     char msgBuf[MAX_MESSAGE_LEN];
270 
271     sprintf_s(msgBuf, "%s(%d): TRACE in %s\n", pFileName, lineNum, pFunction);
272     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
273     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
274     OutputDebugStringA(msgBuf);
275 
276     int offset = 0;
277 
278     if (pFmtString)
279     {
280         va_list args;
281         va_start(args, pFmtString);
282         offset = _vsnprintf_s(
283                 msgBuf,
284                 sizeof(msgBuf),
285                 sizeof(msgBuf),
286                 pFmtString,
287                 args);
288         va_end(args);
289 
290         if (offset < 0) { return; }
291 
292         OutputDebugStringA("\t");
293         OutputDebugStringA(msgBuf);
294         OutputDebugStringA("\n");
295     }
296 #endif // _WIN32
297 }
298 
299 #endif // SWR_ENABLE_ASSERTS
300