1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
/**
* @file llerror.h
* @brief Constants, functions, and macros for logging and runtime errors.
*
* Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#ifndef LL_LLERROR_H
#define LL_LLERROR_H
#include <sstream>
#include <stdio.h>
#include <stdarg.h>
#include "llerrorstream.h"
#include "llerrorbuffer.h"
// Specific error codes
const S32 LL_ERR_NOERR = 0;
const S32 LL_ERR_ASSET_REQUEST_FAILED = -1;
//const S32 LL_ERR_ASSET_REQUEST_INVALID = -2;
const S32 LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
const S32 LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
const S32 LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
const S32 LL_ERR_EOF = -39;
const S32 LL_ERR_CANNOT_OPEN_FILE = -42;
const S32 LL_ERR_FILE_NOT_FOUND = -43;
const S32 LL_ERR_FILE_EMPTY = -44;
const S32 LL_ERR_TCP_TIMEOUT = -23016;
const S32 LL_ERR_CIRCUIT_GONE = -23017;
// Error types
#define LLERR_IMAGE (1 << 1) // Image requests
#define LLERR_MESSAGE (1 << 2) // Messaging
#define LLERR_PERF (1 << 3) // Performance
#define LLERR_SQL (1 << 4) // SQL statements
#define LLERR_DOUG (1 << 5) // Doug's debugging
#define LLERR_USER_INPUT (1 << 6) // Keyboard and mouse
#define LLERR_TIMING (1 << 7) // Verbose time info
#define LLERR_TASK (1 << 8) // Tracking tasks
#define LLERR_MSG_HANDLER (1 << 9) //
#define LLERR_CIRCUIT_INFO (1 << 10) // Message system circuit info
#define LLERR_PHYSICS (1 << 11) // physics
#define LLERR_VFS (1 << 12) // VFS
const U32 LLERR_ALL = 0xffff;
const U32 LLERR_NONE = 0x0;
// Define one of these for different error levels in release...
// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
//////////////////////////////////////////
//
// Implementation - ignore
//
//
#ifdef _DEBUG
#define SHOW_DEBUG
#define SHOW_WARN
#define SHOW_INFO
#define SHOW_ASSERT
#else // _DEBUG
#ifdef RELEASE_SHOW_DEBUG
#define SHOW_DEBUG
#endif
#ifdef RELEASE_SHOW_WARN
#define SHOW_WARN
#endif
#ifdef RELEASE_SHOW_INFO
#define SHOW_INFO
#endif
#ifdef RELEASE_SHOW_ASSERT
#define SHOW_ASSERT
#endif
#endif // _DEBUG
extern LLErrorStream gErrorStream;
// LL Error macros
//
// Usage:
//
// llerrs << "An error, oh my!" << variable << endl;
// llwarns << "Another error, fuck me!" << variable << endl;
// llwarnst(LLERR_IMAGE) << "Debug, mother fucker" << endl;
//
// NOTE: The output format of filename(lineno): is so that MS DevStudio
// can parse the output and automatically jump to that location
inline std::string llerrno_string(int errnum)
{
std::stringstream res;
res << "error(" << errnum << "):" << strerror(errnum) << " ";
return res.str();
}
inline std::string llerror_file_line(const char* file, S32 line)
{
std::stringstream res;
res << file << "(" <<line << ")";
return res.str();
}
// Used to throw an error which is always causes a system halt.
#define llerrs if (gErrorStream.isEnabledFor(LLErrorBuffer::FATAL)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::FATAL; \
llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : error\n"; \
llerror_oss << "ERROR: " << llerror_file_line(__FILE__, __LINE__) << " "
// Used to show warnings
#define llwarns if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : WARNING: "; \
else llerror_oss << "WARNING: "; \
llerror_oss
// Alerts are for serious non-fatal situations that are not supposed to happen and need to alert someone
#define llalerts if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : ALERT: "; \
else llerror_oss << "ALERT: "; \
llerror_oss
// Used to show informational messages that don't get disabled
#define llinfos if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
else llerror_oss << "INFO: "; \
llerror_oss
#define llinfost(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO, type)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
else llerror_oss << "INFO: [" << #type << "] "; \
llerror_oss
// Used for general debugging output
#define lldebugs if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
else llerror_oss << "DEBUG: "; \
llerror_oss
#define lldebugst(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG, type)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
else llerror_oss << "DEBUG: [" << #type << "] "; \
llerror_oss
#define llendl std::endl; gErrorStream.crashOnError(llerror_oss, llerror_level); }
#define llendflush std::endl << std::flush; gErrorStream.crashOnError(llerror_oss, llerror_level); }
#define llcont llerror_oss
#define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl;
#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
#ifdef SHOW_ASSERT
#define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llassert(func)
#endif
#define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#ifdef SHOW_ASSERT
#define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llverify(func) (func); // get rid of warning C4189
#endif
// handy compile-time assert - enforce those template parameters!
#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1]
// Makes the app go down in flames, but on purpose!
void _llcrash_and_loop();
// Use as follows:
// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
//
// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
// should perhaps be replaced with boost::format.
inline std::string llformat(const char *fmt, ...)
{
char tstr[1024]; /* Flawfinder: ignore */
va_list va;
va_start(va, fmt);
#if LL_WINDOWS
_vsnprintf(tstr, 1024, fmt, va);
#else
vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
#endif
va_end(va);
return std::string(tstr);
}
// Helper class to temporarily change error level for the current scope.
class LLScopedErrorLevel
{
public:
LLScopedErrorLevel(LLErrorBuffer::ELevel error_level);
~LLScopedErrorLevel();
private:
LLErrorBuffer::ELevel mOrigErrorLevel;
};
#endif // LL_LLERROR_H
|