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