EDI -> DEBUGPANEL -> GDB INTEGRATION -> START

Reviewers: ajwillia.ms

Reviewed By: ajwillia.ms

Subscribers: bu5hm4n, ajwillia.ms

Differential Revision: https://phab.enlightenment.org/D4822
This commit is contained in:
Al Poole 2017-04-28 22:01:04 +01:00 committed by Andy Williams
parent cfe08f0756
commit 415ab788da
4 changed files with 486 additions and 8 deletions

View File

@ -31,6 +31,7 @@ edi_file.h \
edi_logpanel.h \
edi_searchpanel.h \
edi_consolepanel.h \
edi_debugpanel.h \
mainview/edi_mainview_item.h \
mainview/edi_mainview.h
@ -50,6 +51,7 @@ edi_file.c \
edi_logpanel.c \
edi_searchpanel.c \
edi_consolepanel.c \
edi_debugpanel.c \
mainview/edi_mainview_item.c \
mainview/edi_mainview.c \
edi_main.c \

376
src/bin/edi_debugpanel.c Normal file
View File

@ -0,0 +1,376 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eo.h>
#include <Eina.h>
#include <Elementary.h>
#include "edi_debugpanel.h"
#include "edi_config.h"
#include "edi_private.h"
static Ecore_Exe *_debug_exe = NULL;
static Evas_Object *_info_widget, *_entry_widget, *_button_start, *_button_quit;
static Evas_Object *_button_int, *_button_term;
static Elm_Code *_debug_output;
static void
_edi_debugpanel_line_cb(void *data EINA_UNUSED, const Efl_Event *event)
{
Elm_Code_Line *line;
line = (Elm_Code_Line *)event->info;
if (line->data)
line->status = ELM_CODE_STATUS_TYPE_ERROR;
}
static Eina_Bool
_edi_debugpanel_config_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
elm_code_widget_font_set(_info_widget, _edi_project_config->font.name, _edi_project_config->font.size);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_debugpanel_stdout_handler(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Ecore_Exe_Event_Data *ev;
char buf[65535];
char *pos, *start, *end = NULL;
ev = event;
if (ev)
{
if (ev->size >= (int)(sizeof(buf) -2)) return ECORE_CALLBACK_DONE;
snprintf(buf, ev->size + 1, "%s", (char *)ev->data);
pos = buf;
start = pos;
if (*start == '\n') start++;
while (*pos++ != '\0')
{
if (*pos == '\n')
end = pos;
if (start && end)
{
elm_code_file_line_append(_debug_output->file, start, end - start, NULL);
start = end + 1;
end = NULL;
}
}
}
// FIXME: elm_code reneder hack
elm_code_callback_fire(_debug_output->file->parent, &ELM_CODE_EVENT_FILE_LOAD_DONE, _debug_output->file);
return ECORE_CALLBACK_DONE;
}
static void
_edi_debugpanel_keypress_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Key_Down *event;
const char *text;
char *command;
Eina_Bool res;
event = event_info;
if (!event) return;
if (!event->key) return;
if (!strcmp(event->key, "Return"))
{
if (!_debug_exe) return;
text = elm_object_part_text_get(_entry_widget, NULL);
if (strlen(text))
{
command = malloc(strlen(text) + 2);
snprintf(command, strlen(text) + 2, "%s\n", text);
res = ecore_exe_send(_debug_exe, command, strlen(command));
if (res)
elm_code_file_line_append(_debug_output->file, command, strlen(command) - 1, NULL);
free(command);
}
elm_object_part_text_set(_entry_widget, NULL, "");
}
}
/* Get the process ID of the child process being debugged in *our* session */
static int
_edi_debug_process_id(void)
{
Eina_List *files, *l;
const char *program_name, *temp_name;
char path[PATH_MAX];
char buf[4096];
char *p, *name, *end;
FILE *f;
int count, my_pid, parent_pid, pid, child_pid = -1;
if (!_edi_project_config->launch.path)
return -1;
if (!_debug_exe) return -1;
my_pid = ecore_exe_pid_get(_debug_exe);
program_name = ecore_file_file_get(_edi_project_config->launch.path);
files = ecore_file_ls("/proc");
EINA_LIST_FOREACH(files, l, name)
{
pid = atoi(name);
if (!pid) continue;
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
f = fopen(path, "r");
if (!f) continue;
fgets(buf, sizeof(buf), f);
fclose(f);
temp_name = ecore_file_file_get(buf);
if (!strcmp(temp_name, program_name))
{
parent_pid = 0;
// Match success - program name with pid.
child_pid = pid;
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
f = fopen(path, "r");
if (f)
{
count = 0;
fgets(buf, sizeof(buf), f);
p = buf;
while (*p++ != '\0')
{
if (*p++ == ' ') count++;
if (count == 3) break;
}
end = strchr(p, ' ');
if (end)
{
*end = '\0';
// parent pid matches - right process.
parent_pid = atoi(p);
}
fclose(f);
}
if (parent_pid == my_pid)
break;
}
}
if (files)
eina_list_free(files);
return child_pid;
}
static void
_edi_debugpanel_bt_sigterm_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
pid_t pid;
pid = _edi_debug_process_id();
if (pid <= 0) return;
kill(pid, SIGTERM);
}
static void
_edi_debugpanel_bt_sigint_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
pid_t pid;
pid = _edi_debug_process_id();
if (pid <= 0) return;
kill(pid, SIGINT);
}
static void
_edi_debugpanel_button_quit_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
edi_debugpanel_stop();
}
static void
_edi_debugpanel_button_start_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
edi_debugpanel_start();
}
static Eina_Bool
_edi_debug_active_check_cb(void *data EINA_UNUSED)
{
int pid = ecore_exe_pid_get(_debug_exe);
if (pid == -1)
{
if (_debug_exe) ecore_exe_free(_debug_exe);
_debug_exe = NULL;
elm_object_disabled_set(_button_quit, EINA_TRUE);
elm_object_disabled_set(_button_start, EINA_FALSE);
elm_object_disabled_set(_button_int, EINA_TRUE);
elm_object_disabled_set(_button_term, EINA_TRUE);
}
return ECORE_CALLBACK_RENEW;
}
void edi_debugpanel_stop(void)
{
int pid;
if (_debug_exe)
ecore_exe_terminate(_debug_exe);
pid = ecore_exe_pid_get(_debug_exe);
if (pid != -1)
ecore_exe_quit(_debug_exe);
if (_debug_exe) ecore_exe_free(_debug_exe);
_debug_exe = NULL;
elm_object_disabled_set(_button_quit, EINA_TRUE);
elm_object_disabled_set(_button_int, EINA_TRUE);
elm_object_disabled_set(_button_term, EINA_TRUE);
}
void edi_debugpanel_start(void)
{
char cmd[1024];
char *args;
int len;
const char *fmt = "set args %s\n";
if (!_edi_project_config->launch.path)
{
edi_launcher_config_missing();
return;
}
if (_debug_exe) return;
snprintf(cmd, sizeof(cmd), "gdb %s", _edi_project_config->launch.path);
_debug_exe = ecore_exe_pipe_run(cmd, ECORE_EXE_PIPE_WRITE |
ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_READ, NULL);
ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _debugpanel_stdout_handler, NULL);
elm_object_disabled_set(_button_int, EINA_FALSE);
elm_object_disabled_set(_button_term, EINA_FALSE);
elm_object_disabled_set(_button_quit, EINA_FALSE);
if (_edi_project_config->launch.args)
{
len = strlen(fmt) + strlen(_edi_project_config->launch.args) + 1;
args = malloc(len);
snprintf(args, len, fmt, _edi_project_config->launch.args);
ecore_exe_send(_debug_exe, args, strlen(args));
free(args);
}
ecore_exe_send(_debug_exe, "run\n", 4);
elm_object_disabled_set(_button_start, EINA_TRUE);
}
void edi_debugpanel_add(Evas_Object *parent)
{
Evas_Object *table, *entry, *bt_term, *bt_int, *bt_start, *bt_quit;
Evas_Object *separator;
Evas_Object *ico_start, *ico_quit, *ico_int, *ico_term;
Elm_Code_Widget *widget;
Elm_Code *code;
Ecore_Timer *timer;
code = elm_code_create();
widget = elm_code_widget_add(parent, code);
elm_obj_code_widget_font_set(widget, _edi_project_config->font.name, _edi_project_config->font.size);
elm_obj_code_widget_gravity_set(widget, 0.0, 1.0);
efl_event_callback_add(widget, &ELM_CODE_EVENT_LINE_LOAD_DONE, _edi_debugpanel_line_cb, NULL);
evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(widget);
table = elm_table_add(parent);
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, 0);
separator = elm_separator_add(parent);
elm_separator_horizontal_set(separator, EINA_FALSE);
evas_object_show(separator);
_button_term = bt_term = elm_button_add(parent);
ico_term = elm_icon_add(parent);
elm_icon_standard_set(ico_term, "media-playback-stop");
elm_object_part_content_set(bt_term, "icon", ico_term);
elm_object_tooltip_text_set(bt_term, "Send SIGTERM");
elm_object_disabled_set(bt_term, EINA_TRUE);
evas_object_smart_callback_add(bt_term, "clicked", _edi_debugpanel_bt_sigterm_cb, NULL);
evas_object_show(bt_term);
_button_int = bt_int = elm_button_add(parent);
ico_int = elm_icon_add(parent);
elm_icon_standard_set(ico_int, "media-playback-pause");
elm_object_part_content_set(bt_int, "icon", ico_int);
elm_object_tooltip_text_set(bt_int, "Send SIGINT");
elm_object_disabled_set(bt_int, EINA_TRUE);
evas_object_smart_callback_add(bt_int, "clicked", _edi_debugpanel_bt_sigint_cb, NULL);
evas_object_show(bt_int);
_button_start = bt_start = elm_button_add(parent);
ico_start = elm_icon_add(parent);
elm_icon_standard_set(ico_start, "media-playback-start");
elm_object_tooltip_text_set(bt_start, "Start Debugging");
elm_object_part_content_set(bt_start, "icon", ico_start);
evas_object_smart_callback_add(bt_start, "clicked", _edi_debugpanel_button_start_cb, NULL);
evas_object_show(bt_start);
_button_quit = bt_quit = elm_button_add(parent);
ico_quit = elm_icon_add(parent);
elm_icon_standard_set(ico_quit, "application-exit");
elm_object_part_content_set(bt_quit, "icon", ico_quit);
elm_object_tooltip_text_set(bt_quit, "Stop Debugging");
elm_object_disabled_set(bt_quit, EINA_TRUE);
evas_object_smart_callback_add(bt_quit, "clicked", _edi_debugpanel_button_quit_cb, NULL);
evas_object_show(bt_quit);
entry = elm_entry_add(parent);
elm_entry_single_line_set(entry, EINA_TRUE);
elm_entry_scrollable_set(entry, EINA_TRUE);
elm_entry_editable_set(entry, EINA_TRUE);
evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_event_callback_add(entry, EVAS_CALLBACK_KEY_DOWN, _edi_debugpanel_keypress_cb, NULL);
evas_object_show(entry);
elm_table_pack(table, entry, 0, 0, 1, 1);
elm_table_pack(table, bt_term, 1, 0, 1, 1);
elm_table_pack(table, bt_int, 2, 0, 1, 1);
elm_table_pack(table, separator, 3, 0, 1, 1);
elm_table_pack(table, bt_start, 4, 0, 1, 1);
elm_table_pack(table, bt_quit, 5, 0, 1, 1);
evas_object_show(table);
_debug_output = code;
_info_widget = widget;
_entry_widget = entry;
timer = ecore_timer_add(1.0, _edi_debug_active_check_cb, NULL);
(void) timer;
elm_box_pack_end(parent, widget);
elm_box_pack_end(parent, table);
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_debugpanel_config_changed, NULL);
}

58
src/bin/edi_debugpanel.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef EDI_DEBUGPANEL_H_
# define EDI_DEBUGPANEL_H_
#include <Elementary.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* @brief These routines are used for managing the Edi debug panel.
*/
/**
* @brief UI management functions.
* @defgroup UI
*
* @{
*
* Initialisation and management of the debugpanel UI
*
*/
/**
* Initialize a new Edi debugpanel and add it to the parent panel.
*
* @param parent The panel into which the panel will be loaded.
*
* @ingroup UI
*/
void edi_debugpanel_add(Evas_Object *parent);
/**
* Start a new debugging session
*
* @ingroup UI
*/
void edi_debugpanel_start();
/**
* Stop existing debugging session
*
* @ingroup UI
*/
void edi_debugpanel_stop();
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* EDI_DEBUGPANEL_H_ */

View File

@ -21,6 +21,7 @@
#include "edi_logpanel.h"
#include "edi_consolepanel.h"
#include "edi_searchpanel.h"
#include "edi_debugpanel.h"
#include "mainview/edi_mainview.h"
#include "screens/edi_screens.h"
@ -42,8 +43,8 @@ typedef struct _Edi_Panel_Slide_Effect
#define COPYRIGHT "Copyright © 2014-2015 Andy Williams <andy@andyilliams.me> and various contributors (see AUTHORS)."
static Evas_Object *_edi_toolbar, *_edi_leftpanes, *_edi_bottompanes;
static Evas_Object *_edi_logpanel, *_edi_consolepanel, *_edi_testpanel, *_edi_searchpanel, *_edi_taskspanel;
static Elm_Object_Item *_edi_logpanel_item, *_edi_consolepanel_item, *_edi_testpanel_item, *_edi_searchpanel_item, *_edi_taskspanel_item;
static Evas_Object *_edi_logpanel, *_edi_consolepanel, *_edi_testpanel, *_edi_searchpanel, *_edi_taskspanel, *_edi_debugpanel;
static Elm_Object_Item *_edi_logpanel_item, *_edi_consolepanel_item, *_edi_testpanel_item, *_edi_searchpanel_item, *_edi_taskspanel_item, *_edi_debugpanel_item;
static Elm_Object_Item *_edi_selected_bottompanel;
static Evas_Object *_edi_filepanel, *_edi_filepanel_icon;
@ -116,6 +117,8 @@ _edi_panel_tab_for_index(int index)
return _edi_searchpanel;
if (index == 4)
return _edi_taskspanel;
if (index == 5)
return _edi_debugpanel;
return _edi_logpanel;
}
@ -260,7 +263,7 @@ _edi_toggle_panel(void *data, Evas_Object *obj, void *event_info)
if (obj)
elm_object_focus_set(obj, EINA_FALSE);
for (c = 0; c <= 4; c++)
for (c = 0; c <= 5; c++)
if (c != index)
evas_object_hide(_edi_panel_tab_for_index(c));
@ -324,6 +327,13 @@ edi_taskspanel_show()
elm_toolbar_item_selected_set(_edi_taskspanel_item, EINA_TRUE);
}
void
edi_debugpanel_show()
{
if (_edi_selected_bottompanel != _edi_debugpanel_item)
elm_toolbar_item_selected_set(_edi_debugpanel_item, EINA_TRUE);
}
static Evas_Object *
edi_content_setup(Evas_Object *win, const char *path)
{
@ -344,6 +354,7 @@ edi_content_setup(Evas_Object *win, const char *path)
_edi_testpanel = elm_box_add(win);
_edi_searchpanel = elm_box_add(win);
_edi_taskspanel = elm_box_add(win);
_edi_debugpanel = elm_box_add(win);
// add main content
content_out = elm_box_add(win);
@ -418,6 +429,8 @@ edi_content_setup(Evas_Object *win, const char *path)
_edi_toggle_panel, "3");
_edi_taskspanel_item = elm_toolbar_item_append(tb, "stock_up", "Tasks",
_edi_toggle_panel, "4");
_edi_debugpanel_item = elm_toolbar_item_append(tb, "stock_up", "Debug",
_edi_toggle_panel, "5");
// add lower panel panes
logpanels = elm_table_add(logpane);
@ -451,6 +464,12 @@ edi_content_setup(Evas_Object *win, const char *path)
edi_taskspanel_add(_edi_taskspanel);
elm_table_pack(logpanels, _edi_taskspanel, 0, 0, 1, 1);
edi_debugpanel_add(_edi_debugpanel);
elm_table_pack(logpanels, _edi_debugpanel, 0, 0, 1, 1);
evas_object_size_hint_weight_set(_edi_debugpanel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(_edi_debugpanel, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_part_content_set(logpane, "bottom", logpanels);
if (_edi_project_config->gui.bottomopen)
@ -476,6 +495,11 @@ edi_content_setup(Evas_Object *win, const char *path)
elm_toolbar_item_icon_set(_edi_taskspanel_item, "stock_down");
_edi_selected_bottompanel = _edi_taskspanel_item;
}
else if (_edi_project_config->gui.bottomtab == 5)
{
elm_toolbar_item_icon_set(_edi_debugpanel_item, "stock_down");
_edi_selected_bottompanel = _edi_debugpanel_item;
}
else
{
elm_toolbar_item_icon_set(_edi_logpanel_item, "stock_down");
@ -663,10 +687,10 @@ _tb_run_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSE
}
static void
_tb_clean_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
_tb_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (_edi_build_prep(obj))
edi_builder_clean();
edi_debugpanel_show();
edi_debugpanel_start();
}
static void
@ -759,7 +783,7 @@ static void
_edi_menu_quit_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
elm_exit();
edi_close();
}
static void
@ -861,6 +885,14 @@ _edi_menu_clean_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
edi_builder_clean();
}
static void
_edi_menu_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
edi_debugpanel_show();
edi_debugpanel_start();
}
static void
_edi_menu_website_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
@ -914,6 +946,7 @@ _edi_menu_setup(Evas_Object *obj)
elm_menu_item_add(menu, menu_it, "system-run", "Build", _edi_menu_build_cb, NULL);
elm_menu_item_add(menu, menu_it, "media-record", "Test", _edi_menu_test_cb, NULL);
elm_menu_item_add(menu, menu_it, "media-playback-start", "Run", _edi_menu_run_cb, NULL);
elm_menu_item_add(menu, menu_it, "utilities-terminal", "Debug", _edi_menu_debug_cb, NULL);
elm_menu_item_add(menu, menu_it, "edit-clear", "Clean", _edi_menu_clean_cb, NULL);
menu_it = elm_menu_item_add(menu, NULL, NULL, "Help", NULL, NULL);
@ -979,7 +1012,7 @@ edi_toolbar_setup(Evas_Object *win)
_edi_toolbar_item_add(tb, "system-run", "Build", _tb_build_cb);
_edi_toolbar_item_add(tb, "media-record", "Test", _tb_test_cb);
_edi_toolbar_item_add(tb, "media-playback-start", "Run", _tb_run_cb);
_edi_toolbar_item_add(tb, "edit-clear", "Clean", _tb_clean_cb);
_edi_toolbar_item_add(tb, "utilities-terminal", "Debug", _tb_debug_cb);
tb_it = elm_toolbar_item_append(tb, "separator", "", NULL, NULL);
elm_toolbar_item_separator_set(tb_it, EINA_TRUE);
@ -1125,6 +1158,12 @@ _edi_open_tabs()
}
}
static void
_win_delete_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
edi_close();
}
Eina_Bool
edi_open(const char *inputpath)
{
@ -1199,6 +1238,8 @@ edi_open(const char *inputpath)
_edi_open_tabs();
_edi_icon_update();
evas_object_smart_callback_add(win, "delete,request", _win_delete_cb, NULL);
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_config_changed, NULL);
ecore_event_handler_add(EDI_EVENT_TAB_CHANGED, _edi_tab_changed, NULL);
ecore_event_handler_add(EDI_EVENT_FILE_CHANGED, _edi_file_changed, NULL);
@ -1222,6 +1263,7 @@ edi_open_file(const char *filepath)
void
edi_close()
{
edi_debugpanel_stop();
elm_exit();
}