1 /*
2 * The ManaPlus Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2010 The Mana Developers
5 * Copyright (C) 2011-2019 The ManaPlus Developers
6 * Copyright (C) 2019-2021 Andrei Karas
7 *
8 * This file is part of The ManaPlus Client.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #ifndef LOGGER_H
25 #define LOGGER_H
26
27 #include "localconsts.h"
28
29 #include "utils/vector.h"
30
31 PRAGMA48(GCC diagnostic push)
32 PRAGMA48(GCC diagnostic ignored "-Wshadow")
33 #include <SDL_mutex.h>
PRAGMA48(GCC diagnostic pop)34 PRAGMA48(GCC diagnostic pop)
35
36 #include <string>
37
38 #ifdef ENABLEDEBUGLOG
39 #define DEBUGLOG(str) \
40 if (logger && !mIgnore) \
41 logger->dlog(str)
42 #define DEBUGLOG2(str, pos, comment) \
43 if (logger && !mIgnore) \
44 logger->dlog2(str, pos, comment)
45 #define DEBUGLOGSTR(str) \
46 if (logger) \
47 logger->dlog(str)
48 #define IGNOREDEBUGLOG mIgnore = Net::isIgnorePacket(mId)
49 #else // ENABLEDEBUGLOG
50 #define DEBUGLOG(str) {}
51 #define DEBUGLOG2(str, comment) {}
52 #define DEBUGLOGSTR(str)
53 #define IGNOREDEBUGLOG {}
54 #endif // ENABLEDEBUGLOG
55
56 #define UNIMPLEMENTEDPACKET \
57 logger->unimplemented(msg.getId())
58
59 #define UNIMPLEMENTEDPACKETFIELD(field) \
60 logger->unimplemented(msg.getId(), field)
61
62 #define WRONGPACKETSIZE \
63 logger->unimplemented(CAST_U32(mId), mLength, mPos)
64
65 /**
66 * The Log Class : Useful to write debug or info messages
67 */
68 class Logger final
69 {
70 public:
71 /**
72 * Constructor.
73 */
74 Logger();
75
76 A_DELETE_COPY(Logger)
77
78 /**
79 * Destructor, closes log file.
80 */
81 ~Logger();
82
83 /**
84 * Sets the file to log to and opens it
85 */
86 void setLogFile(const std::string &logFilename);
87
88 /**
89 * Sets whether the log should be written to standard output.
90 */
91 void setLogToStandardOut(const bool value)
92 { mLogToStandardOut = value; }
93
94 /**
95 * Enters a message in the log. The message will be timestamped.
96 */
97 void log(const char *const log_text, ...) A_NONNULL(2)
98 #ifdef __GNUC__
99 #ifdef __OpenBSD__
100
101 __attribute__((__format__(printf, 2, 3)))
102 #else // __OpenBSD__
103
104 #ifdef BAD_CILKPLUS
105 __attribute__((__format__(gnu_printf, 1, 2)))
106 #else // BAD_CILKPLUS
107
108 __attribute__((__format__(gnu_printf, 2, 3)))
109 #endif // BAD_CILKPLUS
110
111 #endif // __OpenBSD__
112 #endif // __GNUC__
113 ;
114
115 /**
116 * Enters a message in the log. The message will be timestamped.
117 */
118 void assertLog(const char *const log_text, ...) A_NONNULL(2)
119 #ifdef __GNUC__
120 #ifdef __OpenBSD__
121
122 __attribute__((__format__(printf, 2, 3)))
123 #else // __OpenBSD__
124
125 #ifdef BAD_CILKPLUS
126 __attribute__((__format__(gnu_printf, 1, 2)))
127 #else // BAD_CILKPLUS
128
129 __attribute__((__format__(gnu_printf, 2, 3)))
130 #endif // BAD_CILKPLUS
131
132 #endif // __OpenBSD__
133 #endif // __GNUC__
134 ;
135
136 /**
137 * Enters a message in the log (thread safe).
138 */
139 void log_r(const char *const log_text, ...) A_NONNULL(2)
140 #ifdef __GNUC__
141 #ifdef __OpenBSD__
142 __attribute__((__format__(printf, 2, 3)))
143 #else // __OpenBSD__
144
145 #ifdef BAD_CILKPLUS
146 __attribute__((__format__(gnu_printf, 1, 2)))
147 #else // BAD_CILKPLUS
148
149 __attribute__((__format__(gnu_printf, 2, 3)))
150 #endif // BAD_CILKPLUS
151
152 #endif // __OpenBSD__
153 #endif // __GNUC__
154 ;
155
156 /**
157 * Enters a message in the log. The message will be timestamped.
158 */
159 void log1(const char *const log_text) A_NONNULL(2);
160
161 /**
162 * Enters a message in the log. The message will be timestamped.
163 */
164 void log(const std::string &str);
165
166 void flush();
167
168 #ifdef ENABLEDEBUGLOG
169 /**
170 * Enters debug message in the log. The message will be timestamped.
171 */
172 void dlog(const std::string &str);
173
174 void dlog2(const std::string &str,
175 const int pos,
176 const char* const comment);
177 #endif // ENABLEDEBUGLOG
178
179 void closeFile();
180
181 void setDebugLog(const bool n)
182 { mDebugLog = n; }
183
184 void setReportUnimplemented(const bool n)
185 { mReportUnimplemented = n; }
186
187 /**
188 * Log an error and quit. The error will pop-up on Windows and Mac, and
189 * will be printed to standard error everywhere else.
190 */
191 void error(const std::string &error_text)
192 #ifndef BAD_CILKPLUS
193 __attribute__ ((noreturn))
194 #endif // BAD_CILKPLUS
195 ;
196
197 /**
198 * Log an error and quit. The error will pop-up on Windows and Mac, and
199 * will be printed to standard error everywhere else.
200 */
201 void safeError(const std::string &error_text)
202 #ifndef BAD_CILKPLUS
203 __attribute__ ((noreturn))
204 #endif // BAD_CILKPLUS
205 ;
206
207 void unimplemented(const int id);
208
209 void unimplemented(const int id,
210 const int id2);
211
212 void unimplemented(const uint32_t id,
213 const uint32_t id2,
214 const uint32_t id3) const;
215
216 FILE *getFile() const;
217
218 private:
219 FILE *mLogFile;
220 STD_VECTOR<std::string> mDelayedLog;
221 SDL_mutex *mMutex;
222 volatile bool mThreadLocked;
223 bool mLogToStandardOut;
224 bool mDebugLog;
225 bool mReportUnimplemented;
226 };
227
228 extern Logger *logger;
229
230 #endif // LOGGER_H
231