FIX: windows build process: enable png 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 "config.h"
29 #include "file.h"
30 #include "item.h"
31 #include "debug.h"
32
33 #ifdef HAVE_API_ANDROID
34 #include <android/log.h>
35 #endif
36
37 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
38 #include <windows.h>
39 #include <windowsx.h>
40 #endif
41
42 int debug_level=0;
43 int segv_level=0;
44 int timestamp_prefix=0;
45
46 static int dummy;
47 static GHashTable *debug_hash;
48 static const char *gdb_program;
49
50 static FILE *debug_fp;
51
52 #if defined(_WIN32) || defined(__CEGCC__)
53
54 static void sigsegv(int sig)
55 {
56 }
57
58 #else
59 #include <unistd.h>
60 static void sigsegv(int sig)
61 {
62         char buffer[256];
63         if (segv_level > 1)
64                 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
65         else
66                 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
67         system(buffer);
68         exit(1);
69 }
70 #endif
71
72 void
73 debug_init(const char *program_name)
74 {
75         gdb_program=program_name;
76         signal(SIGSEGV, sigsegv);
77         debug_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
78         debug_fp = stderr;
79 }
80
81
82 static void
83 debug_update_level(gpointer key, gpointer value, gpointer user_data)
84 {
85         if (debug_level < GPOINTER_TO_INT(value))
86                 debug_level = GPOINTER_TO_INT(value);
87 }
88
89 void
90 debug_level_set(const char *name, gint level)
91 {
92         if (!strcmp(name, "segv")) {
93                 segv_level=level;
94                 if (segv_level)
95                         signal(SIGSEGV, sigsegv);
96                 else
97                         signal(SIGSEGV, NULL);
98         } else if (!strcmp(name, "timestamps")) {
99                 timestamp_prefix=level;
100         } else {
101                 debug_level=0;
102                 g_hash_table_insert(debug_hash, g_strdup(name), GINT_TO_POINTER(level));
103                 g_hash_table_foreach(debug_hash, debug_update_level, NULL);
104         }
105 }
106
107 struct debug *
108 debug_new(struct attr *parent, struct attr **attrs)
109 {
110         struct attr *name,*level;
111         name=attr_search(attrs, NULL, attr_name);
112         level=attr_search(attrs, NULL, attr_level);
113         if (!name || !level)
114                 return NULL;
115         debug_level_set(name->u.str, level->u.num);
116         return (struct debug *)&dummy;
117 }
118
119
120 int
121 debug_level_get(const char *name)
122 {
123         if (!debug_hash)
124                 return 0;
125         return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name));
126 }
127
128 static void debug_timestamp(FILE *fp)
129 {
130         struct timeval tv;
131
132         if (gettimeofday(&tv, NULL) == -1)
133                 return;
134         /* Timestamps are UTC */
135         fprintf(fp,
136                 "%02d:%02d:%02d.%03d|",
137                 (int)(tv.tv_sec/3600)%24,
138                 (int)(tv.tv_sec/60)%60,
139                 (int)tv.tv_sec % 60,
140                 (int)tv.tv_usec/1000);
141 }
142
143 void
144 debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
145 {
146 #ifdef HAVE_API_WIN32_CE
147         char buffer[4096];
148 #else
149         char buffer[mlen+flen+3];
150 #endif
151         FILE *fp=debug_fp;
152
153         sprintf(buffer, "%s:%s", module, function);
154         if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) {
155 #if defined(DEBUG_WIN32_CE_MESSAGEBOX) || defined(HAVE_API_ANDROID)
156                 char xbuffer[4096];
157                 wchar_t muni[4096];
158                 int len=0;
159                 if (prefix) {
160                         strcpy(xbuffer,buffer);
161                         len=strlen(buffer);
162                         xbuffer[len++]=':';
163                 }
164                 vsprintf(xbuffer+len,fmt,ap);
165 #endif
166 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
167                 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
168                 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
169 #else
170 #ifdef HAVE_API_ANDROID
171                 __android_log_print(ANDROID_LOG_ERROR,"navit", "%s", xbuffer);
172 #else
173                 if (! fp)
174                         fp = stderr;
175                 if (timestamp_prefix)
176                         debug_timestamp(fp);
177                 if (prefix)
178                         fprintf(fp,"%s:",buffer);
179                 vfprintf(fp,fmt, ap);
180                 fflush(fp);
181 #endif
182 #endif
183         }
184 }
185
186 void
187 debug_printf(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
188 {
189         va_list ap;
190         va_start(ap, fmt);
191         debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
192         va_end(ap);
193 }
194
195 void
196 debug_assert_fail(char *module, const int mlen,const char *function, const int flen, char *file, int line, char *expr)
197 {
198         debug_printf(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr);
199         abort();
200 }
201
202 void
203 debug_destroy(void)
204 {
205         if (!debug_fp)
206                 return;
207         if (debug_fp == stderr || debug_fp == stdout)
208                 return;
209         fclose(debug_fp);
210         debug_fp = NULL;
211 }
212
213 void debug_set_logfile(const char *path)
214 {
215         FILE *fp;
216         fp = fopen(path, "a");
217         if (fp) {
218                 debug_destroy();
219                 debug_fp = fp;
220                 fprintf(debug_fp, "Navit log started\n");
221                 fflush(debug_fp);
222         }
223 }