Bug fix: Additional debug features
[geeqie.git] / src / debug.c
1 /*
2  * Copyright (C) 2008 - 2016 The Geeqie Team
3  *
4  * Authors: Vladimir Nadvornik, Laurent Monin
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "main.h"
22 #include "debug.h"
23
24 #include "logwindow.h"
25 #include "ui_fileops.h"
26
27 #include <glib/gprintf.h>
28 #include <regex.h>
29
30 /*
31  * Logging functions
32  */
33 static gchar *regexp = NULL;
34
35 static gboolean log_msg_cb(gpointer data)
36 {
37         gchar *buf = data;
38         log_window_append(buf, LOG_MSG);
39         g_free(buf);
40         return FALSE;
41 }
42
43 static gboolean log_normal_cb(gpointer data)
44 {
45         gchar *buf = data;
46         log_window_append(buf, LOG_NORMAL);
47         g_free(buf);
48         return FALSE;
49 }
50
51 void log_domain_print_message(const gchar *domain, gchar *buf)
52 {
53         gchar *buf_nl;
54         regex_t regex;
55         gint ret_comp, ret_exec;
56
57         buf_nl = g_strconcat(buf, "\n", NULL);
58
59         if (regexp && command_line)
60                 {
61                         ret_comp = regcomp(&regex, regexp, 0);
62                         if (!ret_comp)
63                                 {
64                                 ret_exec = regexec(&regex, buf_nl, 0, NULL, 0);
65
66                                 if (!ret_exec)
67                                         {
68                                         print_term(buf_nl);
69                                         if (strcmp(domain, DOMAIN_INFO) == 0)
70                                                 g_idle_add(log_normal_cb, buf_nl);
71                                         else
72                                                 g_idle_add(log_msg_cb, buf_nl);
73                                         }
74                                 regfree(&regex);
75                                 }
76                 }
77         else
78                 {
79                 print_term(buf_nl);
80                 if (strcmp(domain, DOMAIN_INFO) == 0)
81                         g_idle_add(log_normal_cb, buf_nl);
82                 else
83                         g_idle_add(log_msg_cb, buf_nl);
84                 }
85         g_free(buf);
86 }
87
88 void log_domain_print_debug(const gchar *domain, const gchar *file_name,
89                                                                         int line_number, const gchar *format, ...)
90 {
91         va_list ap;
92         gchar *message;
93         gchar *location;
94         gchar *buf;
95
96         va_start(ap, format);
97         message = g_strdup_vprintf(format, ap);
98         va_end(ap);
99
100         location = g_strdup_printf("%s:%d:", file_name, line_number);
101         buf = g_strconcat(location, message, NULL);
102         log_domain_print_message(domain,buf);
103         g_free(location);
104         g_free(message);
105 }
106
107 void log_domain_printf(const gchar *domain, const gchar *format, ...)
108 {
109         va_list ap;
110         gchar *buf;
111
112         va_start(ap, format);
113         buf = g_strdup_vprintf(format, ap);
114         va_end(ap);
115
116         log_domain_print_message(domain, buf);
117 }
118
119 /*
120  * Debugging only functions
121  */
122
123 #ifdef DEBUG
124
125 static gint debug_level = DEBUG_LEVEL_MIN;
126
127
128 gint get_debug_level(void)
129 {
130         return debug_level;
131 }
132
133 void set_debug_level(gint new_level)
134 {
135         debug_level = CLAMP(new_level, DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX);
136 }
137
138 void debug_level_add(gint delta)
139 {
140         set_debug_level(debug_level + delta);
141 }
142
143 gint required_debug_level(gint level)
144 {
145         return (debug_level >= level);
146 }
147
148 static gint timeval_delta(struct timeval *result, struct timeval *x, struct timeval *y)
149 {
150         if (x->tv_usec < y->tv_usec)
151                 {
152                 gint nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
153                 y->tv_usec -= 1000000 * nsec;
154                 y->tv_sec += nsec;
155                 }
156
157         if (x->tv_usec - y->tv_usec > 1000000)
158                 {
159                 gint nsec = (x->tv_usec - y->tv_usec) / 1000000;
160                 y->tv_usec += 1000000 * nsec;
161                 y->tv_sec -= nsec;
162         }
163
164         result->tv_sec = x->tv_sec - y->tv_sec;
165         result->tv_usec = x->tv_usec - y->tv_usec;
166
167         return x->tv_sec < y->tv_sec;
168 }
169
170 const gchar *get_exec_time(void)
171 {
172         static gchar timestr[30];
173         static struct timeval start_tv = {0, 0};
174         static struct timeval previous = {0, 0};
175         static gint started = 0;
176
177         struct timeval tv = {0, 0};
178         static struct timeval delta = {0, 0};
179
180         gettimeofday(&tv, NULL);
181
182         if (start_tv.tv_sec == 0) start_tv = tv;
183
184         tv.tv_sec -= start_tv.tv_sec;
185         if (tv.tv_usec >= start_tv.tv_usec)
186                 tv.tv_usec -= start_tv.tv_usec;
187         else
188                 {
189                 tv.tv_usec += 1000000 - start_tv.tv_usec;
190                 tv.tv_sec -= 1;
191                 }
192
193         if (started) timeval_delta(&delta, &tv, &previous);
194
195         previous = tv;
196         started = 1;
197
198         g_snprintf(timestr, sizeof(timestr), "%5d.%06d (+%05d.%06d)", (gint)tv.tv_sec, (gint)tv.tv_usec, (gint)delta.tv_sec, (gint)delta.tv_usec);
199
200         return timestr;
201 }
202
203 void init_exec_time(void)
204 {
205         get_exec_time();
206 }
207
208 void set_regexp(gchar *cmd_regexp)
209 {
210         regexp = g_strdup(cmd_regexp);
211 }
212
213 gchar *get_regexp(void)
214 {
215         return g_strdup(regexp);
216 }
217
218 #endif /* DEBUG */
219 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */