Optional timer data in log window
[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, const gchar *function_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         if (options && options->log_window.timer_data)
101                 {
102                 location = g_strdup_printf("%s:%s:%s:%d:", get_exec_time(), file_name,
103                                                                                                 function_name, line_number);
104                 }
105         else
106                 {
107                 location = g_strdup_printf("%s:%s:%d:", file_name, function_name, line_number);
108                 }
109
110         buf = g_strconcat(location, message, NULL);
111         log_domain_print_message(domain,buf);
112         g_free(location);
113         g_free(message);
114 }
115
116 void log_domain_printf(const gchar *domain, const gchar *format, ...)
117 {
118         va_list ap;
119         gchar *buf;
120
121         va_start(ap, format);
122         buf = g_strdup_vprintf(format, ap);
123         va_end(ap);
124
125         log_domain_print_message(domain, buf);
126 }
127
128 /*
129  * Debugging only functions
130  */
131
132 #ifdef DEBUG
133
134 static gint debug_level = DEBUG_LEVEL_MIN;
135
136
137 gint get_debug_level(void)
138 {
139         return debug_level;
140 }
141
142 void set_debug_level(gint new_level)
143 {
144         debug_level = CLAMP(new_level, DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX);
145 }
146
147 void debug_level_add(gint delta)
148 {
149         set_debug_level(debug_level + delta);
150 }
151
152 gint required_debug_level(gint level)
153 {
154         return (debug_level >= level);
155 }
156
157 static gint timeval_delta(struct timeval *result, struct timeval *x, struct timeval *y)
158 {
159         if (x->tv_usec < y->tv_usec)
160                 {
161                 gint nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
162                 y->tv_usec -= 1000000 * nsec;
163                 y->tv_sec += nsec;
164                 }
165
166         if (x->tv_usec - y->tv_usec > 1000000)
167                 {
168                 gint nsec = (x->tv_usec - y->tv_usec) / 1000000;
169                 y->tv_usec += 1000000 * nsec;
170                 y->tv_sec -= nsec;
171         }
172
173         result->tv_sec = x->tv_sec - y->tv_sec;
174         result->tv_usec = x->tv_usec - y->tv_usec;
175
176         return x->tv_sec < y->tv_sec;
177 }
178
179 const gchar *get_exec_time(void)
180 {
181         static gchar timestr[30];
182         static struct timeval start_tv = {0, 0};
183         static struct timeval previous = {0, 0};
184         static gint started = 0;
185
186         struct timeval tv = {0, 0};
187         static struct timeval delta = {0, 0};
188
189         gettimeofday(&tv, NULL);
190
191         if (start_tv.tv_sec == 0) start_tv = tv;
192
193         tv.tv_sec -= start_tv.tv_sec;
194         if (tv.tv_usec >= start_tv.tv_usec)
195                 tv.tv_usec -= start_tv.tv_usec;
196         else
197                 {
198                 tv.tv_usec += 1000000 - start_tv.tv_usec;
199                 tv.tv_sec -= 1;
200                 }
201
202         if (started) timeval_delta(&delta, &tv, &previous);
203
204         previous = tv;
205         started = 1;
206
207         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);
208
209         return timestr;
210 }
211
212 void init_exec_time(void)
213 {
214         get_exec_time();
215 }
216
217 void set_regexp(gchar *cmd_regexp)
218 {
219         regexp = g_strdup(cmd_regexp);
220 }
221
222 gchar *get_regexp(void)
223 {
224         return g_strdup(regexp);
225 }
226
227 #endif /* DEBUG */
228 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */