Branch: refs/heads/master Author: Frank Lanitz frank@frank.uvena.de Committer: Frank Lanitz frank@frank.uvena.de Date: Sat, 13 Feb 2016 16:29:16 UTC Commit: 07aa19294b9e2d5a37dbec5d371d09bf541fbec0 https://github.com/geany/geany-plugins/commit/07aa19294b9e2d5a37dbec5d371d09...
Log Message: ----------- Merge pull request #349 from b4n/debugger/master
debugger: Various stuff
Modified Paths: -------------- debugger/src/breakpoints.c debugger/src/breakpoints.h debugger/src/dbm_gdb.c debugger/src/debug.c debugger/src/debug_module.c debugger/src/debug_module.h debugger/src/envtree.c debugger/src/gdb_mi.c debugger/src/gdb_mi.h debugger/src/markers.c debugger/src/stree.c debugger/src/stree.h debugger/src/watch_model.c
Modified: debugger/src/breakpoints.c 6 lines changed, 3 insertions(+), 3 deletions(-) =================================================================== @@ -70,7 +70,7 @@ static void hash_table_foreach_call_function(gpointer key, gpointer value, gpoin static gboolean tree_foreach_add_to_list(gpointer key, gpointer value, gpointer data) { GList **list = (GList**)data; - *list = g_list_append(*list, value); + *list = g_list_prepend(*list, value); return FALSE; }
@@ -675,7 +675,7 @@ GList* breaks_get_for_document(const char* file) { g_tree_foreach(tree, tree_foreach_add_to_list, &breaks); } - return breaks; + return g_list_reverse(breaks); }
/* @@ -702,5 +702,5 @@ GList* breaks_get_all(void) { GList *breaks = NULL; g_hash_table_foreach(files, hash_table_foreach_add_to_list, &breaks); - return breaks; + return g_list_reverse(breaks); }
Modified: debugger/src/breakpoints.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -33,6 +33,7 @@ typedef enum _break_state { } break_state;
typedef void (*move_to_line_cb)(const char* file, int line); +typedef void (*select_thread_cb)(int thread_id); typedef void (*select_frame_cb)(int frame_number);
gboolean breaks_init(move_to_line_cb callback);
Modified: debugger/src/dbm_gdb.c 226 lines changed, 129 insertions(+), 97 deletions(-) =================================================================== @@ -60,9 +60,9 @@ typedef enum _result_class {
/* structure to keep async command data (command line, messages) */ typedef struct _queue_item { - GString *message; - GString *command; - GString *error_message; + gchar *message; + gchar *command; + gchar *error_message; gboolean format_error_message; } queue_item;
@@ -213,10 +213,10 @@ static GList* read_until_prompt(void) break;
line[terminator] = '\0'; - lines = g_list_append (lines, line); + lines = g_list_prepend (lines, line); } - return lines; + return g_list_reverse(lines); }
/* @@ -261,11 +261,9 @@ static void gdb_input_write_line(const gchar *line) */ static void free_queue_item(queue_item *item) { - if (item->message) - g_string_free(item->message, TRUE); - g_string_free(item->command, TRUE); - if (item->error_message) - g_string_free(item->error_message, TRUE); + g_free(item->message); + g_free(item->command); + g_free(item->error_message); g_free(item); }
@@ -289,15 +287,9 @@ static GList* add_to_queue(GList* queue, const gchar *message, const gchar *comm
memset((void*)item, 0, sizeof(queue_item));
- if (message) - { - item->message = g_string_new(message); - } - item->command = g_string_new(command); - if (error_message) - { - item->error_message = g_string_new(error_message); - } + item->message = g_strdup(message); + item->command = g_strdup(command); + item->error_message = g_strdup(error_message); item->format_error_message = format_error_message;
return g_list_append(queue, (gpointer)item); @@ -351,10 +343,10 @@ static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpoint /* send message to debugger messages window */ if (item->message) { - dbg_cbs->send_message(item->message->str, "grey"); + dbg_cbs->send_message(item->message, "grey"); }
- gdb_input_write_line(item->command->str); + gdb_input_write_line(item->command);
gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands); } @@ -385,16 +377,14 @@ static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpoint if (item->format_error_message) { const gchar* gdb_msg = gdb_mi_result_var(record->first, "msg", GDB_MI_VAL_STRING); + gchar *msg = g_strdup_printf(item->error_message, gdb_msg);
- GString *msg = g_string_new(""); - g_string_printf(msg, item->error_message->str, gdb_msg); - dbg_cbs->report_error(msg->str); - - g_string_free(msg, FALSE); + dbg_cbs->report_error(msg); + g_free(msg); } else { - dbg_cbs->report_error(item->error_message->str); + dbg_cbs->report_error(item->error_message); } } @@ -529,7 +519,14 @@ static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer d else { if (!requested_interrupt) - dbg_cbs->report_error(_("Program received a signal")); + { + gchar *msg = g_strdup_printf(_("Program received signal %s (%s)"), + (gchar *) gdb_mi_result_var(record->first, "signal-name", GDB_MI_VAL_STRING), + (gchar *) gdb_mi_result_var(record->first, "signal-meaning", GDB_MI_VAL_STRING)); + + dbg_cbs->report_error(msg); + g_free(msg); + } else requested_interrupt = FALSE; } @@ -696,7 +693,8 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi gchar *working_directory = g_path_get_dirname(file); GList *lines, *iter; GList *commands = NULL; - GString *command; + gchar *command; + gchar *escaped; int bp_index; queue_item *item;
@@ -752,10 +750,11 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi /* collect commands */
/* loading file */ - command = g_string_new(""); - g_string_printf(command, "-file-exec-and-symbols "%s"", file); - commands = add_to_queue(commands, _("~"Loading target file.\n""), command->str, _("Error loading file"), FALSE); - g_string_free(command, TRUE); + escaped = g_strescape(file, NULL); + command = g_strdup_printf("-file-exec-and-symbols "%s"", escaped); + commands = add_to_queue(commands, _("~"Loading target file.\n""), command, _("Error loading file"), FALSE); + g_free(command); + g_free(escaped);
/* setting asyncronous mode */ commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE); @@ -767,16 +766,14 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE);
/* set locale */ - command = g_string_new(""); - g_string_printf(command, "-gdb-set environment LANG=%s", g_getenv("LANG")); - commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); - g_string_free(command, TRUE); + command = g_strdup_printf("-gdb-set environment LANG=%s", g_getenv("LANG")); + commands = add_to_queue(commands, NULL, command, NULL, FALSE); + g_free(command);
/* set arguments */ - command = g_string_new(""); - g_string_printf(command, "-exec-arguments %s", commandline); - commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); - g_string_free(command, TRUE); + command = g_strdup_printf("-exec-arguments %s", commandline); + commands = add_to_queue(commands, NULL, command, NULL, FALSE); + g_free(command);
/* set passed evironment */ iter = env; @@ -788,11 +785,9 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi iter = iter->next; value = (gchar*)iter->data;
- command = g_string_new(""); - g_string_printf(command, "-gdb-set environment %s=%s", name, value); - - commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); - g_string_free(command, TRUE); + command = g_strdup_printf("-gdb-set environment %s=%s", name, value); + commands = add_to_queue(commands, NULL, command, NULL, FALSE); + g_free(command);
iter = iter->next; } @@ -802,50 +797,47 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi while (biter) { breakpoint *bp = (breakpoint*)biter->data; - GString *error_message = g_string_new(""); + gchar *error_message;
- command = g_string_new(""); - g_string_printf(command, "-break-insert -f "\"%s\":%i"", bp->file, bp->line); + escaped = g_strescape(bp->file, NULL); + command = g_strdup_printf("-break-insert -f "\"%s\":%i"", escaped, bp->line); + g_free(escaped);
- g_string_printf(error_message, _("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s"); - - commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); + error_message = g_strdup_printf(_("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s"); + + commands = add_to_queue(commands, NULL, command, error_message, TRUE);
- g_string_free(command, TRUE); + g_free(command);
if (bp->hitscount) { - command = g_string_new(""); - g_string_printf(command, "-break-after %i %i", bp_index, bp->hitscount); - commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); - g_string_free(command, TRUE); + command = g_strdup_printf("-break-after %i %i", bp_index, bp->hitscount); + commands = add_to_queue(commands, NULL, command, error_message, TRUE); + g_free(command); } if (strlen(bp->condition)) { - command = g_string_new(""); - g_string_printf (command, "-break-condition %i %s", bp_index, bp->condition); - commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); - g_string_free(command, TRUE); + command = g_strdup_printf ("-break-condition %i %s", bp_index, bp->condition); + commands = add_to_queue(commands, NULL, command, error_message, TRUE); + g_free(command); } if (!bp->enabled) { - command = g_string_new(""); - g_string_printf (command, "-break-disable %i", bp_index); - commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); - g_string_free(command, TRUE); + command = g_strdup_printf ("-break-disable %i", bp_index); + commands = add_to_queue(commands, NULL, command, error_message, TRUE); + g_free(command); }
- g_string_free(error_message, TRUE); + g_free(error_message);
bp_index++; biter = biter->next; }
/* set debugging terminal */ - command = g_string_new("-inferior-tty-set "); - g_string_append(command, terminal_device); - commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); - g_string_free(command, TRUE); + command = g_strconcat("-inferior-tty-set ", terminal_device, NULL); + commands = add_to_queue(commands, NULL, command, NULL, FALSE); + g_free(command);
/* connect read callback to the output chanel */ gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands); @@ -855,11 +847,11 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi /* send message to debugger messages window */ if (item->message) { - dbg_cbs->send_message(item->message->str, "grey"); + dbg_cbs->send_message(item->message, "grey"); }
/* send first command */ - gdb_input_write_line(item->command->str); + gdb_input_write_line(item->command);
return TRUE; } @@ -930,6 +922,7 @@ static int get_break_number(char* file, int line) { struct gdb_mi_record *record; const struct gdb_mi_result *table, *body, *bkpt; + int break_number = -1;
exec_sync_command("-break-list", TRUE, &record); if (! record) @@ -939,8 +932,8 @@ static int get_break_number(char* file, int line) body = gdb_mi_result_var(table, "body", GDB_MI_VAL_LIST); gdb_mi_result_foreach_matched (bkpt, body, "bkpt", GDB_MI_VAL_LIST) { - const gchar *number = gdb_mi_result_var(bkpt->val->list, "number", GDB_MI_VAL_STRING); - const gchar *location = gdb_mi_result_var(bkpt->val->list, "original-location", GDB_MI_VAL_STRING); + const gchar *number = gdb_mi_result_var(bkpt->val->v.list, "number", GDB_MI_VAL_STRING); + const gchar *location = gdb_mi_result_var(bkpt->val->v.list, "original-location", GDB_MI_VAL_STRING); const gchar *colon; gboolean break_found = FALSE;
@@ -950,21 +943,26 @@ static int get_break_number(char* file, int line) colon = strrchr(location, ':'); if (colon && atoi(colon + 1) == line) { - gchar *fname = g_strndup(location, colon - location); - /* FIXME: the check used to be made against "file" (e.g. file surrounded - * by backslash-quote), but that's not at least how GDB 7.7 does it */ + gchar *fname; + + /* quotes around filename (location not found or something?) */ + if (*location == '"' && colon - location > 2) + fname = g_strndup(location + 1, colon - location - 2); + else + fname = g_strndup(location, colon - location); break_found = strcmp(fname, file) == 0; g_free(fname); } if (break_found) { - return atoi(number); + break_number = atoi(number); + break; } } gdb_mi_record_free(record); - return -1; + return break_number; }
/* @@ -979,18 +977,21 @@ static gboolean set_break(breakpoint* bp, break_set_activity bsa) struct gdb_mi_record *record; const struct gdb_mi_result *bkpt; const gchar *number; + gchar *escaped; int num = 0;
/* 1. insert breakpoint */ - g_snprintf(command, sizeof command, "-break-insert "\"%s\":%i"", bp->file, bp->line); + escaped = g_strescape(bp->file, NULL); + g_snprintf(command, sizeof command, "-break-insert "\"%s\":%i"", escaped, bp->line); if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record) { gdb_mi_record_free(record); record = NULL; - g_snprintf(command, sizeof command, "-break-insert -f "\"%s\":%i"", bp->file, bp->line); + g_snprintf(command, sizeof command, "-break-insert -f "\"%s\":%i"", escaped, bp->line); if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record) { gdb_mi_record_free(record); + g_free(escaped); return FALSE; } } @@ -999,6 +1000,7 @@ static gboolean set_break(breakpoint* bp, break_set_activity bsa) if ((number = gdb_mi_result_var(bkpt, "number", GDB_MI_VAL_STRING))) num = atoi(number); gdb_mi_record_free(record); + g_free(escaped); /* 2. set hits count if differs from 0 */ if (bp->hitscount) { @@ -1084,6 +1086,34 @@ static void set_active_frame(int frame_number) g_free(command); }
+static int get_active_thread(void) +{ + struct gdb_mi_record *record = NULL; + int current_thread = 0; + + if (RC_DONE == exec_sync_command("-thread-info", TRUE, &record)) + { + const gchar *id = gdb_mi_result_var(record->first, "current-thread-id", GDB_MI_VAL_STRING); + current_thread = id ? atoi(id) : 0; + } + gdb_mi_record_free(record); + + return current_thread; +} + +static gboolean set_active_thread(int thread_id) +{ + gchar *command = g_strdup_printf("-thread-select %i", thread_id); + gboolean success = (RC_DONE == exec_sync_command(command, TRUE, NULL)); + + if (success) + set_active_frame(0); + + g_free(command); + + return success; +} + /* * gets stack */ @@ -1102,9 +1132,9 @@ static GList* get_stack(void) stack_node = gdb_mi_result_var(record->first, "stack", GDB_MI_VAL_LIST); gdb_mi_result_foreach_matched (frame_node, stack_node, "frame", GDB_MI_VAL_LIST) { - const gchar *addr = gdb_mi_result_var(frame_node->val->list, "addr", GDB_MI_VAL_STRING); - const gchar *func = gdb_mi_result_var(frame_node->val->list, "func", GDB_MI_VAL_STRING); - const gchar *line = gdb_mi_result_var(frame_node->val->list, "line", GDB_MI_VAL_STRING); + const gchar *addr = gdb_mi_result_var(frame_node->val->v.list, "addr", GDB_MI_VAL_STRING); + const gchar *func = gdb_mi_result_var(frame_node->val->v.list, "func", GDB_MI_VAL_STRING); + const gchar *line = gdb_mi_result_var(frame_node->val->v.list, "line", GDB_MI_VAL_STRING); const gchar *file, *fullname; frame *f = frame_new();
@@ -1112,9 +1142,9 @@ static GList* get_stack(void) f->function = g_strdup(func);
/* file: fullname | file | from */ - if ((fullname = file = gdb_mi_result_var(frame_node->val->list, "fullname", GDB_MI_VAL_STRING)) || - (file = gdb_mi_result_var(frame_node->val->list, "file", GDB_MI_VAL_STRING)) || - (file = gdb_mi_result_var(frame_node->val->list, "from", GDB_MI_VAL_STRING))) + if ((fullname = file = gdb_mi_result_var(frame_node->val->v.list, "fullname", GDB_MI_VAL_STRING)) || + (file = gdb_mi_result_var(frame_node->val->v.list, "file", GDB_MI_VAL_STRING)) || + (file = gdb_mi_result_var(frame_node->val->v.list, "from", GDB_MI_VAL_STRING))) { f->file = g_strdup(file); } @@ -1129,11 +1159,11 @@ static GList* get_stack(void) /* line */ f->line = line ? atoi(line) : 0;
- stack = g_list_append(stack, f); + stack = g_list_prepend(stack, f); } gdb_mi_record_free(record); - return stack; + return g_list_reverse(stack); }
/* @@ -1224,7 +1254,7 @@ static void update_files(void) files_node = gdb_mi_result_var(record->first, "files", GDB_MI_VAL_LIST); gdb_mi_result_foreach_matched (files_node, files_node, NULL, GDB_MI_VAL_LIST) { - const gchar *fullname = gdb_mi_result_var(files_node->val->list, "fullname", GDB_MI_VAL_STRING); + const gchar *fullname = gdb_mi_result_var(files_node->val->v.list, "fullname", GDB_MI_VAL_STRING);
if (fullname && !g_hash_table_lookup(ht, fullname)) { @@ -1293,8 +1323,9 @@ static void update_watches(void) var->evaluated = name != NULL;
/* add to updating list */ - updating = g_list_append(updating, var); + updating = g_list_prepend(updating, var); } + updating = g_list_reverse(updating); /* update watches */ get_variables(updating); @@ -1335,11 +1366,11 @@ static void update_autos(void)
gdb_mi_result_foreach_matched (stack_args, stack_args, "frame", GDB_MI_VAL_LIST) { - const struct gdb_mi_result *args = gdb_mi_result_var(stack_args->val->list, "args", GDB_MI_VAL_LIST); + const struct gdb_mi_result *args = gdb_mi_result_var(stack_args->val->v.list, "args", GDB_MI_VAL_LIST);
gdb_mi_result_foreach_matched (args, args, "name", GDB_MI_VAL_STRING) { - variable *var = variable_new(args->val->string, VT_ARGUMENT); + variable *var = variable_new(args->val->v.string, VT_ARGUMENT); vars = g_list_append(vars, var); } } @@ -1352,7 +1383,7 @@ static void update_autos(void)
gdb_mi_result_foreach_matched (locals, locals, "name", GDB_MI_VAL_STRING) { - variable *var = variable_new(locals->val->string, VT_LOCAL); + variable *var = variable_new(locals->val->v.string, VT_LOCAL); vars = g_list_append(vars, var); } } @@ -1455,8 +1486,8 @@ static GList* get_children (gchar* path)
gdb_mi_result_foreach_matched (child_node, child_node, "child", GDB_MI_VAL_LIST) { - const gchar *internal = gdb_mi_result_var(child_node->val->list, "name", GDB_MI_VAL_STRING); - const gchar *name = gdb_mi_result_var(child_node->val->list, "exp", GDB_MI_VAL_STRING); + const gchar *internal = gdb_mi_result_var(child_node->val->v.list, "name", GDB_MI_VAL_STRING); + const gchar *name = gdb_mi_result_var(child_node->val->v.list, "exp", GDB_MI_VAL_STRING); variable *var;
if (! name || ! internal) @@ -1465,11 +1496,12 @@ static GList* get_children (gchar* path) var = variable_new2(name, internal, VT_CHILD); var->evaluated = TRUE;
- children = g_list_append(children, var); + children = g_list_prepend(children, var); } } gdb_mi_record_free(record); + children = g_list_reverse(children); get_variables(children);
return children;
Modified: debugger/src/debug.c 71 lines changed, 51 insertions(+), 20 deletions(-) =================================================================== @@ -399,7 +399,7 @@ static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent *even
/* check whether only empty row was selected */ if (1 != gtk_tree_selection_count_selected_rows(selection) || - gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path)) + (rows && gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path))) { /* path reference to select after deleteing finishes */ GtkTreeRowReference *reference_to_select = NULL; @@ -418,13 +418,13 @@ static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent *even
/* add path reference if it's not an empty row*/ if (gtk_tree_path_compare(path, empty_path)) - references = g_list_append(references, gtk_tree_row_reference_new(wmodel, path)); + references = g_list_prepend(references, gtk_tree_row_reference_new(wmodel, path));
iter = iter->next; }
/* iterate through references and remove */ - iter = references; + iter = g_list_reverse(references); while (iter) { GtkTreeRowReference *reference = (GtkTreeRowReference*)iter->data; @@ -640,7 +640,7 @@ static void on_debugger_run (void) if (stack) { remove_stack_markers(); - g_list_foreach(stack, (GFunc)frame_free, NULL); + g_list_foreach(stack, (GFunc)frame_unref, NULL); g_list_free(stack); stack = NULL;
@@ -700,11 +700,7 @@ static void on_debugger_stopped (int thread_id)
/* get current stack trace and put in the tree view */ stack = active_module->get_stack(); - for (iter = stack; iter; iter = iter->next) - { - frame *f = (frame*)iter->data; - stree_add(f); - } + stree_add (stack); stree_select_first_frame(TRUE);
/* files */ @@ -799,7 +795,7 @@ static void on_debugger_exited (int code) if (stack) { remove_stack_markers(); - g_list_foreach(stack, (GFunc)frame_free, NULL); + g_list_foreach(stack, (GFunc)frame_unref, NULL); g_list_free(stack); stack = NULL; } @@ -934,9 +930,12 @@ dbg_callbacks callbacks = { static void on_select_frame(int frame_number) { GList *autos, *watches; - frame *f = (frame*)g_list_nth(stack, active_module->get_active_frame())->data; - markers_remove_current_instruction(f->file, f->line); - markers_add_frame(f->file, f->line); + frame *f = (frame*)g_list_nth_data(stack, active_module->get_active_frame()); + if (f) + { + markers_remove_current_instruction(f->file, f->line); + markers_add_frame(f->file, f->line); + }
active_module->set_active_frame(frame_number); @@ -952,9 +951,41 @@ static void on_select_frame(int frame_number) watches = active_module->get_watches(); update_variables(GTK_TREE_VIEW(wtree), NULL, watches);
- f = (frame*)g_list_nth(stack, frame_number)->data; - markers_remove_frame(f->file, f->line); - markers_add_current_instruction(f->file, f->line); + f = (frame*)g_list_nth_data(stack, frame_number); + if (f) + { + markers_remove_frame(f->file, f->line); + markers_add_current_instruction(f->file, f->line); + } +} + +/* + * called when a thread should been selected + */ +static void on_select_thread(int thread_id) +{ + gboolean success; + + if (stack) + remove_stack_markers(); + + if ((success = active_module->set_active_thread(thread_id))) + { + g_list_free_full(stack, (GDestroyNotify)frame_unref); + stack = active_module->get_stack(); + + /* update the stack tree */ + stree_remove_frames(); + stree_set_active_thread_id(thread_id); + stree_add(stack); + stree_select_first_frame(TRUE); + } + + if (stack) + add_stack_markers(); + + if (success) + on_select_frame(0); }
/* @@ -1000,7 +1031,7 @@ void debug_init(void) gtk_container_add(GTK_CONTAINER(tab_autos), atree); /* create stack trace page */ - stree = stree_init(editor_open_position, on_select_frame); + stree = stree_init(editor_open_position, on_select_thread, on_select_frame); tab_call_stack = gtk_scrolled_window_new( gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(stree )), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(stree )) @@ -1075,7 +1106,7 @@ void debug_destroy(void) if (stack) { remove_stack_markers(); - g_list_foreach(stack, (GFunc)frame_free, NULL); + g_list_foreach(stack, (GFunc)frame_unref, NULL); g_list_free(stack); stack = NULL; } @@ -1126,11 +1157,11 @@ GList* debug_get_modules(void) module_description *desc = modules; while (desc->title) { - mods = g_list_append(mods, (gpointer)desc->title); + mods = g_list_prepend(mods, (gpointer)desc->title); desc++; } - return mods; + return g_list_reverse(mods); }
/*
Modified: debugger/src/debug_module.c 28 lines changed, 15 insertions(+), 13 deletions(-) =================================================================== @@ -79,26 +79,28 @@ void variable_reset(variable *var) /* creates new frame */ frame* frame_new(void) { - frame *f = (frame*)malloc(sizeof(frame)); - memset((void*)f, 0, sizeof(frame)); + frame *f = g_malloc0(sizeof *f); + f->ref_count = 1; return f; }
-/* frees a frame */ -void frame_free(frame* f) +/* refs a frame */ +frame* frame_ref(frame* f) { - if (f->address) + f->ref_count++; + return f; +} + +/* unrefs a frame */ +void frame_unref(frame* f) +{ + if (f->ref_count > 1) + f->ref_count--; + else { g_free(f->address); - } - if (f->function) - { g_free(f->function); - } - if (f->file) - { g_free(f->file); + g_free(f); } - - g_free(f); }
Modified: debugger/src/debug_module.h 13 lines changed, 10 insertions(+), 3 deletions(-) =================================================================== @@ -79,6 +79,7 @@ typedef struct _variable {
/* type to hold information about a stack frame */ typedef struct _frame { + gint ref_count; gchar *address; gchar *function; gchar *file; @@ -120,7 +121,10 @@ typedef struct _dbg_module {
void (*set_active_frame)(int frame_number); int (*get_active_frame)(void); - + + gboolean (*set_active_thread)(int thread_id); + int (*get_active_thread)(void); + GList* (*get_autos) (void); GList* (*get_watches) (void); @@ -154,6 +158,8 @@ typedef struct _dbg_module { get_stack, \ set_active_frame, \ get_active_frame, \ + set_active_thread, \ + get_active_thread, \ get_autos, \ get_watches, \ get_files, \ @@ -170,7 +176,8 @@ variable* variable_new(const gchar *name, variable_type vt); variable* variable_new2(const gchar *name, const gchar *internal, variable_type vt); void variable_reset(variable *var);
-frame* frame_new(void); -void frame_free(frame* f); +frame* frame_new(void); +frame* frame_ref(frame* f); +void frame_unref(frame* f);
#endif /* guard */
Modified: debugger/src/envtree.c 6 lines changed, 3 insertions(+), 3 deletions(-) =================================================================== @@ -110,7 +110,7 @@ static void delete_selected_rows(void)
/* check whether only empty row was selected */ if (1 != gtk_tree_selection_count_selected_rows(selection) || - gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path)) + (rows && gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path))) { GtkTreePath *path; /* get references to the selected rows and find out what to @@ -135,7 +135,7 @@ static void delete_selected_rows(void) } if (gtk_tree_path_compare(path, empty_path)) - references = g_list_append(references, gtk_tree_row_reference_new(model, path)); + references = g_list_prepend(references, gtk_tree_row_reference_new(model, path)); iter = iter->next; } @@ -145,7 +145,7 @@ static void delete_selected_rows(void) if (!reference_to_select) reference_to_select = gtk_tree_row_reference_copy (empty_row);
- iter = references; + iter = g_list_reverse(references); while (iter) { GtkTreeIter titer;
Modified: debugger/src/gdb_mi.c 71 lines changed, 45 insertions(+), 26 deletions(-) =================================================================== @@ -47,13 +47,11 @@ void gdb_mi_value_free(struct gdb_mi_value *val) switch (val->type) { case GDB_MI_VAL_STRING: - g_free(val->string); - g_warn_if_fail(val->list == NULL); + g_free(val->v.string); break;
case GDB_MI_VAL_LIST: - gdb_mi_result_free(val->list, TRUE); - g_warn_if_fail(val->string == NULL); + gdb_mi_result_free(val->v.list, TRUE); break; } g_free(val); @@ -98,13 +96,17 @@ static gchar *parse_cstring(const gchar **p)
if (**p == '"') { + const gchar *base; + (*p)++; + base = *p; while (**p != '"') { gchar c = **p; /* TODO: check expansions here */ if (c == '\') { + g_string_append_len(str, base, (*p) - base); (*p)++; c = **p; switch (g_ascii_tolower(c)) @@ -159,12 +161,14 @@ static gchar *parse_cstring(const gchar **p) } break; } + g_string_append_c(str, c); + base = (*p) + 1; } - if (**p == '\0') + else if (**p == '\0') break; - g_string_append_c(str, c); (*p)++; } + g_string_append_len(str, base, (*p) - base); if (**p == '"') (*p)++; } @@ -176,15 +180,15 @@ static gchar *parse_cstring(const gchar **p) * the docs aren't clear on this */ static gchar *parse_string(const gchar **p) { - GString *str = g_string_new(NULL); + const gchar *base = *p;
if (g_ascii_isalpha(**p) || strchr("-_.", **p)) { - g_string_append_c(str, **p); for ((*p)++; g_ascii_isalnum(**p) || strchr("-_.", **p); (*p)++) - g_string_append_c(str, **p); + ; } - return g_string_free(str, FALSE); + + return g_strndup (base, *p - base); }
/* parses: string "=" value */ @@ -205,15 +209,17 @@ static gboolean parse_result(struct gdb_mi_result *result, const gchar **p) * Actually, this is more permissive and allows mixed tuples/lists */ static struct gdb_mi_value *parse_value(const gchar **p) { - struct gdb_mi_value *val = g_malloc0(sizeof *val); + struct gdb_mi_value *val = NULL; if (**p == '"') { + val = g_malloc0(sizeof *val); val->type = GDB_MI_VAL_STRING; - val->string = parse_cstring(p); + val->v.string = parse_cstring(p); } else if (**p == '{' || **p == '[') { struct gdb_mi_result *prev = NULL; + val = g_malloc0(sizeof *val); val->type = GDB_MI_VAL_LIST; gchar end = **p == '{' ? '}' : ']'; (*p)++; @@ -227,7 +233,7 @@ static struct gdb_mi_value *parse_value(const gchar **p) if (prev) prev->next = item; else - val->list = item; + val->v.list = item; prev = item; } else @@ -242,11 +248,6 @@ static struct gdb_mi_value *parse_value(const gchar **p) if (**p == end) (*p)++; } - else - { - gdb_mi_value_free(val); - val = NULL; - } return val; }
@@ -393,9 +394,9 @@ const void *gdb_mi_result_var(const struct gdb_mi_result *result, const gchar *n if (! val || val->type != type) return NULL; else if (val->type == GDB_MI_VAL_STRING) - return val->string; + return val->v.string; else if (val->type == GDB_MI_VAL_LIST) - return val->list; + return val->v.list; return NULL; }
@@ -449,12 +450,12 @@ static void gdb_mi_value_dump(const struct gdb_mi_value *v, gint indent) switch (v->type) { case GDB_MI_VAL_STRING: - fprintf(stderr, "%*sstring = %s\n", indent * 2, "", v->string); + fprintf(stderr, "%*sstring = %s\n", indent * 2, "", v->v.string); break; case GDB_MI_VAL_LIST: fprintf(stderr, "%*slist =>\n", indent * 2, ""); - if (v->list) - gdb_mi_result_dump(v->list, TRUE, indent + 1); + if (v->v.list) + gdb_mi_result_dump(v->v.list, TRUE, indent + 1); break; } } @@ -479,17 +480,35 @@ static void gdb_mi_record_dump(const struct gdb_mi_record *record) gdb_mi_result_dump(record->first, TRUE, 2); }
-int main(void) +static gchar *read_line(FILE *fp) { char buf[1024] = {0}; + GString *line = g_string_new(NULL); + + while (fgets(buf, sizeof buf, fp)) + { + g_string_append(line, buf); + if (line->len < 1 || line->str[line->len - 1] == '\n') + break; + } + + return g_string_free(line, line->len < 1); +}
- while (fgets(buf, sizeof buf, stdin)) +int main(int argc, char **argv) +{ + gchar *line; + + while ((line = read_line(stdin)) != NULL) { - struct gdb_mi_record *record = gdb_mi_record_parse(buf); + struct gdb_mi_record *record = gdb_mi_record_parse(line);
gdb_mi_record_dump(record); gdb_mi_record_free(record); + + g_free(line); } + return 0; }
Modified: debugger/src/gdb_mi.h 6 lines changed, 4 insertions(+), 2 deletions(-) =================================================================== @@ -34,8 +34,10 @@ struct gdb_mi_result; struct gdb_mi_value { enum gdb_mi_value_type type; - gchar *string; - struct gdb_mi_result *list; + union { + gchar *string; + struct gdb_mi_result *list; + } v; };
struct gdb_mi_result
Modified: debugger/src/markers.c 19 lines changed, 10 insertions(+), 9 deletions(-) =================================================================== @@ -40,15 +40,16 @@ extern GeanyData *geany_data; #include "xpm/frame_current.xpm"
/* markers identifiers */ -#define M_FIRST 12 -#define M_BP_ENABLED M_FIRST -#define M_BP_DISABLED (M_FIRST + 1) -#define M_BP_CONDITIONAL (M_FIRST + 2) -#define M_CI_BACKGROUND (M_FIRST + 3) -#define M_CI_ARROW (M_FIRST + 4) -#define M_FRAME (M_FIRST + 5) - -#define MARKER_PRESENT(mask, marker) (mask && (0x01 << marker)) +#define M_FIRST 12 +enum +{ + M_BP_ENABLED = M_FIRST, + M_BP_DISABLED, + M_BP_CONDITIONAL, + M_FRAME, + M_CI_BACKGROUND, + M_CI_ARROW +};
/* markers colors */ #define RGB(R,G,B) (R | (G << 8) | (B << 16))
Modified: debugger/src/stree.c 357 lines changed, 174 insertions(+), 183 deletions(-) =================================================================== @@ -42,26 +42,19 @@ /* Tree view columns */ enum { - S_ADRESS, - S_FUNCTION, - S_FILEPATH, - S_LINE, - S_LAST_VISIBLE, - S_HAVE_SOURCE, + S_FRAME, /* the frame if it's a frame, or NULL if it's a thread */ S_THREAD_ID, S_ACTIVE, S_N_COLUMNS };
-/* hash table to keep thread nodes in the tree */ -static GHashTable *threads; - /* active thread and frame */ static glong active_thread_id = 0; static int active_frame_index = 0;
/* callbacks */ static select_frame_cb select_frame = NULL; +static select_thread_cb select_thread = NULL; static move_to_line_cb move_to_line = NULL;
/* tree view, model and store handles */ @@ -69,9 +62,37 @@ static GtkWidget *tree = NULL; static GtkTreeModel *model = NULL; static GtkTreeStore *store = NULL;
+static GtkTreeViewColumn *column_filepath = NULL; +static GtkTreeViewColumn *column_address = NULL; + /* cell renderer for a frame arrow */ static GtkCellRenderer *renderer_arrow = NULL;
+static GType frame_get_type (void); +G_DEFINE_BOXED_TYPE(frame, frame, frame_ref, frame_unref) +#define STREE_TYPE_FRAME (frame_get_type ()) + +/* finds the iter for thread @thread_id */ +static gboolean find_thread_iter (gint thread_id, GtkTreeIter *iter) +{ + gboolean found = FALSE; + + if (gtk_tree_model_get_iter_first(model, iter)) + { + do + { + gint existing_thread_id; + + gtk_tree_model_get(model, iter, S_THREAD_ID, &existing_thread_id, -1); + if (existing_thread_id == thread_id) + found = TRUE; + } + while (! found && gtk_tree_model_iter_next(model, iter)); + } + + return found; +} + /* * frame arrow clicked callback */ @@ -80,10 +101,13 @@ static void on_frame_arrow_clicked(CellRendererFrameIcon *cell_renderer, gchar * GtkTreePath *new_active_frame = gtk_tree_path_new_from_string (path); if (gtk_tree_path_get_indices(new_active_frame)[1] != active_frame_index) { + GtkTreeIter thread_iter; GtkTreeIter iter; + GtkTreePath *old_active_frame; + + find_thread_iter (active_thread_id, &thread_iter); + old_active_frame = gtk_tree_model_get_path (model, &thread_iter);
- GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); - GtkTreePath *old_active_frame = gtk_tree_row_reference_get_path(reference); gtk_tree_path_append_index(old_active_frame, active_frame_index);
gtk_tree_model_get_iter(model, &iter, old_active_frame); @@ -119,23 +143,23 @@ static gboolean on_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean key gint start_pos, width; gtk_tree_view_column_cell_get_position(column, renderer_arrow, &start_pos, &width); - if (column == gtk_tree_view_get_column(GTK_TREE_VIEW(widget), S_FILEPATH)) + if (column == column_filepath) { - gchar *path = NULL; + frame *f; GtkTreeIter iter; gtk_tree_model_get_iter(model, &iter, tpath); - gtk_tree_model_get(model, &iter, S_FILEPATH, &path, -1); + gtk_tree_model_get(model, &iter, S_FRAME, &f, -1); - gtk_tooltip_set_text(tooltip, path); + gtk_tooltip_set_text(tooltip, f->file); gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, tpath); show = TRUE;
- g_free(path); + frame_unref(f); } - else if (column == gtk_tree_view_get_column(GTK_TREE_VIEW(widget), S_ADRESS && bx >= start_pos && bx < start_pos + width)) + else if (column == column_address && bx >= start_pos && bx < start_pos + width) { gtk_tooltip_set_text(tooltip, gtk_tree_path_get_indices(tpath)[1] == active_frame_index ? _("Active frame") : _("Click an arrow to switch to a frame")); gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, tpath); @@ -165,14 +189,23 @@ static void on_render_arrow(GtkTreeViewColumn *tree_column, GtkCellRenderer *cel static void on_render_line(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { - GtkTreePath *tpath = gtk_tree_model_get_path(model, iter); + frame *f;
- if (1 == gtk_tree_path_get_depth(tpath)) - { + gtk_tree_model_get (model, iter, S_FRAME, &f, -1); + + if (! f) g_object_set(cell, "text", "", NULL); - } + else + { + GValue value = {0};
- gtk_tree_path_free(tpath); + g_value_init(&value, G_TYPE_INT); + g_value_set_int (&value, f->line); + g_object_set_property (G_OBJECT (cell), "text", &value); + + g_value_unset (&value); + frame_unref (f); + } }
/* @@ -181,28 +214,22 @@ static void on_render_line(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell static void on_render_filename(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { - GtkTreePath *tpath = gtk_tree_model_get_path(model, iter); - - if (1 != gtk_tree_path_get_depth(tpath)) - { - gchar *path = NULL, *name; - gtk_tree_model_get(model, iter, S_FILEPATH, &path, -1); + frame *f;
- name = path ? g_path_get_basename(path) : NULL; - g_object_set(cell, "text", name ? name : path, NULL); + gtk_tree_model_get(model, iter, S_FRAME, &f, -1);
- g_free(name); - if (path) - { - g_free(path); - } - } + if (! f) + g_object_set(cell, "text", "", NULL); else { - g_object_set(cell, "text", "", NULL); - } + gchar *name;
- gtk_tree_path_free(tpath); + name = f->file ? g_path_get_basename(f->file) : NULL; + g_object_set(cell, "text", name ? name : f->file, NULL); + + g_free(name); + frame_unref (f); + } }
/* @@ -218,44 +245,31 @@ static gboolean on_msgwin_button_press(GtkWidget *widget, GdkEventButton *event, { if (2 == gtk_tree_path_get_depth(pressed_path)) { - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); - GList *rows = gtk_tree_selection_get_selected_rows(selection, &model); - GtkTreePath *selected_path = (GtkTreePath*)rows->data; + GtkTreePath *selected_path; + gtk_tree_view_get_cursor(GTK_TREE_VIEW(tree), &selected_path, NULL);
- if (!gtk_tree_path_compare(pressed_path, selected_path)) + if (selected_path && !gtk_tree_path_compare(pressed_path, selected_path)) { - gboolean have_source; + frame *f; GtkTreeIter iter; gtk_tree_model_get_iter ( model, &iter, pressed_path);
- gtk_tree_model_get ( - model, - &iter, - S_HAVE_SOURCE, &have_source, - -1); + gtk_tree_model_get (model, &iter, S_FRAME, &f, -1); /* check if file name is not empty and we have source files for the frame */ - if (have_source) + if (f->have_source) { - gchar *file; - gint line; - gtk_tree_model_get ( - model, - &iter, - S_FILEPATH, &file, - S_LINE, &line, - -1); - move_to_line(file, line); - - g_free(file); + move_to_line(f->file, f->line); } + + frame_unref(f); }
- g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); - g_list_free (rows); + if (selected_path) + gtk_tree_path_free(selected_path); }
gtk_tree_path_free(pressed_path); @@ -266,79 +280,97 @@ static gboolean on_msgwin_button_press(GtkWidget *widget, GdkEventButton *event, }
/* - * Tree view selection changed callback + * Tree view cursor changed callback */ -static void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) +static void on_cursor_changed(GtkTreeView *treeview, gpointer user_data) { - GList *rows; GtkTreePath *path; + GtkTreeIter iter; + frame *f; + int thread_id;
- if (!gtk_tree_selection_count_selected_rows(treeselection)) - { + gtk_tree_view_get_cursor(treeview, &path, NULL); + if (! path) return; - } - - rows = gtk_tree_selection_get_selected_rows(treeselection, &model); - path = (GtkTreePath*)rows->data;
- if (2 == gtk_tree_path_get_depth(path)) - { - gboolean have_source; - GtkTreeIter iter; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + S_FRAME, &f, S_THREAD_ID, &thread_id, -1);
- gtk_tree_model_get_iter ( - model, - &iter, - path); - gtk_tree_model_get ( - gtk_tree_view_get_model(GTK_TREE_VIEW(tree)), - &iter, - S_HAVE_SOURCE, &have_source, - -1); - + if (f) /* frame */ + { /* check if file name is not empty and we have source files for the frame */ - if (have_source) + if (f->have_source) { - gchar *file; - gint line; - gtk_tree_model_get ( - model, - &iter, - S_FILEPATH, &file, - S_LINE, &line, - -1); - - move_to_line(file, line); - g_free(file); + move_to_line(f->file, f->line); } + frame_unref(f); + } + else /* thread */ + { + if (thread_id != active_thread_id) + select_thread(thread_id); + } + + gtk_tree_path_free(path); +} + +static void on_render_function (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + frame *f; + + gtk_tree_model_get (tree_model, iter, S_FRAME, &f, -1); + if (! f) + g_object_set (cell, "text", "", NULL); + else + { + g_object_set (cell, "text", f->function, NULL); + frame_unref (f); + } +} + +static void on_render_address (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + frame *f; + + gtk_tree_model_get (tree_model, iter, S_FRAME, &f, -1); + if (f) + { + g_object_set (cell, "text", f->address, NULL); + frame_unref (f); } + else + { + gint thread_id; + gchar *thread_label;
- g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL); - g_list_free(rows); + gtk_tree_model_get (model, iter, S_THREAD_ID, &thread_id, -1); + thread_label = g_strdup_printf(_("Thread %i"), thread_id); + g_object_set (cell, "text", thread_label, NULL); + g_free(thread_label); + } }
/* * inits stack trace tree */ -GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf) +GtkWidget* stree_init(move_to_line_cb ml, select_thread_cb st, select_frame_cb sf) { GtkTreeViewColumn *column; GtkCellRenderer *renderer;
move_to_line = ml; + select_thread = st; select_frame = sf;
/* create tree view */ store = gtk_tree_store_new ( S_N_COLUMNS, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT); + STREE_TYPE_FRAME, /* frame */ + G_TYPE_INT /* thread ID */, + G_TYPE_BOOLEAN /* active */); model = GTK_TREE_MODEL(store); tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)); @@ -350,7 +382,7 @@ GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf) gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree), FALSE); /* connect signals */ - g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed", G_CALLBACK (on_selection_changed), NULL); + g_signal_connect(G_OBJECT(tree), "cursor-changed", G_CALLBACK (on_cursor_changed), NULL);
/* for clicking on already selected frame */ g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(on_msgwin_button_press), NULL); @@ -359,7 +391,7 @@ GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf)
/* creating columns */ /* address */ - column = gtk_tree_view_column_new(); + column_address = column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, _("Address"));
renderer_arrow = cell_renderer_frame_icon_new (); @@ -372,67 +404,59 @@ GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf)
renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start(column, renderer, TRUE); - gtk_tree_view_column_set_attributes(column, renderer, "text", S_ADRESS, NULL); + gtk_tree_view_column_set_cell_data_func(column, renderer, on_render_address, NULL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
/* function */ renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Function"), renderer, "text", S_FUNCTION, NULL); + column = gtk_tree_view_column_new_with_attributes (_("Function"), renderer, NULL); + gtk_tree_view_column_set_cell_data_func(column, renderer, on_render_function, NULL, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); /* file */ renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("File"), renderer, NULL); + column_filepath = column = gtk_tree_view_column_new_with_attributes (_("File"), renderer, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); gtk_tree_view_column_set_cell_data_func(column, renderer, on_render_filename, NULL, NULL); /* line */ renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Line"), renderer, "text", S_LINE, NULL); + column = gtk_tree_view_column_new_with_attributes (_("Line"), renderer, NULL); gtk_tree_view_column_set_cell_data_func(column, renderer, on_render_line, NULL, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
/* Last invisible column */ - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", S_LAST_VISIBLE, NULL); + column = gtk_tree_view_column_new (); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
- /* create threads hash table */ - threads = g_hash_table_new_full( - g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify)gtk_tree_row_reference_free - ); - return tree; }
/* - * add frame to the tree view + * add frames to the tree view */ -void stree_add(frame *f) +void stree_add(GList *frames) { - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); - GtkTreeIter frame_iter; GtkTreeIter thread_iter; - GtkTreePath *path = gtk_tree_row_reference_get_path(reference); - gtk_tree_model_get_iter(model, &thread_iter, path); - gtk_tree_path_free(path); + GList *item;
- gtk_tree_store_insert_before(store, &frame_iter, &thread_iter, 0); + g_object_ref (model); + gtk_tree_view_set_model (GTK_TREE_VIEW (tree), NULL);
- gtk_tree_store_set (store, &frame_iter, - S_ADRESS, f->address, - S_FUNCTION, f->function, - S_FILEPATH, f->file, - S_LINE, f->line, - S_HAVE_SOURCE, f->have_source, - -1); + find_thread_iter (active_thread_id, &thread_iter); + /* prepending is a *lot* faster than appending, so prepend with a reversed data set */ + for (item = g_list_last (frames); item; item = item->prev) + { + gtk_tree_store_insert_with_values (store, NULL, &thread_iter, 0, + S_FRAME, item->data, -1); + } + + gtk_tree_view_set_model (GTK_TREE_VIEW (tree), model); + g_object_unref (model); }
/* @@ -441,7 +465,6 @@ void stree_add(frame *f) void stree_clear(void) { gtk_tree_store_clear(store); - g_hash_table_remove_all(threads); }
/* @@ -449,17 +472,12 @@ void stree_clear(void) */ void stree_select_first_frame(gboolean make_active) { - GtkTreeRowReference *reference; GtkTreeIter thread_iter, frame_iter; - GtkTreePath *active_path;
gtk_tree_view_expand_all(GTK_TREE_VIEW(tree)); - - reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); - active_path = gtk_tree_row_reference_get_path(reference); - gtk_tree_model_get_iter(model, &thread_iter, active_path); - gtk_tree_path_free(active_path); - if(gtk_tree_model_iter_children(model, &frame_iter, &thread_iter)) + + if (find_thread_iter (active_thread_id, &thread_iter) && + gtk_tree_model_iter_children(model, &frame_iter, &thread_iter)) { GtkTreePath* path;
@@ -471,9 +489,7 @@ void stree_select_first_frame(gboolean make_active)
path = gtk_tree_model_get_path(model, &frame_iter);
- gtk_tree_selection_select_path ( - gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), - path); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree), path, NULL, FALSE);
gtk_tree_path_free(path); } @@ -484,11 +500,6 @@ void stree_select_first_frame(gboolean make_active) */ void stree_destroy(void) { - if (threads) - { - g_hash_table_destroy(threads); - threads = NULL; - } }
/* @@ -496,9 +507,6 @@ void stree_destroy(void) */ void stree_add_thread(int thread_id) { - gchar *thread_label; - GtkTreePath *tpath; - GtkTreeRowReference *reference; GtkTreeIter thread_iter, new_thread_iter;
if (gtk_tree_model_get_iter_first(model, &thread_iter)) @@ -507,7 +515,7 @@ void stree_add_thread(int thread_id) do { int existing_thread_id; - gtk_tree_model_get(model, &thread_iter, S_THREAD_ID, &existing_thread_id); + gtk_tree_model_get(model, &thread_iter, S_THREAD_ID, &existing_thread_id, -1); if (existing_thread_id > thread_id) { consecutive = &thread_iter; @@ -530,17 +538,10 @@ void stree_add_thread(int thread_id) gtk_tree_store_append (store, &new_thread_iter, NULL); }
- thread_label = g_strdup_printf(_("Thread %i"), thread_id); gtk_tree_store_set (store, &new_thread_iter, - S_ADRESS, thread_label, + S_FRAME, NULL, S_THREAD_ID, thread_id, -1); - g_free(thread_label); - - tpath = gtk_tree_model_get_path(model, &new_thread_iter); - reference = gtk_tree_row_reference_new(model, tpath); - g_hash_table_insert(threads, (gpointer)(long)thread_id,(gpointer)reference); - gtk_tree_path_free(tpath); }
/* @@ -548,17 +549,10 @@ void stree_add_thread(int thread_id) */ void stree_remove_thread(int thread_id) { - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)(glong)thread_id); - GtkTreePath *tpath = gtk_tree_row_reference_get_path(reference); - GtkTreeIter iter; - gtk_tree_model_get_iter(model, &iter, tpath); - - gtk_tree_store_remove(store, &iter); - - g_hash_table_remove(threads, (gpointer)(glong)thread_id);
- gtk_tree_path_free(tpath); + if (find_thread_iter (thread_id, &iter)) + gtk_tree_store_remove(store, &iter); }
/* @@ -566,14 +560,11 @@ void stree_remove_thread(int thread_id) */ void stree_remove_frames(void) { - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); GtkTreeIter child; GtkTreeIter thread_iter; - GtkTreePath *tpath = gtk_tree_row_reference_get_path(reference); - gtk_tree_model_get_iter(model, &thread_iter, tpath); - gtk_tree_path_free(tpath);
- if (gtk_tree_model_iter_children(model, &child, &thread_iter)) + if (find_thread_iter (active_thread_id, &thread_iter) && + gtk_tree_model_iter_children(model, &child, &thread_iter)) { while(gtk_tree_store_remove(GTK_TREE_STORE(model), &child)) ;
Modified: debugger/src/stree.h 4 lines changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -28,10 +28,10 @@ #include "breakpoints.h" #include "debug_module.h"
-GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf); +GtkWidget* stree_init(move_to_line_cb ml, select_thread_cb st, select_frame_cb sf); void stree_destroy(void);
-void stree_add(frame *f); +void stree_add(GList *frames); void stree_clear(void);
void stree_add_thread(int thread_id);
Modified: debugger/src/watch_model.c 4 lines changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -476,9 +476,9 @@ GList *get_root_items(GtkTreeView *tree) -1); if (strlen(name)) - names = g_list_append(names, name); + names = g_list_prepend(names, name); } while (gtk_tree_model_iter_next(model, &child)); - return names; + return g_list_reverse(names); }
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org