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; }