Beispiel #1
0
static void update_recent_menu(const MMDesc *items)
{
    StringArray recent_files;
    {
	StringArray r;
	get_recent(r);
	for (int i = 0; i < r.size() && items[i].widget != 0; i++)
	    recent_files += r[i];
    }

    // Uniquify labels
    char sep = '/';
    if (gdb->type() == JDB)
	sep = '.';

    StringArray labels;
    uniquify(recent_files, labels, sep);

    // Set labels
    int i;
    for (i = 0; i < labels.size(); i++)
    {
	MString label(itostring(i + 1) + " ");
	label += tt(labels[i]);

	Widget w = items[i].widget;
	set_label(w, label);

	const string& file = recent_files[i];

	bool sens = true;
	if (!remote_gdb())
	{
	    if (gdb->has_exec_files() && !is_debuggee_file(file))
		sens = false;	// File not accessible
	    else if (!gdb->has_classes() && !is_regular_file(file))
		sens = false;	// File not accessible
	}

	set_sensitive(w, sens);
	XtManageChild(w);
    }

    // Unmanage remaining items
    for (; items[i].widget != 0; i++)
	XtUnmanageChild(items[i].widget);
}
// Get information on current debuggee
ProgramInfo::ProgramInfo()
    : file(NO_GDB_ANSWER),
      core(NO_GDB_ANSWER),
      pid(0),
      attached(false),
      running(false),
      state()
{
    if (source_view->have_exec_pos())
    {
	state = "has stopped";
	running = true;
    }
    else
    {
	state = "is not being run";
	running = false;
    }

    switch(gdb->type())
    {
    case GDB:
    case PYDB:
    case DBG:
    {
    	string ans;

    	if (gdb->is_windriver_gdb())
	{
	    // Windriver GDB (VxWorks).

	    // VxWorks allows multiple dynamically relocatable
	    // programs to be loaded simultaneously. Before a program
	    // is run, the 'info source' command can report
	    // information from a source file not related to the
	    // program just downloaded for debugging. (The WindRiver
	    // version of gdb does not support the 'info files'
	    // command.)

	    // In order to tell DDD that there is indeed a source file
	    // available, we need to first see if a program has
	    // already been started. If so, then the 'info source'
	    // command can be used.

	    // Otherwise, the 'info sources' command is used, and the
	    // first file in the list is used, assuming it is related
	    // to the current program that was downloaded.

	    // See if the program has been run first
	    ans = gdb_question("info frame");
	    if (ans == NO_GDB_ANSWER)
		break;

	    file = "";
	    if (ans.contains("No stack"))
	    {
		// Then try using info sources and use first file listed
		ans = gdb_question("info sources");
		if (ans == NO_GDB_ANSWER)
		    break;

		if (ans.contains("Source files for which "
				 "symbols have been read in:"))
		{
		    file = ans.after("\n");
		    file = file.before(" ");
		    file = unquote(file);
		}
	    }
	    else
	    {
	    	// Try using `info source'.
		ans = gdb_question("info source");
		if (ans == NO_GDB_ANSWER)
		    break;

		if (ans.contains("Current source file is "))
		{
		    file = ans.after("Current source file is ");
		    file = file.before(".\n");
		    file = unquote(file);
		}
	    }
	}
	else
	{
	    // Ordinary GDB.
	    ans = gdb_question("info files");
	    if (ans == NO_GDB_ANSWER)
		break;

	    file = "";
	    if (ans.contains("Symbols from "))
	    {
		file = ans.after("Symbols from ");
		file = file.before(".\n");
		file = unquote(file);
	    }

	}
	core = "";
	if (ans.contains("core dump"))
	{
	    core = ans.after("core dump");
	    core = core.after('`');
	    core = core.before("',");
	}

	if (ans.contains("process "))
	{
	    string p = ans.after("process ");
	    pid = atoi(p.chars());
	}

	attached = ans.contains("attached process ");

	ans = gdb_question("info program");
	if (ans == NO_GDB_ANSWER)
	    break;

	if (ans.contains("not being run"))
	    running = false;
	else if (ans.contains("\nIt stopped "))
	{
	    state = ans.from("\nIt stopped ");
	    state = "has " + state.after("\nIt ");
	    state = state.before('.');
	    running = true;
	}
	break;
    }

    case DBX:
    {
	if (gdb->is_ladebug())
	{
	    string ans = gdb_question("show process");
	    // typical answers:
	    // 1:no process 
	    // There are no processes being debugged.
	    // 2: process has been paused.
	    // Current Process: localhost:26177 (a.out) paused.
	    // 3: process terminated
	    // Current Process: localhost:13614 (ddd) terminated.
	    // TODO: treat the terminated case 
     
	    if (ans != NO_GDB_ANSWER && 
		!ans.contains("no processes being debugged"))
	    {
		if (ans.contains("Current Process: "))
		{
		    ans = ans.after(": ");
		    {
			string p = ans.after(":");
			p = p.before(" ");
			pid = atoi(p.chars());
		    }
		    ans = ans.after(" (");
		    file = ans.before(")");

		    ans = ans.after(") ");
		    running = ans.contains("paused");
		    // ladebug always creates a process.
		    // It may be "loaded" or attached.
		    attached = true;
		}
	    }	    
	}

	// AD TODO: shouldn't it be an "else" ?

	string ans = gdb_question(gdb->debug_command());
	if (ans != NO_GDB_ANSWER)
	{
	    if (ans.contains("Current givenfile is ", 0))
		ans = ans.after("Current givenfile is ");
	    else if (ans.contains("Debugging: ", 0))
		ans = ans.after(": ");

	    strip_space(ans);
	    if (!ans.contains(' ')) // Sanity check
		file = ans;
	}
	break;
    }

    case XDB:
	break;			// FIXME

    case PERL:
	// Use the program we were invoked with
	file = gdb->program();
	if (file.matches(rxint))
	    file = "";		// Invoked with a constant expression

	if (file.empty())
	{
	    // Not invoked with a program?  Use the current file, then.
	    file = source_view->file_of_cursor();
	    file = file.before(":");
	}
	core = "";
	break;

    case BASH:
	// Use the program we were invoked with
	file = gdb->program();
	if (file.matches(rxint))
	    file = "";		// Invoked with a constant expression

	if (file.empty())
	{
	    // Not invoked with a program?  Use the current file, then.
	    file = source_view->file_of_cursor();
	    file = file.before(":");
	}
	core = "";
	break;

    case JDB:
	// Just use the current class.
	file = source_view->line_of_cursor();
	file = file.before(":");
	core = "";

	// Save whether JDB's VM is running
	static int last_jdb_pid = -1;
	static bool jvm_running = false;

	if (gdb->pid() != last_jdb_pid)
	{
	    // New JDB: reset info
	    jvm_running = false;
	    last_jdb_pid = gdb->pid();
	}

	// The VM is running iff the prompt contains a backtrace
	// level ("[n]").
	if (!jvm_running && gdb->prompt().contains("["))
	    jvm_running = true;

	running = jvm_running;
	break;
    }

    if (file == NO_GDB_ANSWER)
    {
	// As a fallback, get core file and executable from argument list.
	// Works only on local file system and is more a guess.
	char **argv = saved_argv();
	int argc = 0;
	while (argv[argc] != 0)
	    argc++;

	for (int i = argc - 1; i > 0 && file == NO_GDB_ANSWER; i--)
	{
	    // All debuggers supported by DDD have [EXEC [CORE]] as
	    // their last arguments.
	    string arg = argv[i];
	    if (is_core_file(arg))
		core = arg;
	    else if (is_debuggee_file(arg))
		file = arg;
	}
    }

    if (file != NO_GDB_ANSWER)
	add_to_recent(file);
}
// Return an appropriate debugger type from ARGC/ARGV.
// Set ARG if debugger type could be deduced from an argument.
DebuggerInfo::DebuggerInfo(int argc, const char * const argv[])
    : type(DebuggerType(-1)),
      arg("")
{
    DebuggerType fallback = DebuggerType(-1);
    get_debugger_type(app_data.debugger, fallback);

    static bool have_bash   = (fallback == BASH || have_cmd("bash"));
    static bool have_dbg    = (fallback == DBG  || have_cmd("dbg"));
    static bool have_perl   = (fallback == PERL || have_cmd("perl"));
    static bool have_python = (fallback == PYDB || have_cmd("python"));

    // 1. Check for Perl and Python scripts as given.

    int i;
    for (i = 1; i < argc; i++)
    {
	arg = argv[i];

	if (arg.contains('-', 0))
	    continue;		// Option

	if (have_perl && is_perl_file(arg))
	{
	    type = PERL;
	    return;
	}

	if (have_bash && is_bash_file(arg))
	{
	    type = BASH;
	    return;
	}

	if (have_python && is_python_file(arg))
	{
	    type = PYDB;
	    return;
	}
	
	if (have_dbg && is_php_file(arg))
	{
	    type = DBG;
	    return;
	}
    }


    // 2. Check for executable binary as given.

    static bool have_gdb = (fallback == GDB || have_cmd("gdb"));
    static bool have_dbx = 
	(fallback == DBX || have_cmd("dbx") || have_cmd("ladebug"));
    static bool have_xdb = (fallback == XDB || have_cmd("xdb"));

    for (i = 1; i < argc; i++)
    {
	arg = argv[i];

	if (arg.contains('-', 0))
	    continue;		// Option

	if (is_debuggee_file(arg))
	{
	    if (fallback == GDB || fallback == DBX || fallback == XDB)
	    {
		type = fallback;
		return;
	    }

	    if (have_gdb)
	    {
		type = GDB;
		return;
	    }

	    if (have_dbx)
	    {
		type = DBX;
		return;
	    }

	    if (have_xdb)
	    {
		type = XDB;
		return;
	    }
	}
    }


    // 3. Check for Java class in current directory.

    static bool have_jdb = (fallback == JDB || have_cmd("jdb"));

    if (have_jdb)
    {
	for (i = 1; i < argc; i++)
	{
	    arg = argv[i];

	    if (arg.contains('-', 0))
		continue;		// Option
	    if (arg.contains('/', 0))
		continue;		// File

	    arg.gsub('.', '/');

	    if (is_regular_file(arg + ".java"))
	    {
		type = JDB;
		return;
	    }

	    if (is_regular_file(arg + ".class"))
	    {
		type = JDB;
		return;
	    }
	}
    }


    // 4. Check for executable binary in PATH.

    for (i = 1; i < argc; i++)
    {
	arg = argv[i];

	if (arg.contains('-', 0))
	    continue;		// Option

	const char *path_s = getenv("PATH");
	if (path_s == 0)
	    path_s = ".";

	string path = path_s;
	while (!path.empty())
	{
	    string dir;
	    if (path.contains(':'))
		dir = path.before(':');
	    else
		dir = path;
	    path = path.after(':');

	    if (dir.empty())
		dir = ".";
	    if (!dir.contains('/', -1))
		dir += '/';

	    if (is_debuggee_file(dir + arg))
	    {
		if (fallback == GDB || fallback == DBX || fallback == XDB)
		{
		    type = fallback;
		    return;
		}

		if (have_gdb)
		{
		    type = GDB;
		    return;
		}

		if (have_dbx)
		{
		    type = DBX;
		    return;
		}

		if (have_xdb)
		{
		    type = XDB;
		    return;
		}
	    }
	}
    }


    // 5. Check for Java class in CLASSPATH.

    if (have_jdb)
    {
	for (i = 1; i < argc; i++)
	{
	    arg = argv[i];

	    if (arg.contains('-', 0))
		continue;		// Option
	    if (arg.contains('/', 0))
		continue;		// File

	    const char *classpath_s = getenv("CLASSPATH");
	    if (classpath_s == 0)
		classpath_s = ".";

	    string classpath = classpath_s;
	    while (!classpath.empty())
	    {
		string dir;
		if (classpath.contains(':'))
		    dir = classpath.before(':');
		else
		    dir = classpath;
		classpath = classpath.after(':');

		if (dir.empty())
		    dir = ".";
		if (!dir.contains('/', -1))
		    dir += '/';

		string path = arg;
		path.gsub('.', '/');

		if (is_regular_file(dir + path + ".java"))
		{
		    type = JDB;
		    return;
		}

		if (is_regular_file(dir + path + ".class"))
		{
		    type = JDB;
		    return;
		}
	    }
	}
    }


    // 6. Use fallback.

    arg = "";

    if (fallback != DebuggerType(-1))
    {
	type = fallback;
	return;
    }


    // 7. All fails.  Use GDB.
    type = GDB;
}