Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / camel / camel-debug.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
2  *
3  * Author: Michael Zucchi <notzed@ximian.com>
4  *
5  * Copyright 2004 Novell Inc. (www.novell.com)
6  *
7  * This program is free software; you can redistribute it and/or 
8  * modify it under the terms of version 2 of the GNU Lesser General Public 
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19  * USA
20  */
21
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <libedataserver/e-data-server-util.h>
28
29 #include "camel-debug.h"
30
31 int camel_verbose_debug;
32
33 static GHashTable *debug_table = NULL;
34
35 /**
36  * camel_debug_init:
37  * @void: 
38  * 
39  * Init camel debug.  Maintain legacy CAMEL_VERBOSE_DEBUG as well as the
40  * new CAMEL_DEBUG based environment variable interfaces.
41  *
42  * CAMEL_VERBOSE_DEBUG is set to a number to turn debug on.
43  *
44  * CAMEL_DEBUG is set to a comma separated list of modules to debug.
45  * The modules can contain module-specific specifiers after a ':', or
46  * just act as a wildcard for the module or even specifier.  e.g. 'imap'
47  * for imap debug, or 'imap:folder' for imap folder debug.  Additionaly,
48  * ':folder' can be used for a wildcard for any folder operations.
49  **/
50 void camel_debug_init(void)
51 {
52         char *d;
53
54         d = getenv("CAMEL_VERBOSE_DEBUG");
55         if (d)
56                 camel_verbose_debug = atoi(d);
57
58         d = g_strdup(getenv("CAMEL_DEBUG"));
59         if (d) {
60                 char *p;
61
62                 debug_table = g_hash_table_new(g_str_hash, g_str_equal);
63                 p = d;
64                 while (*p) {
65                         while (*p && *p != ',')
66                                 p++;
67                         if (*p)
68                                 *p++ = 0;
69                         g_hash_table_insert(debug_table, d, d);
70                         d = p;
71                 }
72
73                 if (g_hash_table_lookup(debug_table, "all"))
74                         camel_verbose_debug = 1;
75         }
76 }
77
78 /**
79  * camel_debug:
80  * @mode: 
81  * 
82  * Check to see if a debug mode is activated.  @mode takes one of two forms,
83  * a fully qualified 'module:target', or a wildcard 'module' name.  It
84  * returns a boolean to indicate if the module or module and target is
85  * currently activated for debug output.
86  * 
87  * Return value: 
88  **/
89 gboolean camel_debug(const char *mode)
90 {
91         if (camel_verbose_debug)
92                 return TRUE;
93
94         if (debug_table) {
95                 char *colon;
96                 char *fallback;
97
98                 if (g_hash_table_lookup(debug_table, mode))
99                         return TRUE;
100
101                 /* Check for fully qualified debug */
102                 colon = strchr(mode, ':');
103                 if (colon) {
104                         fallback = g_alloca(strlen(mode)+1);
105                         strcpy(fallback, mode);
106                         colon = (colon-mode) + fallback;
107                         /* Now check 'module[:*]' */
108                         *colon = 0;
109                         if (g_hash_table_lookup(debug_table, fallback))
110                                 return TRUE;
111                         /* Now check ':subsystem' */
112                         *colon = ':';
113                         if (g_hash_table_lookup(debug_table, colon))
114                                 return TRUE;            
115                 }
116         }
117
118         return FALSE;
119 }
120
121 static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER;
122 /**
123  * camel_debug_start:
124  * @mode:
125  * 
126  * Start debug output for a given mode, used to make sure debug output
127  * is output atomically and not interspersed with unrelated stuff.
128  *
129  * Return value: Returns true if mode is set, and in which case, you must
130  * call debug_end when finished any screen output.
131  **/
132 gboolean
133 camel_debug_start(const char *mode)
134 {
135         if (camel_debug(mode)) {
136                 pthread_mutex_lock(&debug_lock);
137                 printf("Thread %" G_GINT64_MODIFIER "x >\n", e_util_pthread_id(pthread_self()));
138                 return TRUE;
139         }
140
141         return FALSE;
142 }
143
144 /**
145  * camel_debug_end:
146  * 
147  * Call this when you're done with your debug output.  If and only if
148  * you called camel_debug_start, and if it returns TRUE.
149  **/
150 void
151 camel_debug_end(void)
152 {
153         printf("< %" G_GINT64_MODIFIER "x >\n", e_util_pthread_id(pthread_self()));
154         pthread_mutex_unlock(&debug_lock);
155 }
156
157 #if 0
158 #include <sys/debugreg.h>
159
160 static unsigned
161 i386_length_and_rw_bits (int len, enum target_hw_bp_type type)
162 {
163   unsigned rw;
164
165   switch (type)
166     {
167       case hw_execute:
168         rw = DR_RW_EXECUTE;
169         break;
170       case hw_write:
171         rw = DR_RW_WRITE;
172         break;
173       case hw_read:      /* x86 doesn't support data-read watchpoints */
174       case hw_access:
175         rw = DR_RW_READ;
176         break;
177 #if 0
178       case hw_io_access: /* not yet supported */
179         rw = DR_RW_IORW;
180         break;
181 #endif
182       default:
183         internal_error (__FILE__, __LINE__, "\
184 Invalid hw breakpoint type %d in i386_length_and_rw_bits.\n", (int)type);
185     }
186
187   switch (len)
188     {
189       case 1:
190         return (DR_LEN_1 | rw);
191       case 2:
192         return (DR_LEN_2 | rw);
193       case 4:
194         return (DR_LEN_4 | rw);
195       case 8:
196         if (TARGET_HAS_DR_LEN_8)
197           return (DR_LEN_8 | rw);
198       default:
199         internal_error (__FILE__, __LINE__, "\
200 Invalid hw breakpoint length %d in i386_length_and_rw_bits.\n", len);
201     }
202 }
203
204 #define I386_DR_SET_RW_LEN(i,rwlen) \
205   do { \
206     dr_control_mirror &= ~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i)));   \
207     dr_control_mirror |= ((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \
208   } while (0)
209
210 #define I386_DR_LOCAL_ENABLE(i) \
211   dr_control_mirror |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
212
213
214 #define set_dr(regnum, val) \
215                 __asm__("movl %0,%%db" #regnum  \
216                         : /* no output */ \
217                         :"r" (val))
218
219 #define get_dr(regnum, val) \
220                 __asm__("movl %%db" #regnum ", %0"  \
221                         :"=r" (val))
222
223 /* fine idea, but it doesn't work, crashes in get_dr :-/ */
224 void
225 camel_debug_hwatch(int wp, void *addr)
226 {
227      guint32 control, rw;
228
229      g_assert(wp <= DR_LASTADDR);
230      g_assert(sizeof(addr) == 4);
231
232      get_dr(7, control);
233      /* set watch mode + size */
234      rw = DR_RW_WRITE | DR_LEN_4;
235      control &= ~(((1<<DR_CONTROL_SIZE)-1) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE * wp));
236      control |= rw << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE*wp);
237      /* set watch enable */
238      control |=  ( 1<< (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * wp));
239      control |= DR_LOCAL_SLOWDOWN;
240      control &= ~DR_CONTROL_RESERVED;
241
242      switch (wp) {
243      case 0:
244              set_dr(0, addr);
245              break;
246      case 1:
247              set_dr(1, addr);
248              break;
249      case 2:
250              set_dr(2, addr);
251              break;
252      case 3:
253              set_dr(3, addr);
254              break;
255      }
256      set_dr(7, control);
257 }
258
259 #endif