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 void set_regexp(gchar *cmd_regexp)
36 {
37         regexp = g_strdup(cmd_regexp);
38 }
39
40 gchar *get_regexp()
41 {
42         return g_strdup(regexp);
43 }
44
45 static gboolean log_msg_cb(gpointer data)
46 {
47         gchar *buf = data;
48         log_window_append(buf, LOG_MSG);
49         g_free(buf);
50         return FALSE;
51 }
52
53 static gboolean log_normal_cb(gpointer data)
54 {
55         gchar *buf = data;
56         log_window_append(buf, LOG_NORMAL);
57         g_free(buf);
58         return FALSE;
59 }
60
61 void log_domain_printf(const gchar *domain, const gchar *format, ...)
62 {
63         va_list ap;
64         gchar *buf;
65         regex_t regex;
66         gint ret_comp, ret_exec;
67         gchar *filtered_buf;
68
69         va_start(ap, format);
70         buf = g_strdup_vprintf(format, ap);
71         va_end(ap);
72
73         if (regexp && command_line && buf)
74                 {
75                 if (g_strcmp0(buf,"\n"))
76                         {
77                         ret_comp = regcomp(&regex, regexp, 0);
78                         if (!ret_comp)
79                                 {
80                                 ret_exec = regexec(&regex, buf, 0, NULL, 0);
81
82                                 filtered_buf = g_strconcat(buf, "\n", NULL);
83                                 if (!ret_exec)
84                                         {
85                                         print_term(filtered_buf);
86                                         if (strcmp(domain, DOMAIN_INFO) == 0)
87                                                 g_idle_add(log_normal_cb, filtered_buf);
88                                         else
89                                                 g_idle_add(log_msg_cb, filtered_buf);
90                                         }
91                                 regfree(&regex);
92                                 }
93                         }
94                 }
95         else
96                 {
97                 print_term(buf);
98                 if (strcmp(domain, DOMAIN_INFO) == 0)
99                         g_idle_add(log_normal_cb, buf);
100                 else
101                         g_idle_add(log_msg_cb, buf);
102                 }
103 }
104
105 /*
106  * Debugging only functions
107  */
108
109 #ifdef DEBUG
110
111 static gint debug_level = DEBUG_LEVEL_MIN;
112
113
114 gint get_debug_level(void)
115 {
116         return debug_level;
117 }
118
119 void set_debug_level(gint new_level)
120 {
121         debug_level = CLAMP(new_level, DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX);
122 }
123
124 void debug_level_add(gint delta)
125 {
126         set_debug_level(debug_level + delta);
127 }
128
129 gint required_debug_level(gint level)
130 {
131         return (debug_level >= level);
132 }
133
134 static gint timeval_delta(struct timeval *result, struct timeval *x, struct timeval *y)
135 {
136         if (x->tv_usec < y->tv_usec)
137                 {
138                 gint nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
139                 y->tv_usec -= 1000000 * nsec;
140                 y->tv_sec += nsec;
141                 }
142
143         if (x->tv_usec - y->tv_usec > 1000000)
144                 {
145                 gint nsec = (x->tv_usec - y->tv_usec) / 1000000;
146                 y->tv_usec += 1000000 * nsec;
147                 y->tv_sec -= nsec;
148         }
149
150         result->tv_sec = x->tv_sec - y->tv_sec;
151         result->tv_usec = x->tv_usec - y->tv_usec;
152
153         return x->tv_sec < y->tv_sec;
154 }
155
156 const gchar *get_exec_time(void)
157 {
158         static gchar timestr[30];
159         static struct timeval start_tv = {0, 0};
160         static struct timeval previous = {0, 0};
161         static gint started = 0;
162
163         struct timeval tv = {0, 0};
164         static struct timeval delta = {0, 0};
165
166         gettimeofday(&tv, NULL);
167
168         if (start_tv.tv_sec == 0) start_tv = tv;
169
170         tv.tv_sec -= start_tv.tv_sec;
171         if (tv.tv_usec >= start_tv.tv_usec)
172                 tv.tv_usec -= start_tv.tv_usec;
173         else
174                 {
175                 tv.tv_usec += 1000000 - start_tv.tv_usec;
176                 tv.tv_sec -= 1;
177                 }
178
179         if (started) timeval_delta(&delta, &tv, &previous);
180
181         previous = tv;
182         started = 1;
183
184         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);
185
186         return timestr;
187 }
188
189 void init_exec_time(void)
190 {
191         get_exec_time();
192 }
193
194 #endif /* DEBUG */
195 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */