Line data Source code
1 0 : /*
2 :
3 : OOLogging.h
4 : By Jens Ayton
5 :
6 : More flexible alternative to NSLog().
7 :
8 :
9 : Copyright (C) 2007-2013 Jens Ayton and contributors
10 :
11 : Permission is hereby granted, free of charge, to any person obtaining a copy
12 : of this software and associated documentation files (the "Software"), to deal
13 : in the Software without restriction, including without limitation the rights
14 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : copies of the Software, and to permit persons to whom the Software is
16 : furnished to do so, subject to the following conditions:
17 :
18 : The above copyright notice and this permission notice shall be included in all
19 : copies or substantial portions of the Software.
20 :
21 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : SOFTWARE.
28 :
29 : */
30 :
31 : #import "OOCocoa.h"
32 : #import "OOFunctionAttributes.h"
33 : #include <stdarg.h>
34 :
35 :
36 : #ifndef OOLOG_POISON_NSLOG
37 : #define OOLOG_POISON_NSLOG 0
38 : #endif
39 :
40 :
41 : #ifndef OOLOG_FUNCTION_NAME
42 : #if defined (__GNUC__) && __GNUC__ >= 2
43 : #define OOLOG_FUNCTION_NAME __FUNCTION__
44 : #elif 199901L <= __STDC_VERSION__
45 : #define OOLOG_FUNCTION_NAME __func__
46 : #else
47 : #define OOLOG_FUNCTION_NAME NULL
48 : #endif
49 : #endif
50 :
51 : #ifndef OOLOG_FILE_NAME
52 : #ifdef OOLOG_NO_FILE_NAME
53 : #define OOLOG_FILE_NAME NULL
54 : #else
55 : #define OOLOG_FILE_NAME __FILE__
56 : #endif
57 : #endif
58 :
59 :
60 : /* OOLOG_SHORT_CIRCUIT:
61 : If nonzero, the test of whether to display a message before evaluating the
62 : other parameters of the call. This saves time, but could cause weird bugs
63 : if the parameters involve calls with side effects.
64 : */
65 : #ifndef OOLOG_SHORT_CIRCUIT
66 : #define OOLOG_SHORT_CIRCUIT 1
67 : #endif
68 :
69 :
70 : /* General usage:
71 : OOLog(messageClass, format, parameters);
72 : is conceptually equivalent to:
73 : NSLog(format, parameters);
74 : except that it will do nothing if logging is disabled for messageClass.
75 :
76 : A message class is a hierarchical string, such as:
77 : @"all.script.debug"
78 :
79 : To determine whether scripting is enabled for this class, a setting for
80 : @"all.script.debug" is looked up in a settings table. If it is not found,
81 : @"all.script" is tried, followed by @"all".
82 :
83 : Message class display settings can be manipulated with
84 : OOLogSetDisplayMessagesInClass() and tested with
85 : OOLogWillDisplayMessagesInClass().
86 : */
87 : #if OOLOG_SHORT_CIRCUIT
88 0 : #define OOLog(class, format, ...) do { if (OOLogWillDisplayMessagesInClass(class)) { OOLogWithFunctionFileAndLine(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, format, ## __VA_ARGS__); }} while (0)
89 0 : #define OOLogWithArguments(class, format, args) do { if (OOLogWillDisplayMessagesInClass(class)) { OOLogWithFunctionFileAndLineAndArguments(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, format, args); }} while (0)
90 : #else
91 : #define OOLog(class, format, ...) OOLogWithFunctionFileAndLine(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, format, ## __VA_ARGS__)
92 : #define OOLogWithArguments(class, format, args) OOLogWithFunctionFileAndLineAndArguments(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, format, args)
93 : #endif
94 :
95 0 : BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass);
96 :
97 0 : void OOLogIndent(void);
98 0 : void OOLogOutdent(void);
99 :
100 : #if OOLOG_SHORT_CIRCUIT
101 0 : #define OOLogIndentIf(class) do { if (OOLogWillDisplayMessagesInClass(class)) OOLogIndent(); } while (0)
102 0 : #define OOLogOutdentIf(class) do { if (OOLogWillDisplayMessagesInClass(class)) OOLogOutdent(); } while (0)
103 : #else
104 : void OOLogIndentIf(NSString *inMessageClass);
105 : void OOLogOutdentIf(NSString *inMessageClass);
106 : #endif
107 :
108 :
109 0 : #define OOLOG_ERROR_PREFIX @"***** ERROR: "
110 0 : #define OOLOG_WARNING_PREFIX @"----- WARNING: "
111 :
112 0 : #define OOLogERR(class, format, ...) OOLogWithPrefix(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, OOLOG_ERROR_PREFIX ,format, ## __VA_ARGS__)
113 0 : #define OOLogWARN(class, format, ...) OOLogWithPrefix(class, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, OOLOG_WARNING_PREFIX, format, ## __VA_ARGS__)
114 :
115 :
116 : // Remember/restore indent levels, for cases where an exception may occur while indented.
117 0 : void OOLogPushIndent(void);
118 0 : void OOLogPopIndent(void);
119 :
120 0 : void OOLogWithPrefix(NSString *inMessageClass, const char *inFunction, const char *inFile, unsigned long inLine, NSString *inPrefix, NSString *inFormat, ...) OO_TAKES_FORMAT_STRING(6, 7);
121 0 : void OOLogWithFunctionFileAndLine(NSString *inMessageClass, const char *inFunction, const char *inFile, unsigned long inLine, NSString *inFormat, ...) OO_TAKES_FORMAT_STRING(5, 6);
122 0 : void OOLogWithFunctionFileAndLineAndArguments(NSString *inMessageClass, const char *inFunction, const char *inFile, unsigned long inLine, NSString *inFormat, va_list inArguments) OO_TAKES_FORMAT_STRING(5, 0);
123 :
124 : // OOLogGenericParameterError(): general parameter error message, "***** $function_name: bad parameters. (This is an internal programming error, please report it.)"
125 0 : #define OOLogGenericParameterError() OOLogGenericParameterErrorForFunction(OOLOG_FUNCTION_NAME)
126 0 : void OOLogGenericParameterErrorForFunction(const char *inFunction);
127 :
128 : // OOLogGenericSubclassResponsibility(): general subclass responsibility message, "***** $function_name is a subclass responsibility. (This is an internal programming error, please report it.)"
129 0 : #define OOLogGenericSubclassResponsibility() OOLogGenericSubclassResponsibilityForFunction(OOLOG_FUNCTION_NAME)
130 0 : void OOLogGenericSubclassResponsibilityForFunction(const char *inFunction);
131 :
132 :
133 : #if OOLOG_POISON_NSLOG
134 : #pragma GCC poison NSLog // Use OOLog instead
135 : #elif !OOLOG_NO_HIJACK_NSLOG
136 : // Hijack NSLog. Buahahahaha.
137 0 : #define NSLog(format, ...) OOLog(kOOLogUnconvertedNSLog, format, ## __VA_ARGS__)
138 0 : #define NSLogv(format, args) OOLogWithArguments(kOOLogUnconvertedNSLog, format, args)
139 : #endif
140 :
141 :
142 : // OODebugLog() is only included in debug builds.
143 : #if OO_DEBUG
144 : #define OODebugLog OOLog
145 : #else
146 0 : #define OODebugLog(class, format, ...) do { (void)class; if (0) (void)format; } while (0)
147 : #endif
148 :
149 :
150 : // OOExtraLog() is included in debug and test-release builds, but not deployment builds.
151 : #ifndef NDEBUG
152 0 : #define OOExtraLog OOLog
153 : #else
154 : #define OOExtraLog(class, format, ...) do { (void)class; if (0) (void)format; } while (0)
155 : #endif
156 :
157 :
158 : // *** Predefined message classes.
159 : /* These are general coding error types. Generally a subclass should be used
160 : for each instance -- for instance, -[Entity warnAboutHostiles] uses
161 : @"general.error.subclassResponsibility.Entity-warnAboutHostiles".
162 : */
163 :
164 0 : extern NSString * const kOOLogSubclassResponsibility; // @"general.error.subclassResponsibility"
165 0 : extern NSString * const kOOLogParameterError; // @"general.error.parameterError"
166 0 : extern NSString * const kOOLogDeprecatedMethod; // @"general.error.deprecatedMethod"
167 0 : extern NSString * const kOOLogAllocationFailure; // @"general.error.allocationFailure"
168 0 : extern NSString * const kOOLogInconsistentState; // @"general.error.inconsistentState"
169 0 : extern NSString * const kOOLogException; // @"exception"
170 :
171 0 : extern NSString * const kOOLogFileNotFound; // @"files.notFound"
172 0 : extern NSString * const kOOLogFileNotLoaded; // @"files.notLoaded"
173 :
174 0 : extern NSString * const kOOLogOpenGLError; // @"rendering.opengl.error"
175 :
176 : // Don't use. However, #defining it as @"unclassified.module" can be used as a stepping stone to OOLog support.
177 0 : extern NSString * const kOOLogUnconvertedNSLog; // @"unclassified"
|