mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-02 16:22:40 -06:00
ide: POSIX debugging of console applications now launches console #507
git-svn-id: svn://ultimatepp.org/upp/trunk@6677 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
094ef62883
commit
7bc553fee0
10 changed files with 168 additions and 24 deletions
|
|
@ -134,25 +134,27 @@ bool LocalProcess::DoStart(const char *command, bool spliterr, const char *envpt
|
|||
p++;
|
||||
else {
|
||||
args.Add(cmd_out);
|
||||
while(*p && (byte)*p > ' ')
|
||||
if(*p == '\\') {
|
||||
while(*p && (byte)*p > ' ') {
|
||||
int c = *p;
|
||||
if(c == '\\') {
|
||||
if(*++p)
|
||||
*cmd_out++ = *p++;
|
||||
}
|
||||
else if(*p == '\"') {
|
||||
else if(c == '\"' || c == '\'') {
|
||||
p++;
|
||||
while(*p && *p != '\"')
|
||||
while(*p && *p != c)
|
||||
if(*p == '\\') {
|
||||
if(*++p)
|
||||
*cmd_out++ = *p++;
|
||||
}
|
||||
else
|
||||
*cmd_out++ = *p++;
|
||||
if(*p == '\"')
|
||||
if(*p == c)
|
||||
p++;
|
||||
}
|
||||
else
|
||||
*cmd_out++ = *p++;
|
||||
}
|
||||
*cmd_out++ = '\0';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ public:
|
|||
bool Start(const char *cmdline, const char *envptr = NULL) { return DoStart(cmdline, false, envptr); }
|
||||
bool Start2(const char *cmdline, const char *envptr = NULL) { return DoStart(cmdline, true, envptr); }
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
int GetPid() const { return pid; }
|
||||
#endif
|
||||
|
||||
LocalProcess& ConvertCharset(bool b = true) { convertcharset = b; return *this; }
|
||||
LocalProcess& NoConvertCharset() { return ConvertCharset(false); }
|
||||
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ void Ide::BuildAndExtDebugFile()
|
|||
BuildAndDebug0(editfile);
|
||||
}
|
||||
|
||||
One<Debugger> GdbCreate(One<Host> host, const String& exefile, const String& cmdline);
|
||||
One<Debugger> Gdb_MI2Create(One<Host> host, const String& exefile, const String& cmdline);
|
||||
One<Debugger> GdbCreate(One<Host> host, const String& exefile, const String& cmdline, bool console);
|
||||
One<Debugger> Gdb_MI2Create(One<Host> host, const String& exefile, const String& cmdline, bool console);
|
||||
#ifdef PLATFORM_WIN32
|
||||
One<Debugger> CdbCreate(One<Host> host, const String& exefile, const String& cmdline);
|
||||
One<Debugger> PdbCreate(One<Host> host, const String& exefile, const String& cmdline);
|
||||
|
|
@ -175,19 +175,22 @@ void Ide::BuildAndDebug(bool runto)
|
|||
host->ChDir(Nvl(rundir, GetFileFolder(target)));
|
||||
HideBottom();
|
||||
editor.Disable();
|
||||
|
||||
bool console = FindIndex(SplitFlags(mainconfigparam, true), "GUI") < 0 || forceconsole;
|
||||
|
||||
#ifdef COMPILER_MSC
|
||||
if(builder == "GCC")
|
||||
if(gdbSelector)
|
||||
debugger = Gdb_MI2Create(host, target, runarg);
|
||||
debugger = Gdb_MI2Create(host, target, runarg, console);
|
||||
else
|
||||
debugger = GdbCreate(host, target, runarg);
|
||||
debugger = GdbCreate(host, target, runarg, console);
|
||||
else
|
||||
debugger = PdbCreate(host, target, runarg);
|
||||
#else
|
||||
if(gdbSelector)
|
||||
debugger = Gdb_MI2Create(host, target, runarg);
|
||||
debugger = Gdb_MI2Create(host, target, runarg, console);
|
||||
else
|
||||
debugger = GdbCreate(host, target, runarg);
|
||||
debugger = GdbCreate(host, target, runarg, console);
|
||||
#endif
|
||||
if(!debugger) return;
|
||||
debuglock = 0;
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ String Dbg::Cmd(const char *command)
|
|||
GuiSleep(sleep);
|
||||
Ctrl::ProcessEvents();
|
||||
sleep = min(20, sleep + max(1, 3 * sleep / 2));
|
||||
if(TTYQuit())
|
||||
Stop();
|
||||
}
|
||||
Unlock();
|
||||
#ifdef _DEBUG
|
||||
|
|
@ -141,6 +143,8 @@ String Dbg::FastCmd(const char *command)
|
|||
String s;
|
||||
// if(!lock)
|
||||
Sleep(0);
|
||||
if(TTYQuit())
|
||||
Stop();
|
||||
if(!dbg->Read(s)) {
|
||||
LLOG(result);
|
||||
PutVerbose(result);
|
||||
|
|
@ -231,5 +235,4 @@ Dbg::Dbg()
|
|||
quickwatch.Icon(DbgImg::QuickWatch());
|
||||
|
||||
Transparent();
|
||||
// log.Open(ConfigFile("debug.log"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@
|
|||
|
||||
typedef uintptr_t adr_t;
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
String CreateDebugTTY();
|
||||
void KillDebugTTY();
|
||||
bool TTYQuit();
|
||||
#endif
|
||||
|
||||
String GdbCommand(bool console);
|
||||
|
||||
class DbgDisas : public Ctrl {
|
||||
public:
|
||||
virtual void Paint(Draw& w);
|
||||
|
|
@ -162,11 +170,16 @@ struct Gdb : Dbg {
|
|||
void CopyStack();
|
||||
void CopyDisas();
|
||||
|
||||
bool Create(One<Host> host, const String& exefile, const String& cmdline);
|
||||
bool Create(One<Host> host, const String& exefile, const String& cmdline, bool console);
|
||||
|
||||
// Period check for killed console
|
||||
TimeCallback periodic;
|
||||
void Periodic();
|
||||
|
||||
typedef Gdb CLASSNAME;
|
||||
|
||||
virtual ~Gdb();
|
||||
Gdb();
|
||||
};
|
||||
|
||||
#include "Gdb_MI2.h"
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@ uses
|
|||
HexView;
|
||||
|
||||
file
|
||||
MIValue.h,
|
||||
MIValue.cpp,
|
||||
Debuggers.h,
|
||||
Debuggers.iml,
|
||||
Gdb.lay,
|
||||
MIValue.h,
|
||||
MIValue.cpp,
|
||||
Terminal.cpp,
|
||||
Disas.cpp,
|
||||
Dbg.cpp,
|
||||
Gdb.cpp,
|
||||
|
|
|
|||
|
|
@ -551,10 +551,10 @@ bool Gdb::Key(dword key, int count)
|
|||
return Ctrl::Key(key, count);
|
||||
}
|
||||
|
||||
bool Gdb::Create(One<Host> _host, const String& exefile, const String& cmdline)
|
||||
bool Gdb::Create(One<Host> _host, const String& exefile, const String& cmdline, bool console)
|
||||
{
|
||||
host = _host;
|
||||
dbg = host->StartProcess("gdb " + GetHostPath(exefile));
|
||||
dbg = host->StartProcess(GdbCommand(console) + GetHostPath(exefile));
|
||||
if(!dbg) {
|
||||
Exclamation("Error invoking gdb !");
|
||||
return false;
|
||||
|
|
@ -593,12 +593,24 @@ Gdb::~Gdb()
|
|||
{
|
||||
IdeRemoveBottom(*this);
|
||||
IdeRemoveRight(disas);
|
||||
KillDebugTTY();
|
||||
}
|
||||
|
||||
One<Debugger> GdbCreate(One<Host> host, const String& exefile, const String& cmdline)
|
||||
void Gdb::Periodic()
|
||||
{
|
||||
if(TTYQuit())
|
||||
Stop();
|
||||
}
|
||||
|
||||
Gdb::Gdb()
|
||||
{
|
||||
periodic.Set(-50, THISBACK(Periodic));
|
||||
}
|
||||
|
||||
One<Debugger> GdbCreate(One<Host> host, const String& exefile, const String& cmdline, bool console)
|
||||
{
|
||||
Gdb *dbg = new Gdb;
|
||||
if(!dbg->Create(host, exefile, cmdline)) {
|
||||
if(!dbg->Create(host, exefile, cmdline, console)) {
|
||||
delete dbg;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,6 +218,12 @@ bool Gdb_MI2::Tip(const String& exp, CodeEditor::MouseTip& mt)
|
|||
// CONSTRUCTOR / DESTRUCTOR
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Gdb_MI2::Periodic()
|
||||
{
|
||||
if(TTYQuit())
|
||||
Stop();
|
||||
}
|
||||
|
||||
Gdb_MI2::Gdb_MI2()
|
||||
{
|
||||
CtrlLayout(regs);
|
||||
|
|
@ -319,12 +325,15 @@ Gdb_MI2::Gdb_MI2()
|
|||
|
||||
started = false;
|
||||
stopped = false;
|
||||
|
||||
periodic.Set(-50, THISBACK(Periodic));
|
||||
}
|
||||
|
||||
Gdb_MI2::~Gdb_MI2()
|
||||
{
|
||||
IdeRemoveBottom(*this);
|
||||
IdeRemoveRight(disas);
|
||||
KillDebugTTY();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1716,10 +1725,10 @@ void Gdb_MI2::ExplorerMenu(Bar& bar)
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// create GDB process and initializes it
|
||||
bool Gdb_MI2::Create(One<Host> _host, const String& exefile, const String& cmdline)
|
||||
bool Gdb_MI2::Create(One<Host> _host, const String& exefile, const String& cmdline, bool console)
|
||||
{
|
||||
host = _host;
|
||||
dbg = host->StartProcess("gdb " + GetHostPath(exefile) + " --interpreter=mi -q");
|
||||
dbg = host->StartProcess(GdbCommand(console) + GetHostPath(exefile) + " --interpreter=mi -q");
|
||||
if(!dbg) {
|
||||
Exclamation(t_("Error invoking gdb !"));
|
||||
return false;
|
||||
|
|
@ -1776,10 +1785,10 @@ bool Gdb_MI2::Create(One<Host> _host, const String& exefile, const String& cmdli
|
|||
return true;
|
||||
}
|
||||
|
||||
One<Debugger> Gdb_MI2Create(One<Host> host, const String& exefile, const String& cmdline)
|
||||
One<Debugger> Gdb_MI2Create(One<Host> host, const String& exefile, const String& cmdline, bool console)
|
||||
{
|
||||
Gdb_MI2 *dbg = new Gdb_MI2;
|
||||
if(!dbg->Create(host, exefile, cmdline))
|
||||
if(!dbg->Create(host, exefile, cmdline, console))
|
||||
{
|
||||
delete dbg;
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -212,6 +212,10 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
// lock/unlock debugger controls
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
// Period check for killed console
|
||||
TimeCallback periodic;
|
||||
void Periodic();
|
||||
|
||||
String GetHostPath(const String& path) { return host->GetHostPath(path); }
|
||||
String GetLocalPath(const String& path) { return host->GetLocalPath(path); }
|
||||
|
|
@ -233,7 +237,7 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
virtual bool Tip(const String& exp, CodeEditor::MouseTip& mt);
|
||||
|
||||
// create GDB process and initializes it
|
||||
bool Create(One<Host> _host, const String& exefile, const String& cmdline);
|
||||
bool Create(One<Host> _host, const String& exefile, const String& cmdline, bool console);
|
||||
|
||||
Gdb_MI2();
|
||||
virtual ~Gdb_MI2();
|
||||
|
|
|
|||
93
uppsrc/ide/Debuggers/Terminal.cpp
Normal file
93
uppsrc/ide/Debuggers/Terminal.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include "Debuggers.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
||||
void Do_ps(VectorMap<String, String>& pids, Index<String>& ttys, const String& cmd)
|
||||
{
|
||||
pids.Clear();
|
||||
ttys.Clear();
|
||||
Vector<String> ps = Split(Sys(cmd), '\n');
|
||||
for(int i = 1; i < ps.GetCount(); i++) {
|
||||
Vector<String> ss = Split(ps[i], ' ');
|
||||
if(ss.GetCount() >= 2) {
|
||||
if(IsDigit(*ss[0]) && IsAlNum(*ss[1])) {
|
||||
pids.Add(ss[1], ss[0]);
|
||||
ttys.FindAdd(ss[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VectorMap<String, String> sPid;
|
||||
static String sTTY;
|
||||
|
||||
String CreateDebugTTY()
|
||||
{ // The method is far from ideal and reliable, but should work most of time
|
||||
sTTY.Clear();
|
||||
|
||||
Index<String> tty0, tty;
|
||||
Do_ps(sPid, tty0, "ps -A");
|
||||
|
||||
IGNORE_RESULT(chdir(GetHomeDirectory()));
|
||||
|
||||
static const char *term[] = {
|
||||
"/usr/bin/mate-terminal -e 'tail -f /dev/null'",
|
||||
"/usr/bin/gnome-terminal -e 'tail -f /dev/null'",
|
||||
"/usr/bin/konsole -e 'tail -f /dev/null'",
|
||||
"/usr/bin/xterm -e 'tail -f /dev/null'",
|
||||
};
|
||||
|
||||
for(int i = 0; i < __countof(term); i++) {
|
||||
if(FileExists(Split(term[i], ' ')[0])) {
|
||||
LocalProcess(term[i]).Detach();
|
||||
for(int i = 0; i < 10; i++) { // Wait for the new TTY to appear
|
||||
Do_ps(sPid, tty, "ps -A");
|
||||
for(int i = 0; i < tty.GetCount(); i++)
|
||||
if(tty0.Find(tty[i]) < 0) {
|
||||
sTTY = tty[i];
|
||||
return "/dev/" + sTTY;
|
||||
}
|
||||
Sleep(200);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Null;
|
||||
}
|
||||
|
||||
void KillDebugTTY()
|
||||
{
|
||||
Index<String> tty;
|
||||
Do_ps(sPid, tty, "ps -A");
|
||||
if(sTTY.GetCount())
|
||||
for(int q = sPid.Find(sTTY); q >= 0; q = sPid.FindNext(q)) {
|
||||
Sys("kill -9 " + sPid[q]);
|
||||
}
|
||||
sTTY.Clear();
|
||||
}
|
||||
|
||||
bool TTYQuit()
|
||||
{
|
||||
if(sTTY.GetCount()) {
|
||||
int fd = open("/dev/" + sTTY, O_RDWR | O_NONBLOCK);
|
||||
if(fd < 0)
|
||||
return true;
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String GdbCommand(bool console)
|
||||
{
|
||||
String gdb = "gdb ";
|
||||
#ifdef PLATFORM_POSIX
|
||||
if(console) {
|
||||
String tty = CreateDebugTTY();
|
||||
if(tty.GetCount())
|
||||
gdb << "-tty=" << tty << ' ';
|
||||
}
|
||||
#endif
|
||||
return gdb;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue