1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2002 Chris Schoeneman
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "arch/IArchMultithread.h"
22 #include "arch/Arch.h"
23 #include "common/common.h"
24 #include "common/stdlist.h"
25 
26 #include <stdarg.h>
27 
28 #define CLOG (Log::getInstance())
29 #define BYE "\nTry `%s --help' for more information."
30 
31 class ILogOutputter;
32 class Thread;
33 
34 //! Logging facility
35 /*!
36 The logging class;  all console output should go through this class.
37 It supports multithread safe operation, several message priority levels,
38 filtering by priority, and output redirection.  The macros LOG() and
39 LOGC() provide convenient access.
40 */
41 class Log {
42 public:
43     Log();
44     Log(Log* src);
45     Log(Log const &) =delete;
46     Log(Log &&) =delete;
47     ~Log();
48 
49     Log& operator=(Log const &) =delete;
50     Log& operator=(Log &&) =delete;
51 
52     //! @name manipulators
53     //@{
54 
55     //! Add an outputter to the head of the list
56     /*!
57     Inserts an outputter to the head of the outputter list.  When the
58     logger writes a message, it goes to the outputter at the head of
59     the outputter list.  If that outputter's \c write() method returns
60     true then it also goes to the next outputter, as so on until an
61     outputter returns false or there are no more outputters.  Outputters
62     still in the outputter list when the log is destroyed will be
63     deleted.  If \c alwaysAtHead is true then the outputter is always
64     called before all outputters with \c alwaysAtHead false and the
65     return value of the outputter is ignored.
66 
67     By default, the logger has one outputter installed which writes to
68     the console.
69     */
70     void                insert(ILogOutputter* adopted,
71                                bool alwaysAtHead = false);
72 
73     //! Remove an outputter from the list
74     /*!
75     Removes the first occurrence of the given outputter from the
76     outputter list.  It does nothing if the outputter is not in the
77     list.  The outputter is not deleted.
78     */
79     void                remove(ILogOutputter* orphaned);
80 
81     //! Remove the outputter from the head of the list
82     /*!
83     Removes and deletes the outputter at the head of the outputter list.
84     This does nothing if the outputter list is empty.  Only removes
85     outputters that were inserted with the matching \c alwaysAtHead.
86     */
87     void                pop_front(bool alwaysAtHead = false);
88 
89     //! Set the minimum priority filter.
90     /*!
91     Set the filter.  Messages below this priority are discarded.
92     The default priority is 4 (INFO) (unless built without NDEBUG
93     in which case it's 5 (DEBUG)).   setFilter(const char*) returns
94     true if the priority \c name was recognized;  if \c name is NULL
95     then it simply returns true.
96     */
97     bool                setFilter(const char* name);
98 
99     //! Set the minimum priority filter (by ordinal).
100     void                setFilter(int);
101 
102     //@}
103     //! @name accessors
104     //@{
105 
106     //! Print a log message
107     /*!
108     Print a log message using the printf-like \c format and arguments
109     preceded by the filename and line number.  If \c file is NULL then
110     neither the file nor the line are printed.
111     */
112     void                print(const char* file, int line,
113                             const char* format, ...);
114 
115     //! Get the minimum priority level.
116     int                    getFilter() const;
117 
118     //! Get the filter name of the current filter level.
119     const char*            getFilterName() const;
120 
121     //! Get the filter name of a specified filter level.
122     const char*            getFilterName(int level) const;
123 
124     //! Get the singleton instance of the log
125     static Log*        getInstance();
126 
127     //! Get the console filter level (messages above this are not sent to console).
getConsoleMaxLevel()128     int                    getConsoleMaxLevel() const { return kDEBUG2; }
129 
130     //@}
131 
132 private:
133     void                output(ELevel priority, char* msg);
134 
135 private:
136     typedef std::list<ILogOutputter*> OutputterList;
137 
138     static Log*        s_log;
139 
140     ArchMutex            m_mutex;
141     OutputterList        m_outputters;
142     OutputterList        m_alwaysOutputters;
143     int                    m_maxNewlineLength;
144     int                    m_maxPriority;
145 };
146 
147 /*!
148 \def LOG(arg)
149 Write to the log.  Because macros cannot accept variable arguments, this
150 should be invoked like so:
151 \code
152 LOG((CLOG_XXX "%d and %d are %s", x, y, x == y ? "equal" : "not equal"));
153 \endcode
154 In particular, notice the double open and close parentheses.  Also note
155 that there is no comma after the \c CLOG_XXX.  The \c XXX should be
156 replaced by one of enumerants in \c Log::ELevel without the leading
157 \c k.  For example, \c CLOG_INFO.  The special \c CLOG_PRINT level will
158 not be filtered and is never prefixed by the filename and line number.
159 
160 If \c NOLOGGING is defined during the build then this macro expands to
161 nothing.  If \c NDEBUG is defined during the build then it expands to a
162 call to Log::print.  Otherwise it expands to a call to Log::print,
163 which includes the filename and line number.
164 */
165 
166 /*!
167 \def LOGC(expr, arg)
168 Write to the log if and only if expr is true.  Because macros cannot accept
169 variable arguments, this should be invoked like so:
170 \code
171 LOGC(x == y, (CLOG_XXX "%d and %d are equal", x, y));
172 \endcode
173 In particular, notice the parentheses around everything after the boolean
174 expression.    Also note that there is no comma after the \c CLOG_XXX.
175 The \c XXX should be replaced by one of enumerants in \c Log::ELevel
176 without the leading \c k.  For example, \c CLOG_INFO.  The special
177 \c CLOG_PRINT level will not be filtered and is never prefixed by the
178 filename and line number.
179 
180 If \c NOLOGGING is defined during the build then this macro expands to
181 nothing.  If \c NDEBUG is not defined during the build then it expands
182 to a call to Log::print that prints the filename and line number,
183 otherwise it expands to a call that doesn't.
184 */
185 
186 #if defined(NOLOGGING)
187 #define LOG(_a1)
188 #define LOGC(_a1, _a2)
189 #define CLOG_TRACE
190 #elif defined(NDEBUG)
191 #define LOG(_a1)        CLOG->print _a1
192 #define LOGC(_a1, _a2)    if (_a1) CLOG->print _a2
193 #define CLOG_TRACE        NULL, 0,
194 #else
195 #define LOG(_a1)        CLOG->print _a1
196 #define LOGC(_a1, _a2)    if (_a1) CLOG->print _a2
197 #define CLOG_TRACE        __FILE__, __LINE__,
198 #endif
199 
200 // the CLOG_* defines are line and file plus %z and an octal number (060=0,
201 // 071=9), but the limitation is that once we run out of numbers at either
202 // end, then we resort to using non-numerical chars. this still works (since
203 // to deduce the number we subtract octal \060, so '/' is -1, and ':' is 10
204 
205 #define CLOG_PRINT        CLOG_TRACE "%z\057" // char is '/'
206 #define CLOG_CRIT        CLOG_TRACE "%z\060" // char is '0'
207 #define CLOG_ERR        CLOG_TRACE "%z\061"
208 #define CLOG_WARN        CLOG_TRACE "%z\062"
209 #define CLOG_NOTE        CLOG_TRACE "%z\063"
210 #define CLOG_INFO        CLOG_TRACE "%z\064"
211 #define CLOG_DEBUG        CLOG_TRACE "%z\065"
212 #define CLOG_DEBUG1        CLOG_TRACE "%z\066"
213 #define CLOG_DEBUG2        CLOG_TRACE "%z\067"
214 #define CLOG_DEBUG3        CLOG_TRACE "%z\070"
215 #define CLOG_DEBUG4        CLOG_TRACE "%z\071" // char is '9'
216 #define CLOG_DEBUG5        CLOG_TRACE "%z\072" // char is ':'
217