Ejemplo n.º 1
0
/*
 * Set breakpoints condition.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 * 		condition - breakpoints line
 */
void breaks_set_condition(const char* file, int line, const char* condition)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* lookup for breakpoint */
	breakpoint* bp = NULL;
	if (!(bp = breaks_lookup_breakpoint(file, line)))
		return;
	
	/* change condition */
	strcpy(bp->condition, condition);
	
	/* handle setting condition instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (state == DBS_IDLE)
	{
		on_set_condition(bp);
		config_set_debug_changed();
	}
	else if (state == DBS_STOPPED)
		breaks_set_condition_debug(bp);
	else if (state != DBS_STOP_REQUESTED)
		debug_request_interrupt((bs_callback)breaks_set_condition_debug, (gpointer)bp);
}
Ejemplo n.º 2
0
/*
 * Switch breakpoints state.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 */
void breaks_switch(const char* file, int line)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* lookup for breakpoint */
	breakpoint* bp = NULL;
	if (!(bp = breaks_lookup_breakpoint(file, line)))
		return;
	
	/* change activeness */
	bp->enabled = !bp->enabled;
	
	/* handle switching instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_switch(bp);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_switch_debug(bp);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_switch_debug, (gpointer)bp);
}
Ejemplo n.º 3
0
/*
 * Add new breakpoint.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 * 		condition - breakpoints line
 * 		enabled - is new breakpoint enabled
 * 		hitscount - breakpoints hitscount
 */
void breaks_add(const char* file, int line, char* condition, int enabled, int hitscount)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;
	
	/* allocate memory */
	breakpoint* bp = break_new_full(file, line, condition, enabled, hitscount);
	
	/* check whether GTree for this file exists and create if doesn't */
	GTree *tree;
	if (!(tree = g_hash_table_lookup(files, bp->file)))
	{
		char *newfile = g_strdup(bp->file);
		tree = g_tree_new_full(compare_func, NULL, NULL, (GDestroyNotify)g_free);
		g_hash_table_insert(files, newfile, tree);
	}
	
	/* insert to internal storage */
	g_tree_insert(tree, GINT_TO_POINTER(bp->line), bp);

	/* handle creation instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_add(bp);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_add_debug(bp);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_add_debug, (gpointer)bp);
}
Ejemplo n.º 4
0
/* Called by Geany before unloading the plugin.
 * Here any UI changes should be removed, memory freed and any other finalization done.
 * Be sure to leave Geany as it was before plugin_init(). */
void plugin_cleanup(void)
{
	/* stop debugger if running */
	if (DBS_IDLE != debug_get_state())
	{
		debug_stop();
		while (DBS_IDLE != debug_get_state())
			g_main_context_iteration(NULL,FALSE);
	}

	config_destroy();
	pixbufs_destroy();
	debug_destroy();
	breaks_destroy();
	dpaned_destroy();
	envtree_destroy();
	
	/* release other allocated strings and objects */
	gtk_widget_destroy(hbox);
}
Ejemplo n.º 5
0
/*
 * 	Occures on document opening.
 * 	Used to set breaks markers 
 */
void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_data)
{
	/*set markers*/
	markers_set_for_document(doc->editor->sci);

	/*set dwell interval*/
	scintilla_send_message(doc->editor->sci, SCI_SETMOUSEDWELLTIME, 500, 0);

	/* set tab size for calltips */
	scintilla_send_message(doc->editor->sci, SCI_CALLTIPUSESTYLE, 20, (long)NULL);

	/* set breakpoint and frame markers */
	set_markers_for_file(DOC_FILENAME(doc));

	/* if debug is active - tell the debug module that a file was opened */
	if (DBS_IDLE != debug_get_state())
		debug_on_file_open(doc);
}
Ejemplo n.º 6
0
/*
 * 	Set breakpoint and stack markers for a file
 */
static void set_markers_for_file(const gchar* file)
{
	GList *breaks;
	if ( (breaks = breaks_get_for_document(file)) )
	{
		GList *iter = breaks;
		while (iter)
		{
			breakpoint *bp = (breakpoint*)iter->data;
			markers_add_breakpoint(bp);
			
			iter = iter->next;
		}
		g_list_free(breaks);
	}

	/* set frames markers if exists */
	if (DBS_STOPPED == debug_get_state())
	{
		int active_frame_index = debug_get_active_frame();
		
		GList *iter = debug_get_stack();
		int frame_index = 0;
		for (; iter; iter = iter->next, frame_index++)
		{
			if (iter)
			{
				frame *f = (frame*)iter->data;
				if (f->have_source && !strcmp(f->file, file))
				{
					if (active_frame_index == frame_index)
					{
						markers_add_current_instruction(f->file, f->line);
					}
					else
					{
						markers_add_frame(f->file, f->line);
					}
				}
			}
		}
	}
}
Ejemplo n.º 7
0
/*
 * Remove all breakpoints in the list.
 * arguments:
 * 		list - list f breakpoints
 */
void breaks_remove_list(GList *list)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* handle removing instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_remove_list(list);
		g_list_free(list);
		
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_remove_list_debug(list);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_remove_list_debug, (gpointer)list);
}
Ejemplo n.º 8
0
/*
 * sets all breakpoints fo the file enabled or disabled.
 * arguments:
 * 		file - list of breakpoints
 * 		enabled - anble or disable breakpoints
 */
void breaks_set_enabled_for_file(const const char *file, gboolean enabled)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	GList *breaks = breaks_get_for_document(file);

	/* handle switching instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_set_enabled_list(breaks, enabled);
		g_list_free(breaks);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		enabled ? breaks_set_enabled_list_debug(breaks) : breaks_set_disabled_list_debug(breaks);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)(enabled ? breaks_set_enabled_list_debug : breaks_set_disabled_list_debug), (gpointer)breaks);
}
Ejemplo n.º 9
0
static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer data)
{
	gchar *line;
	gsize length;
	
	if (G_IO_STATUS_NORMAL != g_io_channel_read_line(src, &line, NULL, &length, NULL))
		return TRUE;		

	gboolean prompt = !strcmp(line, GDB_PROMPT);
	
	*(line + length) = '\0';

	if (!prompt)
	{
		if ('~' == line[0])
		{
			colorize_message(line);
		}
		else
		{
			gchar *compressed = g_strcompress(line);
			colorize_message(compressed);
			g_free(compressed);
		}
	}
		
	if (!target_pid && g_str_has_prefix(line, "=thread-group-created"))
	{
		*(strrchr(line, '\"')) = '\0';
		target_pid = atoi(line + strlen("=thread-group-created,id=\""));
	}
	else if (g_str_has_prefix(line, "=thread-created"))
	{
		*(strrchr(line, ',') - 1) = '\0';
		int thread_id = atoi(line + strlen("=thread-created,id=\""));
		dbg_cbs->add_thread(thread_id);
	}
	else if (g_str_has_prefix(line, "=thread-exited"))
	{
		*(strrchr(line, ',') - 1) = '\0';
		int thread_id = atoi(line + strlen("=thread-exited,id=\""));
		dbg_cbs->remove_thread(thread_id);
	}
	else if (g_str_has_prefix(line, "=library-loaded") || g_str_has_prefix(line, "=library-unloaded"))
	{
		file_refresh_needed = TRUE;
	}
	else if (*line == '*')
	{
		/* asyncronous record found */
		char *record = NULL;
		if ( (record = strchr(line, ',')) )
		{
			*record = '\0';
			record++;
		}
		else
			record = line + strlen(line);
		
		if (!strcmp(line, "*running"))
			dbg_cbs->set_run();
		else if (!strcmp(line, "*stopped"))
		{
			/* removing read callback (will pulling all output left manually) */
			g_source_remove(gdb_id_out);

			/* looking for a reason to stop */
			char *next = NULL;
			char *reason = strstr(record, "reason=\"");
			if (reason)
			{
				reason += strlen("reason=\"");
				next = strstr(reason, "\"") + 1;
				*(next - 1) = '\0';
				if (!strcmp(reason, "breakpoint-hit"))
					stop_reason = SR_BREAKPOINT_HIT;
				else if (!strcmp(reason, "end-stepping-range"))
					stop_reason = SR_END_STEPPING_RANGE;
				else if (!strcmp(reason, "signal-received"))
					stop_reason = SR_SIGNAL_RECIEVED;
				else if (!strcmp(reason, "exited-normally"))
					stop_reason = SR_EXITED_NORMALLY;
				else if (!strcmp(reason, "exited-signalled"))
					stop_reason = SR_EXITED_SIGNALLED;
			}
			else
			{
				/* somehow, sometimes there can be no stop reason */
				stop_reason = SR_END_STEPPING_RANGE;
			}
			
			if (SR_BREAKPOINT_HIT == stop_reason || SR_END_STEPPING_RANGE == stop_reason || SR_SIGNAL_RECIEVED == stop_reason)
			{
				gchar *thread_id = strstr(reason + strlen(reason) + 1,"thread-id=\"") + strlen("thread-id=\"");
				*(strchr(thread_id, '\"')) = '\0'; 
				
				if (SR_BREAKPOINT_HIT == stop_reason || SR_END_STEPPING_RANGE == stop_reason)
				{
					/* update autos */
					update_autos();
			
					/* update watches */
					update_watches();
			
					/* update files */
					if (file_refresh_needed)
					{
						update_files();
						file_refresh_needed = FALSE;
					}

					dbg_cbs->set_stopped(atoi(thread_id));
				}
				else
				{
					if (!requested_interrupt)
						dbg_cbs->report_error(_("Program received a signal"));
					else
						requested_interrupt = FALSE;
						
					dbg_cbs->set_stopped(atoi(thread_id));
				}
			}
			else if (stop_reason == SR_EXITED_NORMALLY || stop_reason == SR_EXITED_SIGNALLED)
			{
				stop();
			}
		}
	}
	else if (g_str_has_prefix (line, "^error"))
	{
		/* removing read callback (will pulling all output left manually) */
		g_source_remove(gdb_id_out);

		/* set debugger stopped if is running */
		if (DBS_STOPPED != debug_get_state())
		{
			gchar *thread_id = strstr(line + strlen(line) + 1,"thread-id=\"");
			*(strchr(thread_id, '\"')) = '\0'; 

			dbg_cbs->set_stopped(atoi(thread_id));
		}

		/* get message */
		char *msg = strstr(line, "msg=\"") + strlen("msg=\"");
		*strrchr(msg, '\"') = '\0';
		msg = g_strcompress(msg);
		
		/* reading until prompt */
		GList *lines = read_until_prompt();
		GList *iter = lines;
		while(iter)
		{
			gchar *l = (gchar*)iter->data;
			if (strcmp(l, GDB_PROMPT))
				colorize_message(l);
			g_free(l);
			
			iter = iter->next;
		}
		g_list_free (lines);

		/* send error message */
		dbg_cbs->report_error(msg);

		g_free(msg);
	}

	g_free(line);

	return TRUE;
}
Ejemplo n.º 10
0
/*
 * 	Occures when key is pressed.
 * 	Handles debug Run/Stop/... and add/remove breakpoint activities  
 */
gboolean keys_callback(guint key_id)
{
	switch (key_id)
	{
		case KEY_RUN:
			debug_run();
			break;
		case KEY_STOP:
			debug_stop();
			break;
		case KEY_RESTART:
			debug_restart();
			break;
		case KEY_STEP_OVER:
			debug_step_over();
			break;
		case KEY_STEP_INTO:
			debug_step_into();
			break;
		case KEY_STEP_OUT:
			debug_step_out();
			break;
		case KEY_EXECUTE_UNTIL:
		{
			GeanyDocument *doc = document_get_current();
			if (doc)
			{
				int line = sci_get_current_line(doc->editor->sci) + 1;
				debug_execute_until(DOC_FILENAME(doc), line);
			}
			break;
		}
		case KEY_BREAKPOINT:
		{
			GeanyDocument *doc = document_get_current();
			if (doc)
			{
				int line = sci_get_current_line(doc->editor->sci) + 1;
				break_state	bs = breaks_get_state(DOC_FILENAME(doc), line);
				if (BS_NOT_SET == bs)
					breaks_add(DOC_FILENAME(doc), line, NULL, TRUE, 0);
				else if (BS_ENABLED == bs)
					breaks_remove(DOC_FILENAME(doc), line);
				else if (BS_DISABLED == bs)
					breaks_switch(DOC_FILENAME(doc), line);
				
				scintilla_send_message(doc->editor->sci, SCI_SETFOCUS, TRUE, 0);
			}
			break;
		}
		case KEY_CURRENT_INSTRUCTION:
		{
			if (DBS_STOPPED == debug_get_state() && debug_current_instruction_have_sources())
			{
				debug_jump_to_current_instruction();
				gtk_widget_set_sensitive(tab_call_stack, FALSE);
				stree_select_first_frame(FALSE);
				gtk_widget_set_sensitive(tab_call_stack, TRUE);
			}
		}
	}
	
	return TRUE;
} 
Ejemplo n.º 11
0
/*
 * 	Occures on notify from editor.
 * 	Handles margin click to set/remove breakpoint 
 */
gboolean on_editor_notify(
	GObject *object, GeanyEditor *editor,
	SCNotification *nt, gpointer data)
{
	if (!editor->document->real_path)
	{
		/* no other way to handle removing a file from outside of geany */
		markers_remove_all(editor->document);
	}
	
	switch (nt->nmhdr.code)
	{
		case SCN_MARGINCLICK:
		{
			char* file;
			int line;
			break_state bs;

			if (!editor->document->real_path || 1 != nt->margin)
				break;
			
			file = editor->document->file_name;
			line = sci_get_line_from_position(editor->sci, nt->position) + 1;

			bs = breaks_get_state(file, line);
			if (BS_NOT_SET == bs)
				breaks_add(file, line, NULL, TRUE, 0);
			else if (BS_ENABLED == bs)
				breaks_remove(file, line);
			else if (BS_DISABLED == bs)
				breaks_switch(file, line);
			
			scintilla_send_message(editor->sci, SCI_SETFOCUS, TRUE, 0);
			
			return TRUE;
		}
		case SCN_DWELLSTART:
		{
			GString *word;

			if (DBS_STOPPED != debug_get_state ())
				break;

			/* get a word under the cursor */
			word = get_word_at_position(editor->sci, nt->position);
			if (word->len)
			{
				gchar *calltip = debug_get_calltip_for_expression(word->str);
				if (calltip)
				{
					leave_signal = g_signal_connect(G_OBJECT(editor->sci), "leave-notify-event", G_CALLBACK(on_mouse_leave), NULL);
					scintilla_send_message (editor->sci, SCI_CALLTIPSHOW, nt->position, (long)calltip);
				}
			}
				
			g_string_free(word, TRUE);
			
			break;
		}
		case SCN_DWELLEND:
		{
			if (DBS_STOPPED != debug_get_state ())
				break;

			if (scintilla_send_message (editor->sci, SCI_CALLTIPACTIVE, 0, 0))
			{
				g_signal_handler_disconnect(G_OBJECT(editor->sci), leave_signal);
				scintilla_send_message (editor->sci, SCI_CALLTIPCANCEL, 0, 0);
			}
			break;
		}
		case SCN_MODIFYATTEMPTRO:
		{
			dialogs_show_msgbox(GTK_MESSAGE_INFO, _("To edit source files stop debugging session"));
			break;
		}
		case SCN_MODIFIED:
		{
			if(((SC_MOD_INSERTTEXT & nt->modificationType) || (SC_MOD_DELETETEXT && nt->modificationType)) && editor->document->file_name && nt->linesAdded)
			{
				int line = sci_get_line_from_position(editor->sci, nt->position) + 1;

				GList *breaks = breaks_get_for_document(editor->document->file_name);
				if (breaks)
				{
					GList *iter = breaks;
					while (iter)
					{
						breakpoint *bp = (breakpoint*)iter->data;

						if (nt->linesAdded > 0 && bp->line >= line)
						{
							breaks_move_to_line(bp->file, bp->line, bp->line + nt->linesAdded);
							bptree_update_breakpoint(bp);
						}
						else if (nt->linesAdded < 0 && bp->line >= line)
						{
							if (bp->line < line - nt->linesAdded)
							{
								breaks_remove(bp->file, bp->line);
							}
							else
							{
								breaks_move_to_line(bp->file, bp->line, bp->line + nt->linesAdded);
								bptree_update_breakpoint(bp);
							}
						}
						iter = iter->next;
					}
					
					config_set_debug_changed();

					g_list_free(breaks);
				}
			}
			break;
		}
	}

	return FALSE;
}