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