forked from enlightenment/edi
edi_debug: improve debugging support.
This improves support and simplifies some of the debugging tasks.
This commit is contained in:
parent
ae3b0c2f57
commit
29c5ecb538
|
@ -85,6 +85,12 @@ _edi_project_config_dir_get(void)
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_edi_project_config_debug_command_get(void)
|
||||||
|
{
|
||||||
|
return _edi_project_config->debug_command;
|
||||||
|
}
|
||||||
|
|
||||||
/* local functions */
|
/* local functions */
|
||||||
static Edi_Config_DD *
|
static Edi_Config_DD *
|
||||||
_edi_config_descriptor_new(const char *name, int size)
|
_edi_config_descriptor_new(const char *name, int size)
|
||||||
|
@ -278,6 +284,7 @@ _edi_config_init(void)
|
||||||
|
|
||||||
EDI_CONFIG_VAL(D, T, launch.path, EET_T_STRING);
|
EDI_CONFIG_VAL(D, T, launch.path, EET_T_STRING);
|
||||||
EDI_CONFIG_VAL(D, T, launch.args, EET_T_STRING);
|
EDI_CONFIG_VAL(D, T, launch.args, EET_T_STRING);
|
||||||
|
EDI_CONFIG_VAL(D, T, debug_command, EET_T_STRING);
|
||||||
EDI_CONFIG_VAL(D, T, user_fullname, EET_T_STRING);
|
EDI_CONFIG_VAL(D, T, user_fullname, EET_T_STRING);
|
||||||
EDI_CONFIG_VAL(D, T, user_email, EET_T_STRING);
|
EDI_CONFIG_VAL(D, T, user_email, EET_T_STRING);
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ struct _Edi_Project_Config
|
||||||
} gui;
|
} gui;
|
||||||
|
|
||||||
Edi_Project_Config_Launch launch;
|
Edi_Project_Config_Launch launch;
|
||||||
|
Eina_Stringshare *debug_command;
|
||||||
Eina_Stringshare *user_fullname;
|
Eina_Stringshare *user_fullname;
|
||||||
Eina_Stringshare *user_email;
|
Eina_Stringshare *user_email;
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ extern Edi_Project_Config *_edi_project_config;
|
||||||
Eina_Bool _edi_config_init(void);
|
Eina_Bool _edi_config_init(void);
|
||||||
Eina_Bool _edi_config_shutdown(void);
|
Eina_Bool _edi_config_shutdown(void);
|
||||||
const char *_edi_config_dir_get(void);
|
const char *_edi_config_dir_get(void);
|
||||||
|
const char *_edi_project_config_debug_command_get(void);
|
||||||
|
|
||||||
// Global configuration handling
|
// Global configuration handling
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/user.h>
|
||||||
|
#endif
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Eo.h>
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <Elementary.h>
|
||||||
|
|
||||||
|
#include "edi_debug.h"
|
||||||
|
#include "edi_config.h"
|
||||||
|
#include "edi_private.h"
|
||||||
|
|
||||||
|
Edi_Debug_Tool _debugger_tools[] = {
|
||||||
|
{ "gdb", "gdb", NULL, "run\n", "c\n", "set args %s" },
|
||||||
|
{ "lldb", "lldb", NULL, "run\n", "c\n", "settings set target.run-args %s" },
|
||||||
|
{ "pdb", "pdb", NULL, NULL, "c\n", "run %s" },
|
||||||
|
{ "memcheck", "valgrind", "--tool=memcheck", NULL, NULL, NULL },
|
||||||
|
{ "massif", "valgrind", "--tool=massif", NULL, NULL, NULL },
|
||||||
|
{ "callgrind", "valgrind", "--tool=callgrind", NULL, NULL, NULL },
|
||||||
|
{ NULL, NULL, NULL, NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
Edi_Debug *_debugger = NULL;
|
||||||
|
|
||||||
|
Edi_Debug *edi_debug_new(void)
|
||||||
|
{
|
||||||
|
_debugger = calloc(1, sizeof(Edi_Debug));
|
||||||
|
return _debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
Edi_Debug *edi_debug_get(void)
|
||||||
|
{
|
||||||
|
return _debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
Edi_Debug_Tool *edi_debug_tools_get(void)
|
||||||
|
{
|
||||||
|
return _debugger_tools;
|
||||||
|
}
|
||||||
|
|
||||||
|
Edi_Debug_Tool *edi_debug_tool_get(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; _debugger_tools[i].name && name; i++)
|
||||||
|
{
|
||||||
|
if (!strcmp(_debugger_tools[i].name, name) &&
|
||||||
|
ecore_file_app_installed(_debugger_tools[i].exec))
|
||||||
|
return &_debugger_tools[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback, but not installed.
|
||||||
|
if (name || !ecore_file_app_installed(_debugger_tools[0].exec))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Fallback to first.
|
||||||
|
return &_debugger_tools[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
static long int
|
||||||
|
_sysctlfromname(const char *name, void *mib, int depth, size_t *len)
|
||||||
|
{
|
||||||
|
long int result;
|
||||||
|
|
||||||
|
if (sysctlnametomib(name, mib, len) < 0) return -1;
|
||||||
|
*len = sizeof(result);
|
||||||
|
if (sysctl(mib, depth, &result, len, NULL, 0) < 0) return -1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get the process ID of the child process being debugged in *our* session */
|
||||||
|
int edi_debug_process_id(Edi_Debug *debugger)
|
||||||
|
{
|
||||||
|
int my_pid, child_pid = -1;
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
||||||
|
struct kinfo_proc kp;
|
||||||
|
int mib[6];
|
||||||
|
size_t len;
|
||||||
|
int max_pid, i;
|
||||||
|
|
||||||
|
if (!debugger->program_name) return -1;
|
||||||
|
if (!debugger->exe) return -1;
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
len = sizeof(max_pid);
|
||||||
|
max_pid = _sysctlfromname("kern.lastpid", mib, 2, &len);
|
||||||
|
#elif defined(PID_MAX)
|
||||||
|
max_pid = PID_MAX;
|
||||||
|
#else
|
||||||
|
max_pid = 99999;
|
||||||
|
#endif
|
||||||
|
my_pid = ecore_exe_pid_get(debugger->exe);
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||||
|
if (sysctlnametomib("kern.proc.pid", mib, &len) < 0) return -1;
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_PROC;
|
||||||
|
mib[2] = KERN_PROC_PID;
|
||||||
|
mib[4] = sizeof(struct kinfo_proc);
|
||||||
|
mib[5] = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = my_pid; i <= max_pid; i++)
|
||||||
|
{
|
||||||
|
mib[3] = i;
|
||||||
|
len = sizeof(kp);
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
if (sysctl(mib, 6, &kp, &len, NULL, 0) == -1) continue;
|
||||||
|
#else
|
||||||
|
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
if (kp.ki_ppid != my_pid) continue;
|
||||||
|
if (strcmp(debugger->program_name, kp.ki_comm)) continue;
|
||||||
|
child_pid = kp.ki_pid;
|
||||||
|
if (kp.ki_stat == SRUN || kp.ki_stat == SSLEEP)
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
||||||
|
else
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
if (kp.p_ppid != my_pid) continue;
|
||||||
|
if (strcmp(debugger->program_name, kp.p_comm)) continue;
|
||||||
|
child_pid = kp.p_pid;
|
||||||
|
|
||||||
|
if (kp.p_stat == SRUN || kp.p_stat == SSLEEP)
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
||||||
|
else
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
||||||
|
#else /* APPLE */
|
||||||
|
if (kp.kp_proc.p_oppid != my_pid) continue;
|
||||||
|
if (strcmp(debugger->program_name, kp.kp_proc.p_comm)) continue;
|
||||||
|
child_pid = kp.kp_proc.p_pid;
|
||||||
|
if (kp.kp_proc.p_stat == SRUN || kp.kp_proc.p_stat == SSLEEP)
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
||||||
|
else
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Eina_List *files, *l;
|
||||||
|
const char *temp_name;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char buf[4096];
|
||||||
|
char *p, *name, *end;
|
||||||
|
FILE *f;
|
||||||
|
int count, parent_pid, pid;
|
||||||
|
|
||||||
|
if (!debugger->program_name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!debugger->exe) return -1;
|
||||||
|
|
||||||
|
my_pid = ecore_exe_pid_get(debugger->exe);
|
||||||
|
|
||||||
|
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;
|
||||||
|
p = fgets(buf, sizeof(buf), f);
|
||||||
|
fclose(f);
|
||||||
|
if (!p) continue;
|
||||||
|
temp_name = ecore_file_file_get(buf);
|
||||||
|
if (!strcmp(temp_name, debugger->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;
|
||||||
|
p = fgets(buf, sizeof(buf), f);
|
||||||
|
while (*p++ != '\0')
|
||||||
|
{
|
||||||
|
if (p[0] == ' ') { count++; p++; }
|
||||||
|
if (count == 2)
|
||||||
|
{
|
||||||
|
if (p[0] == 'S' || p[0] == 'R')
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
||||||
|
else
|
||||||
|
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
return child_pid;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
#ifndef EDI_DEBUG_H_
|
||||||
|
# define EDI_DEBUG_H_
|
||||||
|
|
||||||
|
#include <Elementary.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief These routines are used for managing debugging features.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EDI_DEBUG_PROCESS_SLEEPING = 0,
|
||||||
|
EDI_DEBUG_PROCESS_ACTIVE
|
||||||
|
} Edi_Debug_Process_State;
|
||||||
|
|
||||||
|
typedef struct _Edi_Debug_Tool {
|
||||||
|
const char *name;
|
||||||
|
const char *exec;
|
||||||
|
const char *arguments;
|
||||||
|
const char *command_start;
|
||||||
|
const char *command_continue;
|
||||||
|
const char *command_arguments;
|
||||||
|
} Edi_Debug_Tool;
|
||||||
|
|
||||||
|
typedef struct _Edi_Debug {
|
||||||
|
Edi_Debug_Tool *tool;
|
||||||
|
const char *program_name;
|
||||||
|
Ecore_Exe *exe;
|
||||||
|
char cmd[1024];
|
||||||
|
Edi_Debug_Process_State state;
|
||||||
|
} Edi_Debug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug management functions.
|
||||||
|
* @defgroup Debug
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* Initialisation and management of debugging features.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise debugger internals.
|
||||||
|
*
|
||||||
|
* @return pointer to initialized debug instance.
|
||||||
|
*
|
||||||
|
* @ingroup Debug
|
||||||
|
*/
|
||||||
|
Edi_Debug *edi_debug_new(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain pointer to initialized debug instance.
|
||||||
|
*
|
||||||
|
* @ingroup Debug
|
||||||
|
*/
|
||||||
|
Edi_Debug *edi_debug_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain process information of debugged process.
|
||||||
|
*
|
||||||
|
* @param debugger Edi_Debug instance.
|
||||||
|
*
|
||||||
|
* @return process id of debugged process that is child of running debugger.
|
||||||
|
*
|
||||||
|
* @ingroup Debug
|
||||||
|
*/
|
||||||
|
int edi_debug_process_id(Edi_Debug *debugger);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain debugging info for given program name.
|
||||||
|
*
|
||||||
|
* @param name The name of the tool used to obtain helper data for given program.
|
||||||
|
*
|
||||||
|
* @return Pointer to debugging information instance associated with its name.
|
||||||
|
*
|
||||||
|
* @ingroup Debug
|
||||||
|
*/
|
||||||
|
Edi_Debug_Tool *edi_debug_tool_get(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a pointer to the list of available debugging tools.
|
||||||
|
*
|
||||||
|
* @return Pointer to debugging information for all available tools.
|
||||||
|
*
|
||||||
|
* @ingroup Debug
|
||||||
|
*/
|
||||||
|
Edi_Debug_Tool *edi_debug_tools_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* EDI_DEBUG_H_ */
|
|
@ -2,20 +2,11 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#endif
|
|
||||||
#if defined(__OpenBSD__)
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <Eo.h>
|
#include <Eo.h>
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
#include <Elementary.h>
|
#include <Elementary.h>
|
||||||
|
|
||||||
|
#include "edi_debug.h"
|
||||||
#include "edi_debugpanel.h"
|
#include "edi_debugpanel.h"
|
||||||
#include "edi_config.h"
|
#include "edi_config.h"
|
||||||
|
|
||||||
|
@ -27,21 +18,16 @@
|
||||||
#define LIBTOOL_COMMAND "libtool"
|
#define LIBTOOL_COMMAND "libtool"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Ecore_Exe *_debug_exe = NULL;
|
|
||||||
static Evas_Object *_info_widget, *_entry_widget, *_button_start, *_button_quit;
|
static Evas_Object *_info_widget, *_entry_widget, *_button_start, *_button_quit;
|
||||||
static Evas_Object *_button_int, *_button_term;
|
static Evas_Object *_button_int, *_button_term;
|
||||||
static Elm_Code *_debug_output;
|
static Elm_Code *_debug_output;
|
||||||
|
|
||||||
#define DEBUG_PROCESS_SLEEPING 0
|
|
||||||
#define DEBUG_PROCESS_ACTIVE 1
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_debugpanel_line_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
_edi_debugpanel_line_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
||||||
{
|
{
|
||||||
Elm_Code_Line *line;
|
Elm_Code_Line *line;
|
||||||
|
|
||||||
line = (Elm_Code_Line *)event->info;
|
line = (Elm_Code_Line *)event->info;
|
||||||
|
|
||||||
if (line->data)
|
if (line->data)
|
||||||
line->status = ELM_CODE_STATUS_TYPE_ERROR;
|
line->status = ELM_CODE_STATUS_TYPE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -58,10 +44,17 @@ static Eina_Bool
|
||||||
_debugpanel_stdout_handler(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
_debugpanel_stdout_handler(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
{
|
{
|
||||||
Ecore_Exe_Event_Data *ev;
|
Ecore_Exe_Event_Data *ev;
|
||||||
|
Edi_Debug *debug;
|
||||||
int idx;
|
int idx;
|
||||||
char *start, *end = NULL;
|
char *start, *end = NULL;
|
||||||
|
|
||||||
ev = event;
|
ev = event;
|
||||||
|
|
||||||
|
debug = edi_debug_get();
|
||||||
|
|
||||||
|
if (ev->exe != debug->exe)
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
|
||||||
if (ev && ev->size)
|
if (ev && ev->size)
|
||||||
{
|
{
|
||||||
if (!ev->data) return ECORE_CALLBACK_DONE;
|
if (!ev->data) return ECORE_CALLBACK_DONE;
|
||||||
|
@ -102,6 +95,7 @@ _edi_debugpanel_keypress_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Ob
|
||||||
const char *text_markup;
|
const char *text_markup;
|
||||||
char *command, *text;
|
char *command, *text;
|
||||||
Eina_Bool res;
|
Eina_Bool res;
|
||||||
|
Edi_Debug *debug = edi_debug_get();
|
||||||
|
|
||||||
event = event_info;
|
event = event_info;
|
||||||
|
|
||||||
|
@ -111,7 +105,7 @@ _edi_debugpanel_keypress_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Ob
|
||||||
|
|
||||||
if (!strcmp(event->key, "Return"))
|
if (!strcmp(event->key, "Return"))
|
||||||
{
|
{
|
||||||
if (!_debug_exe) return;
|
if (!debug->exe) return;
|
||||||
|
|
||||||
text_markup = elm_object_part_text_get(_entry_widget, NULL);
|
text_markup = elm_object_part_text_get(_entry_widget, NULL);
|
||||||
text = elm_entry_markup_to_utf8(text_markup);
|
text = elm_entry_markup_to_utf8(text_markup);
|
||||||
|
@ -119,7 +113,7 @@ _edi_debugpanel_keypress_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Ob
|
||||||
{
|
{
|
||||||
command = malloc(strlen(text) + 2);
|
command = malloc(strlen(text) + 2);
|
||||||
snprintf(command, strlen(text) + 2, "%s\n", text);
|
snprintf(command, strlen(text) + 2, "%s\n", text);
|
||||||
res = ecore_exe_send(_debug_exe, command, strlen(command));
|
res = ecore_exe_send(debug->exe, command, strlen(command));
|
||||||
if (res)
|
if (res)
|
||||||
elm_code_file_line_append(_debug_output->file, command, strlen(command) - 1, NULL);
|
elm_code_file_line_append(_debug_output->file, command, strlen(command) - 1, NULL);
|
||||||
|
|
||||||
|
@ -130,189 +124,17 @@ _edi_debugpanel_keypress_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Ob
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
|
|
||||||
static long int
|
|
||||||
_sysctlfromname(const char *name, void *mib, int depth, size_t *len)
|
|
||||||
{
|
|
||||||
long int result;
|
|
||||||
|
|
||||||
if (sysctlnametomib(name, mib, len) < 0) return -1;
|
|
||||||
*len = sizeof(result);
|
|
||||||
if (sysctl(mib, depth, &result, len, NULL, 0) < 0) return -1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get the process ID of the child process being debugged in *our* session */
|
|
||||||
static int
|
|
||||||
_edi_debug_process_id(int *state)
|
|
||||||
{
|
|
||||||
const char *program_name;
|
|
||||||
int my_pid, child_pid = -1;
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
|
||||||
struct kinfo_proc kp;
|
|
||||||
int mib[6];
|
|
||||||
size_t len;
|
|
||||||
int max_pid, i;
|
|
||||||
|
|
||||||
if (!_edi_project_config->launch.path) return -1;
|
|
||||||
|
|
||||||
if (!_debug_exe) return -1;
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
len = sizeof(max_pid);
|
|
||||||
max_pid = _sysctlfromname("kern.lastpid", mib, 2, &len);
|
|
||||||
#elif defined(PID_MAX)
|
|
||||||
max_pid = PID_MAX;
|
|
||||||
#else
|
|
||||||
max_pid = 99999;
|
|
||||||
#endif
|
|
||||||
my_pid = ecore_exe_pid_get(_debug_exe);
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
|
||||||
if (sysctlnametomib("kern.proc.pid", mib, &len) < 0) return -1;
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_PROC;
|
|
||||||
mib[2] = KERN_PROC_PID;
|
|
||||||
mib[4] = sizeof(struct kinfo_proc);
|
|
||||||
mib[5] = 1;
|
|
||||||
#endif
|
|
||||||
program_name = ecore_file_file_get(_edi_project_config->launch.path);
|
|
||||||
|
|
||||||
for (i = my_pid; i <= max_pid; i++)
|
|
||||||
{
|
|
||||||
mib[3] = i;
|
|
||||||
len = sizeof(kp);
|
|
||||||
#if defined(__OpenBSD__)
|
|
||||||
if (sysctl(mib, 6, &kp, &len, NULL, 0) == -1) continue;
|
|
||||||
#else
|
|
||||||
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
if (kp.ki_ppid != my_pid) continue;
|
|
||||||
if (strcmp(program_name, kp.ki_comm)) continue;
|
|
||||||
child_pid = kp.ki_pid;
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
if (kp.ki_stat == SRUN || kp.ki_stat == SSLEEP)
|
|
||||||
*state = DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
*state = DEBUG_PROCESS_SLEEPING;
|
|
||||||
}
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
if (kp.p_ppid != my_pid) continue;
|
|
||||||
if (strcmp(program_name, kp.p_comm)) continue;
|
|
||||||
child_pid = kp.p_pid;
|
|
||||||
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
if (kp.p_stat == SRUN || kp.p_stat == SSLEEP)
|
|
||||||
*state = DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
*state = DEBUG_PROCESS_SLEEPING;
|
|
||||||
}
|
|
||||||
#else /* APPLE */
|
|
||||||
if (kp.kp_proc.p_oppid != my_pid) continue;
|
|
||||||
if (strcmp(program_name, kp.kp_proc.p_comm)) continue;
|
|
||||||
child_pid = kp.kp_proc.p_pid;
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
if (kp.kp_proc.p_stat == SRUN || kp.kp_proc.p_stat == SSLEEP)
|
|
||||||
*state = DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
*state = DEBUG_PROCESS_SLEEPING;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Eina_List *files, *l;
|
|
||||||
const char *temp_name;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char buf[4096];
|
|
||||||
char *p, *name, *end;
|
|
||||||
FILE *f;
|
|
||||||
int count, parent_pid, pid;
|
|
||||||
|
|
||||||
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;
|
|
||||||
p = fgets(buf, sizeof(buf), f);
|
|
||||||
fclose(f);
|
|
||||||
if (!p) continue;
|
|
||||||
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;
|
|
||||||
p = fgets(buf, sizeof(buf), f);
|
|
||||||
while (*p++ != '\0')
|
|
||||||
{
|
|
||||||
if (p[0] == ' ') { count++; p++; }
|
|
||||||
if (count == 2)
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
if (p[0] == 'S' || p[0] == 'R')
|
|
||||||
*state = DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
*state = DEBUG_PROCESS_SLEEPING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
#endif
|
|
||||||
return child_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_debugpanel_bt_sigterm_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_edi_debugpanel_bt_sigterm_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
Evas_Object *ico_int;
|
Evas_Object *ico_int;
|
||||||
|
Edi_Debug *debug;
|
||||||
|
|
||||||
pid = _edi_debug_process_id(NULL);
|
debug = edi_debug_get();
|
||||||
|
if (!debug) return;
|
||||||
|
|
||||||
|
pid = edi_debug_process_id(debug);
|
||||||
if (pid <= 0) return;
|
if (pid <= 0) return;
|
||||||
|
|
||||||
ico_int = elm_icon_add(_button_int);
|
ico_int = elm_icon_add(_button_int);
|
||||||
|
@ -323,13 +145,13 @@ _edi_debugpanel_bt_sigterm_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUS
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_debugpanel_icons_update(int state)
|
_edi_debugpanel_icons_update(Edi_Debug_Process_State state)
|
||||||
{
|
{
|
||||||
Evas_Object *ico_int;
|
Evas_Object *ico_int;
|
||||||
|
|
||||||
ico_int = elm_icon_add(_button_int);
|
ico_int = elm_icon_add(_button_int);
|
||||||
|
|
||||||
if (state == DEBUG_PROCESS_ACTIVE)
|
if (state == EDI_DEBUG_PROCESS_ACTIVE)
|
||||||
elm_icon_standard_set(ico_int, "media-playback-pause");
|
elm_icon_standard_set(ico_int, "media-playback-pause");
|
||||||
else
|
else
|
||||||
elm_icon_standard_set(ico_int, "media-playback-start");
|
elm_icon_standard_set(ico_int, "media-playback-start");
|
||||||
|
@ -341,17 +163,20 @@ static void
|
||||||
_edi_debugpanel_bt_sigint_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_edi_debugpanel_bt_sigint_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int state;
|
Edi_Debug *debug;
|
||||||
|
|
||||||
pid = _edi_debug_process_id(&state);
|
debug = edi_debug_get();
|
||||||
|
if (!debug) return;
|
||||||
|
|
||||||
|
pid = edi_debug_process_id(debug);
|
||||||
if (pid <= 0) return;
|
if (pid <= 0) return;
|
||||||
|
|
||||||
if (state == DEBUG_PROCESS_ACTIVE)
|
if (debug->state == EDI_DEBUG_PROCESS_ACTIVE)
|
||||||
kill(pid, SIGINT);
|
kill(pid, SIGINT);
|
||||||
else
|
else if (debug->tool->command_continue)
|
||||||
ecore_exe_send(_debug_exe, "c\n", 2);
|
ecore_exe_send(debug->exe, debug->tool->command_continue, strlen(debug->tool->command_continue));
|
||||||
|
|
||||||
_edi_debugpanel_icons_update(state);
|
_edi_debugpanel_icons_update(debug->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -363,18 +188,20 @@ _edi_debugpanel_button_quit_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNU
|
||||||
static void
|
static void
|
||||||
_edi_debugpanel_button_start_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
_edi_debugpanel_button_start_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
{
|
{
|
||||||
edi_debugpanel_start();
|
edi_debugpanel_start(_edi_project_config_debug_command_get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_edi_debug_active_check_cb(void *data EINA_UNUSED)
|
_edi_debug_active_check_cb(void *data EINA_UNUSED)
|
||||||
{
|
{
|
||||||
int state, pid = ecore_exe_pid_get(_debug_exe);
|
int pid;
|
||||||
|
Edi_Debug *debug = edi_debug_get();
|
||||||
|
|
||||||
|
pid = ecore_exe_pid_get(debug->exe);
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
if (_debug_exe) ecore_exe_quit(_debug_exe);
|
if (debug->exe) ecore_exe_quit(debug->exe);
|
||||||
_debug_exe = NULL;
|
debug->exe = NULL;
|
||||||
elm_object_disabled_set(_button_quit, EINA_TRUE);
|
elm_object_disabled_set(_button_quit, EINA_TRUE);
|
||||||
elm_object_disabled_set(_button_start, EINA_FALSE);
|
elm_object_disabled_set(_button_start, EINA_FALSE);
|
||||||
elm_object_disabled_set(_button_int, EINA_TRUE);
|
elm_object_disabled_set(_button_int, EINA_TRUE);
|
||||||
|
@ -382,8 +209,8 @@ _edi_debug_active_check_cb(void *data EINA_UNUSED)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_edi_debug_process_id(&state) > 0)
|
if (edi_debug_process_id(debug) > 0)
|
||||||
_edi_debugpanel_icons_update(state);
|
_edi_debugpanel_icons_update(debug->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ECORE_CALLBACK_RENEW;
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
@ -391,28 +218,61 @@ _edi_debug_active_check_cb(void *data EINA_UNUSED)
|
||||||
|
|
||||||
void edi_debugpanel_stop(void)
|
void edi_debugpanel_stop(void)
|
||||||
{
|
{
|
||||||
|
Edi_Debug *debug;
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
if (_debug_exe)
|
debug = edi_debug_get();
|
||||||
ecore_exe_terminate(_debug_exe);
|
if (!debug)
|
||||||
|
return;
|
||||||
|
|
||||||
pid = ecore_exe_pid_get(_debug_exe);
|
if (debug->exe)
|
||||||
|
ecore_exe_terminate(debug->exe);
|
||||||
|
|
||||||
|
pid = ecore_exe_pid_get(debug->exe);
|
||||||
if (pid != -1)
|
if (pid != -1)
|
||||||
ecore_exe_quit(_debug_exe);
|
ecore_exe_quit(debug->exe);
|
||||||
|
|
||||||
_debug_exe = NULL;
|
debug->exe = NULL;
|
||||||
|
|
||||||
elm_object_disabled_set(_button_quit, EINA_TRUE);
|
elm_object_disabled_set(_button_quit, EINA_TRUE);
|
||||||
elm_object_disabled_set(_button_int, EINA_TRUE);
|
elm_object_disabled_set(_button_int, EINA_TRUE);
|
||||||
elm_object_disabled_set(_button_term, EINA_TRUE);
|
elm_object_disabled_set(_button_term, EINA_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void edi_debugpanel_start(void)
|
static void
|
||||||
|
_edi_debugger_run(Edi_Debug *debug)
|
||||||
{
|
{
|
||||||
char cmd[1024];
|
const char *fmt;
|
||||||
char *args;
|
char *args;
|
||||||
int len;
|
int len;
|
||||||
const char *warning, *mime, *fmt;
|
|
||||||
|
debug->exe = ecore_exe_pipe_run(debug->cmd, ECORE_EXE_PIPE_WRITE |
|
||||||
|
ECORE_EXE_PIPE_ERROR |
|
||||||
|
ECORE_EXE_PIPE_READ, NULL);
|
||||||
|
|
||||||
|
if (debug->tool->command_arguments && _edi_project_config->launch.args)
|
||||||
|
{
|
||||||
|
fmt = debug->tool->command_arguments;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug->tool->command_start)
|
||||||
|
ecore_exe_send(debug->exe, debug->tool->command_start, strlen(debug->tool->command_start));
|
||||||
|
}
|
||||||
|
|
||||||
|
void edi_debugpanel_start(const char *name)
|
||||||
|
{
|
||||||
|
const char *mime;
|
||||||
|
Edi_Debug *debug;
|
||||||
|
|
||||||
|
debug = edi_debug_get();
|
||||||
|
if (!debug) return;
|
||||||
|
|
||||||
|
if (debug->exe) return;
|
||||||
|
|
||||||
if (!_edi_project_config->launch.path)
|
if (!_edi_project_config->launch.path)
|
||||||
{
|
{
|
||||||
|
@ -420,44 +280,31 @@ void edi_debugpanel_start(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_debug_exe) return;
|
debug->program_name = ecore_file_file_get(_edi_project_config->launch.path);
|
||||||
|
|
||||||
if (!ecore_file_exists(_edi_project_config->launch.path))
|
debug->tool = edi_debug_tool_get(name);
|
||||||
|
if (!debug->tool)
|
||||||
{
|
{
|
||||||
warning = _("Warning: executable does not exists (run make?)");
|
edi_debug_exe_missing();
|
||||||
elm_code_file_line_append(_debug_output->file, warning, strlen(warning), NULL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mime = efreet_mime_type_get(_edi_project_config->launch.path);
|
mime = efreet_mime_type_get(_edi_project_config->launch.path);
|
||||||
if (!strcmp(mime, "application/x-shellscript"))
|
if (mime && !strcmp(mime, "application/x-shellscript"))
|
||||||
snprintf(cmd, sizeof(cmd), LIBTOOL_COMMAND " --mode execute gdb %s", _edi_project_config->launch.path);
|
snprintf(debug->cmd, sizeof(debug->cmd), LIBTOOL_COMMAND " --mode execute %s %s", debug->tool->exec, _edi_project_config->launch.path);
|
||||||
|
else if (debug->tool->arguments)
|
||||||
|
snprintf(debug->cmd, sizeof(debug->cmd), "%s %s %s", debug->tool->exec, debug->tool->arguments, _edi_project_config->launch.path);
|
||||||
else
|
else
|
||||||
snprintf(cmd, sizeof(cmd), "gdb %s", _edi_project_config->launch.path);
|
snprintf(debug->cmd, sizeof(debug->cmd), "%s %s", debug->tool->exec, _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);
|
|
||||||
ecore_event_handler_add(ECORE_EXE_EVENT_ERROR, _debugpanel_stdout_handler, NULL);
|
|
||||||
|
|
||||||
elm_object_disabled_set(_button_int, EINA_FALSE);
|
elm_object_disabled_set(_button_int, EINA_FALSE);
|
||||||
elm_object_disabled_set(_button_term, EINA_FALSE);
|
elm_object_disabled_set(_button_term, EINA_FALSE);
|
||||||
elm_object_disabled_set(_button_quit, EINA_FALSE);
|
elm_object_disabled_set(_button_quit, EINA_FALSE);
|
||||||
|
|
||||||
if (_edi_project_config->launch.args)
|
|
||||||
{
|
|
||||||
fmt = "set args %s\n";
|
|
||||||
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);
|
elm_object_disabled_set(_button_start, EINA_TRUE);
|
||||||
|
|
||||||
|
elm_code_file_clear(_debug_output->file);
|
||||||
|
|
||||||
|
_edi_debugger_run(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
void edi_debugpanel_add(Evas_Object *parent)
|
void edi_debugpanel_add(Evas_Object *parent)
|
||||||
|
@ -542,11 +389,15 @@ void edi_debugpanel_add(Evas_Object *parent)
|
||||||
_info_widget = widget;
|
_info_widget = widget;
|
||||||
_entry_widget = entry;
|
_entry_widget = entry;
|
||||||
|
|
||||||
|
edi_debug_new();
|
||||||
|
|
||||||
timer = ecore_timer_add(1.0, _edi_debug_active_check_cb, NULL);
|
timer = ecore_timer_add(1.0, _edi_debug_active_check_cb, NULL);
|
||||||
(void) timer;
|
(void) timer;
|
||||||
|
|
||||||
elm_box_pack_end(parent, widget);
|
elm_box_pack_end(parent, widget);
|
||||||
elm_box_pack_end(parent, table);
|
elm_box_pack_end(parent, table);
|
||||||
|
|
||||||
|
ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _debugpanel_stdout_handler, NULL);
|
||||||
|
ecore_event_handler_add(ECORE_EXE_EVENT_ERROR, _debugpanel_stdout_handler, NULL);
|
||||||
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_debugpanel_config_changed, NULL);
|
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_debugpanel_config_changed, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,11 @@ void edi_debugpanel_add(Evas_Object *parent);
|
||||||
/**
|
/**
|
||||||
* Start a new debugging session
|
* Start a new debugging session
|
||||||
*
|
*
|
||||||
|
* @param The toolname to do debugging with.
|
||||||
|
*
|
||||||
* @ingroup UI
|
* @ingroup UI
|
||||||
*/
|
*/
|
||||||
void edi_debugpanel_start();
|
void edi_debugpanel_start(const char *toolname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop existing debugging session
|
* Stop existing debugging session
|
||||||
|
|
|
@ -563,6 +563,17 @@ edi_launcher_config_missing()
|
||||||
edi_screens_message(_edi_main_win, title, message);
|
edi_screens_message(_edi_main_win, title, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
edi_debug_exe_missing(void)
|
||||||
|
{
|
||||||
|
const char *title, *message;
|
||||||
|
|
||||||
|
title = _("Unable to launch debugger");
|
||||||
|
message = _("No debug binary found, please check system configuration and Settings.");
|
||||||
|
|
||||||
|
edi_screens_message(_edi_main_win, title, message);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_project_credentials_missing()
|
_edi_project_credentials_missing()
|
||||||
|
|
||||||
|
@ -729,6 +740,12 @@ _edi_build_display_status_cb(int status, void *data)
|
||||||
eina_strbuf_free(message);
|
eina_strbuf_free(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_edi_debug_project(void)
|
||||||
|
{
|
||||||
|
edi_debugpanel_start(_edi_project_config_debug_command_get());
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_build_project(void)
|
_edi_build_project(void)
|
||||||
{
|
{
|
||||||
|
@ -796,7 +813,7 @@ static void
|
||||||
_tb_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
_tb_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||||
{
|
{
|
||||||
edi_debugpanel_show();
|
edi_debugpanel_show();
|
||||||
edi_debugpanel_start();
|
_edi_debug_project();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1012,12 +1029,21 @@ _edi_menu_clean_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
_edi_build_clean_project();
|
_edi_build_clean_project();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_edi_menu_memcheck_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
|
void *event_info EINA_UNUSED)
|
||||||
|
{
|
||||||
|
edi_debugpanel_show();
|
||||||
|
edi_debugpanel_stop();
|
||||||
|
edi_debugpanel_start("memcheck");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_menu_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
_edi_menu_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
void *event_info EINA_UNUSED)
|
void *event_info EINA_UNUSED)
|
||||||
{
|
{
|
||||||
edi_debugpanel_show();
|
edi_debugpanel_show();
|
||||||
edi_debugpanel_start();
|
_edi_debug_project();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1189,9 +1215,12 @@ _edi_menu_setup(Evas_Object *win)
|
||||||
_edi_menu_build = elm_menu_item_add(menu, menu_it, "system-run", _("Build"), _edi_menu_build_cb, NULL);
|
_edi_menu_build = elm_menu_item_add(menu, menu_it, "system-run", _("Build"), _edi_menu_build_cb, NULL);
|
||||||
_edi_menu_test = elm_menu_item_add(menu, menu_it, "media-record", _("Test"), _edi_menu_test_cb, NULL);
|
_edi_menu_test = 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, "media-playback-start", _("Run"), _edi_menu_run_cb, NULL);
|
||||||
elm_menu_item_add(menu, menu_it, "utilities-terminal", _("Debug"), _edi_menu_debug_cb, NULL);
|
|
||||||
_edi_menu_clean = elm_menu_item_add(menu, menu_it, "edit-clear", _("Clean"), _edi_menu_clean_cb, NULL);
|
_edi_menu_clean = elm_menu_item_add(menu, menu_it, "edit-clear", _("Clean"), _edi_menu_clean_cb, NULL);
|
||||||
|
|
||||||
|
menu_it = elm_menu_item_add(menu, NULL, NULL, _("Debug"), NULL, NULL);
|
||||||
|
elm_menu_item_add(menu, menu_it, "utilities-terminal", _("Debugger"), _edi_menu_debug_cb, NULL);
|
||||||
|
elm_menu_item_add(menu, menu_it, "applications-electronics", _("Memcheck"), _edi_menu_memcheck_cb, NULL);
|
||||||
|
|
||||||
menu_it = elm_menu_item_add(menu, NULL, NULL, _("Project"), NULL, NULL);
|
menu_it = elm_menu_item_add(menu, NULL, NULL, _("Project"), NULL, NULL);
|
||||||
_edi_menu_init = elm_menu_item_add(menu, menu_it, "media-playback-start", _("Init"), _edi_menu_scm_init_cb, NULL);
|
_edi_menu_init = elm_menu_item_add(menu, menu_it, "media-playback-start", _("Init"), _edi_menu_scm_init_cb, NULL);
|
||||||
_edi_menu_commit = elm_menu_item_add(menu, menu_it, "mail-send", _("Commit"), _edi_menu_scm_commit_cb, NULL);
|
_edi_menu_commit = elm_menu_item_add(menu, menu_it, "mail-send", _("Commit"), _edi_menu_scm_commit_cb, NULL);
|
||||||
|
|
|
@ -55,6 +55,8 @@ void edi_open_url();
|
||||||
Eina_Bool edi_noproject();
|
Eina_Bool edi_noproject();
|
||||||
|
|
||||||
void edi_launcher_config_missing();
|
void edi_launcher_config_missing();
|
||||||
|
void edi_debug_exe_missing(void);
|
||||||
|
|
||||||
|
|
||||||
Eina_Bool _edi_project_config_save_no_notify(void);
|
Eina_Bool _edi_project_config_save_no_notify(void);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ src = files([
|
||||||
'edi_consolepanel.h',
|
'edi_consolepanel.h',
|
||||||
'edi_content_provider.c',
|
'edi_content_provider.c',
|
||||||
'edi_content_provider.h',
|
'edi_content_provider.h',
|
||||||
|
'edi_debug.c',
|
||||||
|
'edi_debug.h',
|
||||||
'edi_debugpanel.c',
|
'edi_debugpanel.c',
|
||||||
'edi_debugpanel.h',
|
'edi_debugpanel.h',
|
||||||
'edi_file.c',
|
'edi_file.c',
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Edi.h"
|
#include "Edi.h"
|
||||||
#include "edi_screens.h"
|
#include "edi_screens.h"
|
||||||
#include "edi_config.h"
|
#include "edi_config.h"
|
||||||
|
#include "edi_debug.h"
|
||||||
|
|
||||||
#include "edi_private.h"
|
#include "edi_private.h"
|
||||||
|
|
||||||
|
@ -293,76 +294,139 @@ _edi_settings_builds_args_cb(void *data EINA_UNUSED, Evas_Object *obj,
|
||||||
_edi_project_config_save();
|
_edi_project_config_save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_edi_settings_builds_debug_tool_text_get_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Edi_Debug_Tool *tool;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = (int)(uintptr_t) data;
|
||||||
|
|
||||||
|
tool = &edi_debug_tools_get()[i];
|
||||||
|
|
||||||
|
return strdup(tool->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _edi_settings_builds_debug_pressed_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info)
|
||||||
|
{
|
||||||
|
const char *text = elm_object_item_text_get(event_info);
|
||||||
|
|
||||||
|
if (_edi_project_config->debug_command)
|
||||||
|
eina_stringshare_del(_edi_project_config->debug_command);
|
||||||
|
|
||||||
|
_edi_project_config->debug_command = eina_stringshare_add(text);
|
||||||
|
_edi_project_config_save();
|
||||||
|
|
||||||
|
elm_object_text_set(obj, text);
|
||||||
|
elm_combobox_hover_end(obj);
|
||||||
|
}
|
||||||
|
|
||||||
static Evas_Object *
|
static Evas_Object *
|
||||||
_edi_settings_builds_create(Evas_Object *parent)
|
_edi_settings_builds_create(Evas_Object *parent)
|
||||||
{
|
{
|
||||||
Evas_Object *box, *frame, *hbox, *label, *ic, *selector, *file, *entry;
|
Evas_Object *box, *frame, *table, *label, *ic, *selector, *file, *entry;
|
||||||
|
Evas_Object *combobox;
|
||||||
|
Elm_Genlist_Item_Class *itc;
|
||||||
|
Edi_Debug_Tool *tools;
|
||||||
|
int i;
|
||||||
|
|
||||||
frame = _edi_settings_panel_create(parent, _("Builds"));
|
frame = _edi_settings_panel_create(parent, _("Builds"));
|
||||||
box = elm_object_part_content_get(frame, "default");
|
box = elm_object_part_content_get(frame, "default");
|
||||||
|
|
||||||
hbox = elm_box_add(parent);
|
table = elm_table_add(parent);
|
||||||
elm_box_horizontal_set(hbox, EINA_TRUE);
|
elm_table_padding_set(table, 5, 5);
|
||||||
evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
|
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, 0.0);
|
||||||
evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(box, hbox);
|
evas_object_show(table);
|
||||||
evas_object_show(hbox);
|
elm_box_pack_end(box, table);
|
||||||
|
|
||||||
label = elm_label_add(hbox);
|
label = elm_label_add(box);
|
||||||
elm_object_text_set(label, _("Runtime binary"));
|
elm_object_text_set(label, _("Runtime binary:"));
|
||||||
evas_object_size_hint_weight_set(label, 0.0, 0.0);
|
evas_object_size_hint_weight_set(label, 0.0, 0.0);
|
||||||
evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(hbox, label);
|
elm_table_pack(table, label, 0, 0, 1, 1);
|
||||||
evas_object_show(label);
|
evas_object_show(label);
|
||||||
|
|
||||||
ic = elm_icon_add(hbox);
|
ic = elm_icon_add(box);
|
||||||
elm_icon_standard_set(ic, "file");
|
elm_icon_standard_set(ic, "file");
|
||||||
evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
|
evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
|
||||||
|
evas_object_show(ic);
|
||||||
|
|
||||||
selector = elm_fileselector_button_add(box);
|
selector = elm_fileselector_button_add(box);
|
||||||
elm_object_text_set(selector, _("Select"));
|
elm_object_text_set(selector, _("Select"));
|
||||||
elm_object_part_content_set(selector, "icon", ic);
|
elm_object_part_content_set(selector, "icon", ic);
|
||||||
elm_fileselector_path_set(selector, edi_project_get());
|
elm_fileselector_path_set(selector, edi_project_get());
|
||||||
evas_object_size_hint_weight_set(selector, 0.25, 0.0);
|
|
||||||
evas_object_size_hint_align_set(selector, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(selector, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(hbox, selector);
|
elm_table_pack(table, selector, 1, 0, 1, 1);
|
||||||
evas_object_show(selector);
|
evas_object_show(selector);
|
||||||
|
|
||||||
elm_object_focus_set(selector, EINA_TRUE);
|
file = elm_entry_add(box);
|
||||||
|
elm_entry_editable_set(file, EINA_FALSE);
|
||||||
file = elm_label_add(hbox);
|
elm_entry_single_line_set(file, EINA_TRUE);
|
||||||
|
elm_entry_scrollable_set(file, EINA_TRUE);
|
||||||
elm_object_text_set(file, _edi_project_config->launch.path);
|
elm_object_text_set(file, _edi_project_config->launch.path);
|
||||||
evas_object_size_hint_weight_set(file, 0.75, 0.0);
|
evas_object_size_hint_weight_set(file, 0.75, 0.0);
|
||||||
evas_object_size_hint_align_set(file, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(file, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(hbox, file);
|
elm_table_pack(table, file, 2, 0, 1, 1);
|
||||||
evas_object_show(file);
|
evas_object_show(file);
|
||||||
|
|
||||||
evas_object_smart_callback_add(selector, "file,chosen",
|
evas_object_smart_callback_add(selector, "file,chosen",
|
||||||
_edi_settings_builds_binary_chosen_cb, file);
|
_edi_settings_builds_binary_chosen_cb, file);
|
||||||
|
|
||||||
hbox = elm_box_add(parent);
|
label = elm_label_add(box);
|
||||||
elm_box_horizontal_set(hbox, EINA_TRUE);
|
elm_object_text_set(label, _("Runtime arguments:"));
|
||||||
evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
|
|
||||||
evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
||||||
elm_box_pack_end(box, hbox);
|
|
||||||
evas_object_show(hbox);
|
|
||||||
|
|
||||||
label = elm_label_add(hbox);
|
|
||||||
elm_object_text_set(label, _("Runtime arguments"));
|
|
||||||
evas_object_size_hint_weight_set(label, 0.0, 0.0);
|
evas_object_size_hint_weight_set(label, 0.0, 0.0);
|
||||||
evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(hbox, label);
|
elm_table_pack(table, label, 0, 1, 1, 1);
|
||||||
evas_object_show(label);
|
evas_object_show(label);
|
||||||
|
|
||||||
entry = elm_entry_add(hbox);
|
entry = elm_entry_add(box);
|
||||||
elm_object_text_set(entry, _edi_project_config->launch.args);
|
elm_object_text_set(entry, _edi_project_config->launch.args);
|
||||||
|
elm_entry_editable_set(entry, EINA_TRUE);
|
||||||
|
elm_entry_single_line_set(entry, EINA_TRUE);
|
||||||
|
elm_entry_scrollable_set(entry, EINA_TRUE);
|
||||||
evas_object_size_hint_weight_set(entry, 0.75, 0.0);
|
evas_object_size_hint_weight_set(entry, 0.75, 0.0);
|
||||||
evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
elm_box_pack_end(hbox, entry);
|
elm_table_pack(table, entry, 1, 1, 2, 1);
|
||||||
evas_object_show(entry);
|
evas_object_show(entry);
|
||||||
evas_object_smart_callback_add(entry, "changed",
|
evas_object_smart_callback_add(entry, "changed",
|
||||||
_edi_settings_builds_args_cb, NULL);
|
_edi_settings_builds_args_cb, NULL);
|
||||||
|
|
||||||
|
label = elm_label_add(box);
|
||||||
|
elm_object_text_set(label, _("Default debugger:"));
|
||||||
|
evas_object_size_hint_weight_set(label, 0.0, 0.0);
|
||||||
|
evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
|
||||||
|
elm_table_pack(table, label, 0, 2, 1, 1);
|
||||||
|
evas_object_show(label);
|
||||||
|
|
||||||
|
combobox = elm_combobox_add(box);
|
||||||
|
if (_edi_project_config->debug_command)
|
||||||
|
elm_object_part_text_set(combobox, "guide", _edi_project_config->debug_command);
|
||||||
|
else
|
||||||
|
elm_object_part_text_set(combobox, "guide", _("Please choose ..."));
|
||||||
|
|
||||||
|
evas_object_size_hint_weight_set(combobox, 0.75, 0.0);
|
||||||
|
evas_object_size_hint_align_set(combobox, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||||
|
evas_object_show(combobox);
|
||||||
|
evas_object_smart_callback_add(combobox, "item,pressed",
|
||||||
|
_edi_settings_builds_debug_pressed_cb, NULL);
|
||||||
|
|
||||||
|
elm_table_pack(table, combobox, 1, 2, 2, 1);
|
||||||
|
|
||||||
|
itc = elm_genlist_item_class_new();
|
||||||
|
itc->item_style = "default";
|
||||||
|
itc->func.text_get = _edi_settings_builds_debug_tool_text_get_cb;
|
||||||
|
|
||||||
|
tools = edi_debug_tools_get();
|
||||||
|
for (i = 0; tools[i].name; i++)
|
||||||
|
{
|
||||||
|
if (ecore_file_app_installed(tools[i].exec))
|
||||||
|
elm_genlist_item_append(combobox, itc, (void *)(uintptr_t) i, NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)(uintptr_t) i);
|
||||||
|
}
|
||||||
|
|
||||||
|
elm_genlist_realized_items_update(combobox);
|
||||||
|
elm_genlist_item_class_free(itc);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue