Fix:Core:Fixed win32 build
[navit-package] / navit / debug.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <signal.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <sys/time.h>
27 #include <glib.h>
28 #include "file.h"
29 #include "item.h"
30 #include "debug.h"
31
32 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
33 #include <windows.h>
34 #include <windowsx.h>
35 #endif
36
37 int debug_level=0;
38 int segv_level=0;
39 int timestamp_prefix=0;
40
41 static int dummy;
42 static GHashTable *debug_hash;
43 static const char *gdb_program;
44
45 static FILE *debug_fp;
46
47 #if defined(_WIN32) || defined(__CEGCC__)
48
49 static void sigsegv(int sig)
50 {
51 }
52
53 #else
54 #include <unistd.h>
55 static void sigsegv(int sig)
56 {
57         char buffer[256];
58         if (segv_level > 1)
59                 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
60         else
61                 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
62         system(buffer);
63         exit(1);
64 }
65 #endif
66
67 void
68 debug_init(const char *program_name)
69 {
70         gdb_program=program_name;
71         signal(SIGSEGV, sigsegv);
72         debug_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
73         debug_fp = stderr;
74 }
75
76
77 static void
78 debug_update_level(gpointer key, gpointer value, gpointer user_data)
79 {
80         if (debug_level < (int) value)
81                 debug_level=(int) value;
82 }
83
84 void
85 debug_level_set(const char *name, int level)
86 {
87         if (!strcmp(name, "segv")) {
88                 segv_level=level;
89                 if (segv_level)
90                         signal(SIGSEGV, sigsegv);
91                 else
92                         signal(SIGSEGV, NULL);
93         } else if (!strcmp(name, "timestamps")) {
94                 timestamp_prefix=level;
95         } else {
96                 debug_level=0;
97                 g_hash_table_insert(debug_hash, g_strdup(name), (gpointer) level);
98                 g_hash_table_foreach(debug_hash, debug_update_level, NULL);
99         }
100 }
101
102 struct debug *
103 debug_new(struct attr *parent, struct attr **attrs)
104 {
105         struct attr *name,*level;
106         name=attr_search(attrs, NULL, attr_name);
107         level=attr_search(attrs, NULL, attr_level);
108         if (!name || !level)
109                 return NULL;
110         debug_level_set(name->u.str, level->u.num);
111         return (struct debug *)&dummy;
112 }
113
114
115 int
116 debug_level_get(const char *name)
117 {
118         if (!debug_hash)
119                 return 0;
120         return (int)(g_hash_table_lookup(debug_hash, name));
121 }
122
123 static void debug_timestamp(FILE *fp)
124 {
125         struct timeval tv;
126
127         if (gettimeofday(&tv, NULL) == -1)
128                 return;
129         /* Timestamps are UTC */
130         fprintf(fp,
131                 "%02d:%02d:%02d.%03d|",
132                 (int)(tv.tv_sec/3600)%24,
133                 (int)(tv.tv_sec/60)%60,
134                 (int)tv.tv_sec % 60,
135                 (int)tv.tv_usec/1000);
136 }
137
138 void
139 debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
140 {
141 #ifdef HAVE_API_WIN32_CE
142         char buffer[4096];
143 #else
144         char buffer[mlen+flen+3];
145 #endif
146         FILE *fp=debug_fp;
147
148         sprintf(buffer, "%s:%s", module, function);
149         if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) {
150 #ifndef DEBUG_WIN32_CE_MESSAGEBOX
151                 if (! fp)
152                         fp = stderr;
153                 if (timestamp_prefix)
154                         debug_timestamp(fp);
155                 if (prefix)
156                         fprintf(fp,"%s:",buffer);
157                 vfprintf(fp,fmt, ap);
158                 fflush(fp);
159 #else
160         wchar_t muni[4096];
161         char xbuffer[4096];
162         int len=0;
163         if (prefix) {
164                 strcpy(xbuffer,buffer);
165                 len=strlen(buffer);
166                 xbuffer[len++]=':';
167         }
168         vsprintf(xbuffer+len,fmt,ap);
169         mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
170         MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
171 #endif
172         }
173 }
174
175 void
176 debug_printf(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
177 {
178         va_list ap;
179         va_start(ap, fmt);
180         debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
181         va_end(ap);
182 }
183
184 void
185 debug_assert_fail(char *module, const int mlen,const char *function, const int flen, char *file, int line, char *expr)
186 {
187         debug_printf(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr);
188         abort();
189 }
190
191 void
192 debug_destroy(void)
193 {
194         if (!debug_fp)
195                 return;
196         if (debug_fp == stderr || debug_fp == stdout)
197                 return;
198         fclose(debug_fp);
199         debug_fp = NULL;
200 }
201
202 void debug_set_logfile(const char *path)
203 {
204         FILE *fp;
205         fp = fopen(path, "a");
206         if (fp) {
207                 debug_destroy();
208                 debug_fp = fp;
209                 fprintf(debug_fp, "Navit log started\n");
210                 fflush(debug_fp);
211         }
212 }