1 /** \file gphoto2-port-log.h
2  *
3  * Copyright 2001 Lutz Mueller <lutz@users.sf.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  */
20 
21 #ifndef __GPHOTO2_PORT_LOG_H__
22 #define __GPHOTO2_PORT_LOG_H__
23 
24 #include <stdarg.h>
25 
26 /**
27  * \brief Logging level
28  * Specifies the logging severity level.
29  */
30 typedef enum {
31 	GP_LOG_ERROR = 0,	/**< \brief Log message is an error information. */
32 	GP_LOG_VERBOSE = 1,	/**< \brief Log message is an verbose debug information. */
33 	GP_LOG_DEBUG = 2,	/**< \brief Log message is an debug information. */
34 	GP_LOG_DATA = 3		/**< \brief Log message is a data hex dump. */
35 } GPLogLevel;
36 
37 /**
38  * GP_LOG_ALL:
39  *
40  * Used by frontends if they want to be sure their
41  * callback function receives all messages. Defined
42  * as the highest debug level. Can make frontend code
43  * more understandable and extension of log levels
44  * easier.
45  **/
46 #define GP_LOG_ALL GP_LOG_DATA
47 
48 /**
49  * \brief Logging function hook
50  *
51  * This is the function frontends can use to receive logging information
52  * from the libgphoto2 framework. It is set using gp_log_add_func() and
53  * removed using gp_log_remove_func() and will then receive the logging
54  * messages of the level specified.
55  *
56  * \param level the log level of the passed message, as set by the camera driver or libgphoto2
57  * \param domain the logging domain as set by the camera driver, or libgphoto2 function
58  * \param str the logmessage, without linefeed
59  * \param data the caller private data that was passed to gp_log_add_func()
60  */
61 typedef void (* GPLogFunc) (GPLogLevel level, const char *domain, const char *str, void *data);
62 
63 #ifndef DISABLE_DEBUGGING
64 
65 int  gp_log_add_func    (GPLogLevel level, GPLogFunc func, void *data);
66 int  gp_log_remove_func (int id);
67 
68 /* Logging */
69 void gp_log      (GPLogLevel level, const char *domain,
70 		  const char *format, ...)
71 #ifdef __GNUC__
72 	__attribute__((__format__(printf,3,4)))
73 #endif
74 ;
75 void gp_log_with_source_location(
76 		  GPLogLevel level, const char *file, int line, const char *func,
77 		  const char *format, ...)
78 #ifdef __GNUC__
79 	__attribute__((__format__(printf,5,6)))
80 #endif
81 ;
82 void gp_logv     (GPLogLevel level, const char *domain, const char *format,
83 		  va_list args)
84 #ifdef __GNUC__
85 	__attribute__((__format__(printf,3,0)))
86 #endif
87 ;
88 void gp_log_data (const char *domain, const char *data, unsigned int size,
89 		  const char *format, ...)
90 #ifdef __GNUC__
91 __attribute__((__format__(printf,4,5)))
92 #endif
93 ;
94 
95 /*
96  * GP_DEBUG:
97  * msg: message to log
98  * params: params to message
99  *
100  * Logs message at log level #GP_LOG_DEBUG by calling #gp_log() with
101  * an automatically generated domain
102  * You have to define GP_MODULE as "mymod" for your module
103  * mymod before using #GP_DEBUG().
104  */
105 
106 #ifdef _GPHOTO2_INTERNAL_CODE
107 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
108 #define GP_DEBUG(...) \
109         gp_log(GP_LOG_DEBUG, GP_MODULE "/" __FILE__, __VA_ARGS__)
110 
111 /*
112  * GP_LOG_D/E:
113  * simple helper macros for convenient and consistent logging of error
114  * and debug messages including information about the source location.
115  */
116 #define GP_LOG_D(...) gp_log(GP_LOG_DEBUG, __func__, __VA_ARGS__)
117 #define GP_LOG_E(...) gp_log_with_source_location(GP_LOG_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__)
118 #define GP_LOG_DATA(DATA, SIZE, MSG, ...) gp_log_data(__func__, DATA, SIZE, MSG, ##__VA_ARGS__)
119 
120 #elif defined(__GNUC__) &&  __GNUC__ >= 2
121 #define GP_DEBUG(msg, params...) \
122         gp_log(GP_LOG_DEBUG, GP_MODULE "/" __FILE__, msg, ##params)
123 /*
124  * GP_LOG_D/E:
125  * simple helper macros for convenient and consistent logging of error
126  * and debug messages including information about the source location.
127  */
128 #define GP_LOG_D(...) gp_log(GP_LOG_DEBUG, __func__, __VA_ARGS__)
129 #define GP_LOG_E(...) gp_log_with_source_location(GP_LOG_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__)
130 #define GP_LOG_DATA(DATA, SIZE, MSG, ...) gp_log_data(__func__, DATA, SIZE, MSG, ##__VA_ARGS__)
131 
132 #else
133 # ifdef __GNUC__
134 #  warning Disabling GP_DEBUG because variadic macros are not allowed
135 # endif
136 #define GP_DEBUG (void)
137 #define GP_LOG_D(...) /* no-op */
138 #define GP_LOG_E(...) /* no-op */
139 #define GP_LOG_DATA(DATA, SIZE, ...) /* no-op */
140 #endif
141 #endif /* _GPHOTO2_INTERNAL_CODE */
142 
143 #else /* DISABLE_DEBUGGING */
144 
145 /* Stub these functions out if debugging is disabled */
146 #define gp_log_add_func(level, func, data) (0)
147 #define gp_log_remove_func(id) (0)
148 #define gp_log(level, domain, format, args...) /**/
149 #define gp_log_with_source_location(level, file, line, func, format, ...)
150 #define gp_logv(level, domain, format, args) /**/
151 #define gp_log_data(domain, data, size) /**/
152 
153 #ifdef _GPHOTO2_INTERNAL_CODE
154 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
155 #define GP_DEBUG(...) /* no-op */
156 #define GP_LOG_D(...) /* no-op */
157 #define GP_LOG_E(...) /* no-op */
158 #define GP_LOG_DATA(DATA, SIZE, ...) /* no-op */
159 
160 #elif defined(__GNUC__)
161 #define GP_DEBUG(msg, params...) /* no-op */
162 #define GP_LOG_D(...) /* no-op */
163 #define GP_LOG_E(...) /* no-op */
164 #define GP_LOG_DATA(DATA, SIZE, ...) /* no-op */
165 #else
166 #define GP_DEBUG (void)
167 #define GP_LOG_D (void /* no-op */
168 #define GP_LOG_E (void) /* no-op */
169 #define GP_LOG_DATA(void) /* no-op */
170 #endif
171 #endif /* _GPHOTO2_INTERNAL_CODE */
172 
173 #endif /* DISABLE_DEBUGGING */
174 
175 #ifdef _GPHOTO2_INTERNAL_CODE
176 
177   typedef struct StringFlagItem {
178     char *str;
179     unsigned int flag;
180   } StringFlagItem;
181 
182   typedef void (*string_item_func) (const char *str, void *data);
183 
184   const char *
185   gpi_enum_to_string(const unsigned int _enum,
186 		     const StringFlagItem *map);
187 
188   int
189   gpi_string_to_enum(const char *str,
190 		     unsigned int *result,
191 		     const StringFlagItem *map);
192 
193   void
194   gpi_flags_to_string_list(const unsigned int flags,
195 			   const StringFlagItem *map,
196 			   string_item_func func, void *data);
197 
198   int
199   gpi_string_or_to_flags(const char *str,
200 			 unsigned int *flags,
201 			 const StringFlagItem *map);
202 
203   unsigned int
204   gpi_string_to_flag(const char *str,
205 		     const StringFlagItem *map);
206 
207   unsigned int
208   gpi_string_list_to_flags(const char *str[],
209 			   const StringFlagItem *map);
210 
211   /* Allocates a sufficiently large buffer and interpolates the format
212    * string with the proveded va_list args. The returned memory has to
213    * be freed by the caller. */
214   char*
215   gpi_vsnprintf (const char* format, va_list args);
216 
217 #define C_MEM(MEM) do {\
218 	if ((MEM) == NULL) {\
219 		GP_LOG_E ("Out of memory: '%s' failed.", #MEM);\
220 		return GP_ERROR_NO_MEMORY;\
221 	}\
222 } while(0)
223 
224 #define C_PARAMS(PARAMS) do {\
225 	if (!(PARAMS)) {\
226 		GP_LOG_E ("Invalid parameters: '%s' is NULL/FALSE.", #PARAMS);\
227 		return GP_ERROR_BAD_PARAMETERS;\
228 	}\
229 } while(0)
230 
231 #define C_PARAMS_MSG(PARAMS, MSG, ...) do {\
232 	if (!(PARAMS)) {\
233 		GP_LOG_E ("Invalid parameters: " #MSG " ('%s' is NULL/FALSE.)", ##__VA_ARGS__, #PARAMS);\
234 		return GP_ERROR_BAD_PARAMETERS;\
235 	}\
236 } while(0)
237 
238 #endif /* _GPHOTO2_INTERNAL_CODE */
239 
240 #endif /* __GPHOTO2_PORT_LOG_H__ */
241