1 /* $Id: log.h,v 1.2 2009/08/30 13:23:39 fredette Exp $ */
2 
3 /* tme/log.h - public header file for logging: */
4 
5 /*
6  * Copyright (c) 2003 Matt Fredette
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Matt Fredette.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifndef _TME_LOG_H
37 #define _TME_LOG_H
38 
39 #include <tme/common.h>
40 _TME_RCSID("$Id: log.h,v 1.2 2009/08/30 13:23:39 fredette Exp $");
41 
42 /* includes: */
43 
44 /* macros: */
45 
46 /* if TME_NO_LOG has been specified, shut down all logging except for
47    level zero: */
48 #ifdef TME_NO_LOG
49 #undef TME_LOG_LEVEL_MAX
50 #define TME_LOG_LEVEL_MAX	(0)
51 #endif /* TME_NO_LOG */
52 
53 /* non-ancient GCCs can check the arguments to our printf-like
54    functions: */
55 #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
56 #define __tme_printf_attribute __attribute__ ((format (printf, 2, 3)))
57 #else
58 #define __tme_printf_attribute
59 #endif
60 
61 /* log modes: */
62 #define TME_LOG_MODE_TEXT		(0)
63 #define TME_LOG_MODE_BINARY		(1)
64 
65 /* maximum message sizes: */
66 #define TME_LOG_MESSAGE_SIZE_MAX_BINARY	(1024)
67 
68 /* a logging handle: */
69 struct tme_log_handle {
70 
71   /* the maximum log level output: */
72   unsigned long tme_log_handle_level_max;
73 
74   /* the log level of this message: */
75   unsigned long tme_log_handle_level;
76 
77   /* the log message: */
78   char *tme_log_handle_message;
79   unsigned long tme_log_handle_message_size;
80 
81   /* any errno with this message: */
82   int tme_log_handle_errno;
83 
84   /* the interface's private data: */
85   void *tme_log_handle_private;
86 
87   /* the interface's log output function: */
88   void (*tme_log_handle_output) _TME_P((struct tme_log_handle *));
89 
90   /* the mode of this handle: */
91   unsigned int tme_log_handle_mode;
92 
93   /* a format hash: */
94   struct _tme_hash *tme_log_handle_hash_format;
95 };
96 
97 /* prototypes and macros: */
98 
99 /* this starts logging a message: */
100 #ifdef TME_LOG_LEVEL_MAX
101 #define _tme_log_start(handle, level)			\
102   ((level) <= TME_LOG_LEVEL_MAX				\
103     && (level) <= (handle)->tme_log_handle_level_max)
104 #else  /* !TME_LOG_LEVEL_MAX */
105 #define _tme_log_start(handle, level)			\
106   ((level) <= (handle)->tme_log_handle_level_max)
107 #endif /* !TME_LOG_LEVEL_MAX */
108 #define tme_log_start(handle, level, rc)		\
109 do {							\
110   if (_tme_log_start(handle, level)) {			\
111     (handle)->tme_log_handle_level = (level);		\
112     (handle)->tme_log_handle_errno = (rc);		\
113     do
114 
115 /* this logs (part of) the body of a message: */
116 void tme_log_part _TME_P((struct tme_log_handle *, _tme_const char *, ...)) __tme_printf_attribute;
117 
118 /* this finishes logging a message: */
119 #define tme_log_finish(handle)				\
120     while (/* CONSTCOND */ 0);				\
121     (*(handle)->tme_log_handle_output)(handle);		\
122   }							\
123 } while (/* CONSTCOND */ 0)
124 
125 /* this handles all of the logging of a message: */
126 #define tme_log(handle, level, rc, x)			\
127 do {							\
128   tme_log_start(handle, level, rc) {			\
129     tme_log_part x;					\
130   } tme_log_finish(handle);				\
131 } while (/* CONSTCOND */ 0)
132 
133 /* these collect output: */
134 void tme_output_append_raw _TME_P((char **, const char *, unsigned int));
135 void tme_output_prepend_raw _TME_P((char **, const char *, unsigned int));
136 void tme_output_append _TME_P((char **, const char *, ...)) __tme_printf_attribute;
137 void tme_output_prepend _TME_P((char **, const char *, ...)) __tme_printf_attribute;
138 void tme_output_append_error _TME_P((char **, const char *, ...)) __tme_printf_attribute;
139 void tme_output_prepend_error _TME_P((char **, const char *, ...)) __tme_printf_attribute;
140 
141 #endif /* !_TME_LOG_H */
142