1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 utilities.c
4 Copyright (C) 2000 Kh. Naba Kumar Singh
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
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/wait.h>
28 #include <sys/stat.h>
29 #include <limits.h>
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <glib.h>
33
34 #include <gtk/gtk.h>
35 #include <gdk/gdk.h>
36 #include <glib.h>
37 #include <glib/gi18n.h>
38 #include <libanjuta/anjuta-launcher.h>
39 #include <libanjuta/interfaces/ianjuta-message-manager.h>
40 #include <libanjuta/interfaces/ianjuta-message-view.h>
41 #include "plugin.h"
42 #include "utilities.h"
43
44 #define ICON_FILE "anjuta-gdb.plugin.png"
45 #define SRCH_CHAR '\\'
46
47 static int
get_hex_as(const gchar c)48 get_hex_as (const gchar c)
49 {
50 if (isdigit (c))
51 return c - '0';
52 else
53 return toupper (c) - 'A' + 10;
54 }
55
56 static gchar
get_hex_b(const gchar c1,const gchar c2)57 get_hex_b (const gchar c1, const gchar c2)
58 {
59 return get_hex_as (c1) * 16 + get_hex_as(c2);
60 }
61
62 gchar*
gdb_util_get_str_cod(const gchar * szIn)63 gdb_util_get_str_cod (const gchar *szIn)
64 {
65 gchar *szRet ;
66 g_return_val_if_fail( NULL != szIn, NULL );
67 szRet = g_malloc( strlen( szIn )+2 );
68 if( NULL != szRet )
69 {
70 gchar* szDst = szRet ;
71 while( szIn[0] )
72 {
73 if( SRCH_CHAR == szIn[0] )
74 {
75 if( SRCH_CHAR == szIn[1] )
76 {
77 *szDst++ = *szIn ++ ;
78 szIn ++ ;
79 } else
80 {
81 *szDst ++ = get_hex_b (szIn[1], szIn[2]);
82 szIn += 3;
83 }
84 } else
85 {
86 *szDst++ = *szIn ++ ;
87 }
88 }
89 szDst [0] = '\0' ;
90 }
91 return szRet ;
92 }
93
94 gboolean
gdb_util_parse_error_line(const gchar * line,gchar ** filename,guint * lineno)95 gdb_util_parse_error_line (const gchar * line, gchar ** filename, guint *lineno)
96 {
97 gint i = 0;
98 gint j = 0;
99 gint k = 0;
100 gchar *dummy;
101
102 while (line[i++] != ':')
103 {
104 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
105 {
106 goto down;
107 }
108 }
109 if (isdigit (line[i]))
110 {
111 j = i;
112 while (isdigit (line[i++])) ;
113 dummy = g_strndup (&line[j], i - j - 1);
114 *lineno = strtoul (dummy, NULL, 10);
115 if (dummy)
116 g_free (dummy);
117 dummy = g_strndup (line, j - 1);
118 *filename = g_strdup (g_strstrip (dummy));
119 if (dummy)
120 g_free (dummy);
121 return TRUE;
122 }
123
124 down:
125 i = strlen (line) - 1;
126 while (isspace (line[i]) == FALSE)
127 {
128 i--;
129 if (i < 0)
130 {
131 *filename = NULL;
132 *lineno = 0;
133 return FALSE;
134 }
135 }
136 k = i++;
137 while (line[i++] != ':')
138 {
139 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
140 {
141 *filename = NULL;
142 *lineno = 0;
143 return FALSE;
144 }
145 }
146 if (isdigit (line[i]))
147 {
148 j = i;
149 while (isdigit (line[i++])) ;
150 dummy = g_strndup (&line[j], i - j - 1);
151 *lineno = strtoul (dummy, NULL, 10);
152 if (dummy)
153 g_free (dummy);
154 dummy = g_strndup (&line[k], j - k - 1);
155 *filename = g_strdup (g_strstrip (dummy));
156 if (dummy)
157 g_free (dummy);
158 return TRUE;
159 }
160 *lineno = 0;
161 *filename = NULL;
162 return FALSE;
163 }
164
165 gchar *
gdb_util_remove_white_spaces(const gchar * text)166 gdb_util_remove_white_spaces (const gchar * text)
167 {
168 guint src_count, dest_count, tab_count;
169 gchar buff[2048]; /* Let us hope that it does not overflow */
170
171 tab_count = 8;
172 dest_count = 0;
173
174 for (src_count = 0; src_count < strlen (text); src_count++)
175 {
176 if (text[src_count] == '\t')
177 {
178 gint j;
179 for (j = 0; j < tab_count; j++)
180 buff[dest_count++] = ' ';
181 }
182 else if (isspace (text[src_count]))
183 {
184 buff[dest_count++] = ' ';
185 }
186 else
187 {
188 buff[dest_count++] = text[src_count];
189 }
190 }
191 buff[dest_count] = '\0';
192 return g_strdup (buff);
193 }
194
195 GList *
gdb_util_remove_blank_lines(const GList * lines)196 gdb_util_remove_blank_lines (const GList * lines)
197 {
198 GList *list, *node;
199 gchar *str;
200
201 if (lines)
202 list = g_list_copy ((GList*)lines);
203 else
204 list = NULL;
205
206 node = list;
207 while (node)
208 {
209 str = node->data;
210 node = g_list_next (node);
211 if (!str)
212 {
213 list = g_list_remove (list, str);
214 continue;
215 }
216 if (strlen (g_strchomp (str)) < 1)
217 list = g_list_remove (list, str);
218 }
219 return list;
220 }
221
222 /* Excluding the final 0 */
gdb_util_calc_string_len(const gchar * szStr)223 gint gdb_util_calc_string_len( const gchar *szStr )
224 {
225 if( NULL == szStr )
226 return 0;
227 return strlen( szStr )*3 ; /* Leave space for the translated character */
228 }
229
gdb_util_calc_gnum_len(void)230 gint gdb_util_calc_gnum_len(void)
231 {
232 return 24 ; /* size of a stringfied integer */
233 }
234
235 /* Allocates a struct of pointers */
236 gchar **
gdb_util_string_parse_separator(const gint nItems,gchar * szStrIn,const gchar chSep)237 gdb_util_string_parse_separator (const gint nItems, gchar *szStrIn,
238 const gchar chSep)
239 {
240 gchar **szAllocPtrs = (char**)g_new( gchar*, nItems );
241 if( NULL != szAllocPtrs )
242 {
243 int i ;
244 gboolean bOK = TRUE ;
245 gchar *p = szStrIn ;
246 for( i = 0 ; i < nItems ; i ++ )
247 {
248 gchar *szp ;
249 szp = strchr( p, chSep ) ;
250 if( NULL != szp )
251 {
252 szAllocPtrs[i] = p ;
253 szp[0] = '\0' ; /* Parse Operation */
254 p = szp + 1 ;
255 } else
256 {
257 bOK = FALSE ;
258 break;
259 }
260 }
261 if( ! bOK )
262 {
263 g_free( szAllocPtrs );
264 szAllocPtrs = NULL ;
265 }
266 }
267 return szAllocPtrs ;
268 }
269
270 gint
gdb_util_kill_process(pid_t process_id,const gchar * signal)271 gdb_util_kill_process (pid_t process_id, const gchar* signal)
272 {
273 int status;
274 gchar *pid_str;
275 pid_t pid;
276
277 pid_str = g_strdup_printf ("%d", process_id);
278 pid = fork();
279 if (pid == 0)
280 {
281 execlp ("kill", "kill", "-s", signal, pid_str, NULL);
282 g_warning (_("Cannot execute command: \"%s\""), "kill");
283 _exit(1);
284 }
285 g_free (pid_str);
286 if (pid > 0) {
287 waitpid (pid, &status, 0);
288 return 0;
289 } else {
290 return -1;
291 }
292 }
293
294 /* Debugger message manager management */
295
296 #if 0
297 static const gchar * MESSAGE_VIEW_TITLE = N_("Debug");
298
299 static void
300 on_gdb_util_mesg_view_destroy(GdbPlugin* plugin, gpointer destroyed_view)
301 {
302 plugin->mesg_view = NULL;
303 }
304
305 static void
306 on_gdb_util_debug_buffer_flushed (IAnjutaMessageView *view, const gchar* line,
307 AnjutaPlugin *plugin)
308 {
309 g_return_if_fail (line != NULL);
310
311 IAnjutaMessageViewType type = IANJUTA_MESSAGE_VIEW_TYPE_NORMAL;
312 ianjuta_message_view_append (view, type, line, "", NULL);
313 }
314
315 static void
316 on_gdb_util_debug_mesg_clicked (IAnjutaMessageView* view, const gchar* line,
317 AnjutaPlugin* plugin)
318 {
319 /* FIXME: Parse the given line */
320 }
321
322 static IAnjutaMessageView *
323 gdb_util_get_message_view (AnjutaPlugin *plugin)
324 {
325 GObject *obj;
326 IAnjutaMessageView *message_view;
327 IAnjutaMessageManager *message_manager = NULL;
328 GdbPlugin *gdb_plugin = ANJUTA_PLUGIN_GDB (plugin);
329
330 g_return_val_if_fail (plugin != NULL, NULL);
331
332 if (gdb_plugin->mesg_view)
333 return gdb_plugin->mesg_view;
334
335 /* TODO: error checking */
336 obj = anjuta_shell_get_object (plugin->shell, "IAnjutaMessageManager",
337 NULL);
338 message_manager = IANJUTA_MESSAGE_MANAGER (obj);
339 message_view = ianjuta_message_manager_add_view (
340 message_manager, MESSAGE_VIEW_TITLE, ICON_FILE, NULL);
341 g_object_weak_ref (G_OBJECT (message_view),
342 (GWeakNotify)on_gdb_util_mesg_view_destroy, plugin);
343 g_signal_connect (G_OBJECT (message_view), "buffer-flushed",
344 G_CALLBACK (on_gdb_util_debug_buffer_flushed), plugin);
345 g_signal_connect (G_OBJECT (message_view), "message-clicked",
346 G_CALLBACK (on_gdb_util_debug_mesg_clicked), plugin);
347 ianjuta_message_manager_set_current_view (message_manager, message_view,
348 NULL);
349 gdb_plugin->mesg_view = message_view;
350
351 return message_view;
352 }
353
354 void
355 gdb_util_append_message (AnjutaPlugin *plugin, const gchar* message)
356 {
357 IAnjutaMessageView *message_view = NULL;
358
359 g_return_if_fail (plugin != NULL);
360
361 /* TODO: error checking */
362 message_view = gdb_util_get_message_view (plugin);
363 ianjuta_message_view_buffer_append (message_view, message, NULL);
364 }
365
366 void
367 gdb_util_show_messages (AnjutaPlugin *plugin)
368 {
369 GObject *obj;
370 IAnjutaMessageManager *message_manager = NULL;
371 IAnjutaMessageView *message_view = NULL;
372
373 /* TODO: error checking */
374 obj = anjuta_shell_get_object (ANJUTA_PLUGIN (plugin)->shell,
375 "IAnjutaMessageManager", NULL);
376 message_manager = IANJUTA_MESSAGE_MANAGER (obj);
377 message_view = gdb_util_get_message_view (plugin);
378 ianjuta_message_manager_set_current_view (message_manager, message_view,
379 NULL);
380 }
381
382 void
383 gdb_util_clear_messages (AnjutaPlugin *plugin)
384 {
385 IAnjutaMessageView *message_view = NULL;
386
387 g_return_if_fail (plugin != NULL);
388
389 /* TODO: error checking */
390 message_view = gdb_util_get_message_view (plugin);
391 ianjuta_message_view_clear (message_view, NULL);
392 }
393 #endif
394