Esempio n. 1
0
string BreakPoint::pos() const
{
    if (line_nr() == 0)
	return "*" + address();
    else if (file_name().empty())
	return itostring(line_nr());
    else
	return file_name() + ":" + itostring(line_nr());
}
Esempio n. 2
0
static void SetViewCB(Widget, XtPointer client_data, XtPointer)
{
    PlotWindowInfo *plot = (PlotWindowInfo *)client_data;

    int rot_x = 60;
    int rot_z = 30;

    XtVaGetValues(plot->vsb, XmNvalue, &rot_x, XtPointer(0));
    XtVaGetValues(plot->hsb, XmNvalue, &rot_z, XtPointer(0));

    string cmd = 
	"set view " + itostring(rot_x) + ", " + itostring(rot_z);

    send_and_replot(plot, cmd);
}
Esempio n. 3
0
// Fetch a component
static string component(const AppData& ad, DDDFont font, FontComponent n)
{
    if (n == PointSize)
    {
	int sz = 0;
	switch(font)
	{
	case DefaultDDDFont:
	    sz = ad.default_font_size;
	    break;

	case VariableWidthDDDFont:
	case SymbolDDDFont:
	    sz = ad.variable_width_font_size;
	    break;

	case FixedWidthDDDFont:
	    sz = ad.fixed_width_font_size;
	    break;

	case DataDDDFont:
	    sz = ad.data_font_size;
	    break;
	}

	return itostring(sz);
    }

    string w = component(userfont(ad, font), n);
    if (w.empty())		// nothing specified
	w = component(fallbackfont(font), n);
    return w;
}
Esempio n. 4
0
static bool refresh_tip_dialog(Widget w)
{
    MString tip = get_tip_of_the_day(w, app_data.startup_tip_count);
    if (!is_tip(tip))
    {
	// Restart from first tip
	app_data.startup_tip_count = 0;
	tip = get_tip_of_the_day(w, app_data.startup_tip_count);
    }
    if (!is_tip(tip))
	return false;

    XtVaSetValues(w, XmNmessageString, tip.xmstring(), XtPointer(0));

    MString next_tip = get_tip_of_the_day(w, app_data.startup_tip_count + 1);
    MString prev_tip = get_tip_of_the_day(w, app_data.startup_tip_count - 1);

    set_sensitive(XmMessageBoxGetChild(w, XmDIALOG_CANCEL_BUTTON),
		  is_tip(prev_tip));
    set_sensitive(XmMessageBoxGetChild(w, XmDIALOG_HELP_BUTTON),
		  is_tip(next_tip));

    string title = DDD_NAME " Tip of the Day #" + 
	itostring(app_data.startup_tip_count);
    XtVaSetValues(XtParent(w), XmNtitle, title.chars(), XtPointer(0));

    return true;
}
Esempio n. 5
0
// OK pressed in `Open Process'
static void openProcessDone(Widget w, XtPointer client_data, 
			    XtPointer call_data)
{
    int pid = get_pid(w, client_data, call_data);
    if (pid <= 0)
    {
	gdbUpdateProcessesCB(w, client_data, call_data);	
	return;
    }

    XtUnmanageChild(w);

    ProgramInfo info;

    if (pid == info.pid)
    {
	set_status("Already attached to process " + itostring(pid) + ".");
	return;
    }

    if (info.file == NO_GDB_ANSWER || info.file.empty())
    {
	post_error("No program.", "no_program", w);
	return;
    }

    // GDB does not always detach processes upon opening new
    // files, so we do it explicitly
    if (info.attached)
	gdb_command(gdb->detach_command(info.pid));

    // Attach to new process
    gdb_command(gdb->attach_command(pid, info.file));
}
Esempio n. 6
0
static void SelectCB(Widget, XtPointer client_data, XtPointer)
{
    string& reply = *((string *)client_data);

    IntArray numbers;
    getItemNumbers(gdb_selection_list_w, numbers);
    if (numbers.size() > 0)
	reply = itostring(numbers[0]) + "\n";
}
Esempio n. 7
0
string BreakPoint::symbol() const
{
    char c;
    if (!enabled())
	c = '_';
    else if (!condition().empty() || ignore_count() != 0)
	c = '?';
    else
	c = '#';

    return c + itostring(number()) + c;
}
Esempio n. 8
0
// Select a process
static void SelectProcessCB(Widget w, XtPointer client_data, 
			    XtPointer call_data)
{
    XmListCallbackStruct *cbs = (XmListCallbackStruct *)call_data;
    int pos = cbs->item_position;
    if (pos == 1)
	XmListDeselectAllItems(w); // Title selected
    else
	ListSetAndSelectPos(w, pos);

    int pid = get_pid(w, client_data, call_data);
    if (pid <= 0)
	set_status("");
    else
	set_status("Process " + itostring(pid));
}
Esempio n. 9
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);
}
Esempio n. 10
0
static void SaveTipCountCB(Widget, XtPointer = 0, XtPointer = 0)
{
    create_session_dir(DEFAULT_SESSION);
    const string file = session_tips_file();

    std::ofstream os(file.chars());
    os << 
	"! " DDD_NAME " tips file\n"
	"\n"
       << app_value(XtNstartupTipCount,
		    itostring(++app_data.startup_tip_count)) << "\n";

    os.close();
    if (os.bad())
    {
	post_error("Cannot save tip count in " + quote(file),
		   "options_save_error");
    }
}
Esempio n. 11
0
static MString get_tip_of_the_day(Widget w, int n)
{
    struct tip_of_the_day_resource_values {
	XmString tip;
    };

    const string tip_name = "tip" + itostring(n);

    XtResource r;
    r.resource_name   = XTRESSTR(tip_name.chars());
    r.resource_class  = XTRESSTR("Tip");
    r.resource_type   = XmRXmString;
    r.resource_size   = sizeof(XmString);
    r.resource_offset = XtOffsetOf(tip_of_the_day_resource_values, tip);
    r.default_type    = XtRImmediate;
    r.default_addr    = XtPointer(0);

    tip_of_the_day_resource_values values;
    XtGetApplicationResources(w, &values, &r, 1, ArgList(0), 0);

    return MString(values.tip, true);
}
Esempio n. 12
0
bool lock_session_dir(Display *display,
		      const string& session, 
		      LockInfo& info)
{
    info.pid = 0;
    string lock_file = session_lock_file(session);

    {
	std::ifstream is(lock_file.chars());
	if (!is.bad())
	{
	    string version;
	    is >> version;

	    if (version.contains(DDD_NAME, 0))
	    {
		// Lock already exists -- use contents as diagnostics
		is >> info.hostname
		   >> info.pid 
		   >> info.display 
		   >> info.uid
		   >> info.username;

		if (info.username.empty())
		{
		    // DDD 3.0.90 and earlier do not save the user name
		    info.username = itostring(info.uid);
		}

		if (info.hostname != fullhostname())
		    return false;	// Process running on remote host

		if (info.pid > 0 && kill(info.pid, 0) == 0)
		    return false;	// Process running on host
	    }
	}
Esempio n. 13
0
// Initialization
void DispValue::init(DispValue *parent, int depth, string& value,
		     DispValueType given_type)
{
#if LOG_CREATE_VALUES
    std::clog << "Building value from " << quote(value) << "\n";
#endif

    // Be sure the value is not changed in memory
    value.consuming(true);

    const char *initial_value = value.chars();

    static const DispValueArray empty(0);
    _children = empty;

    if (background(value.length()))
    {
	clear();

	mytype = Simple;
	_value = "(Aborted)";
	value  = "Aborted\n";
	return;
    }

    mytype = given_type;
    if (mytype == UnknownType && 
	(parent == 0 || parent->type() == List) && print_name.empty())
	mytype = Text;
    if (mytype == UnknownType && parent == 0 && is_user_command(print_name))
	mytype = List;
    if (mytype == UnknownType)
	mytype = determine_type(value);

    bool ignore_repeats = (parent != 0 && parent->type() == Array);

    char perl_type = '\0';

    switch (mytype)
    {

    case Simple:
    {
	_value = read_simple_value(value, depth, ignore_repeats);
#if LOG_CREATE_VALUES
	std::clog << mytype << ": " << quote(_value) << "\n";
#endif
	perl_type = '$';
	break;
    }

    case Text:
    {
	// Read in a line of text
	if (value.contains('\n'))
	    _value = value.through('\n');
	else
	    _value = value;
	value = value.after('\n');
#if LOG_CREATE_VALUES
	std::clog << mytype << ": " << quote(_value) << "\n";
#endif
	perl_type = '$';
	break;
    }

    case Pointer:
    {
	_value = read_pointer_value(value, ignore_repeats);
	_dereferenced = false;

#if LOG_CREATE_VALUES
	std::clog << mytype << ": " << quote(_value) << "\n";
#endif
	// Hide vtable pointers.
	if (_value.contains("virtual table") || _value.contains("vtable"))
	    myexpanded = false;
	perl_type = '$';

	// In Perl, pointers may be followed by indented `pointed to'
	// info.  Skip this.
	if (gdb->type() == PERL)
	{
	    while (value.contains("\n  ", 0))
	    {
		value = value.after("\n  ");
		value = value.from("\n");
	    }
	}		
	break;
    }

    case Array:
    {
	string base = normalize_base(myfull_name);

	_orientation = app_data.array_orientation;

#if LOG_CREATE_VALUES
	std::clog << mytype << ": " << "\n";
#endif

	read_array_begin(value, myaddr);

	// Check for `vtable entries' prefix.
	string vtable_entries = read_vtable_entries(value);
	if (!vtable_entries.empty())
	{
	    _children += parse_child(depth, vtable_entries, myfull_name);
	}

	// Read the array elements.  Assume that the type is the
	// same across all elements.
	DispValueType member_type = UnknownType;
	if (!_have_index_base)
	{
	    _index_base = index_base(base, depth);
	    _have_index_base = true;
	}
	int array_index = _index_base;

	// The array has at least one element.  Otherwise, GDB
	// would treat it as a pointer.
	do {
	    const char *repeated_value = value.chars();
	    string member_name = 
		gdb->index_expr("", itostring(array_index++));
	    DispValue *dv = parse_child(depth, value,
					add_member_name(base, member_name), 
					member_name, member_type);
	    member_type = dv->type();
	    _children += dv;

	    int repeats = read_repeats(value);

	    if (expand_repeated_values)
	    {
		// Create one value per repeat
		while (--repeats > 0)
		{
		    member_name = 
			gdb->index_expr("", itostring(array_index++));
		    string val = repeated_value;
		    DispValue *repeated_dv = 
			parse_child(depth, val, 
				    add_member_name(base, member_name),
				    member_name, member_type);
		    _children += repeated_dv;
		}
	    }
	    else
	    {
		// Show repetition in member
		if (repeats > 1)
		{
		    array_index--;

#if 0
		    // We use the GDB `artificial array' notation here,
		    // since repeat recognition is supported in GDB only.
		    member_name += "@" + itostring(repeats);

		    dv->full_name() = add_member_name(base, member_name);
		    dv->name()      = member_name;
#endif
		    dv->repeats()   = repeats;

		    array_index += repeats;
		}
	    }

	    if (background(value.length()))
	    {
		init(parent, depth, value);
		return;
	    }
	} while (read_array_next(value));
	read_array_end(value);

	// Expand only if at top-level.
	myexpanded = (depth == 0 || nchildren() <= 1);

#if LOG_CREATE_VALUES
	std::clog << mytype << " has " << nchildren() << " members\n";
#endif
	perl_type = '@';
	break;
    }

    case List:
	// Some DBXes issue the local variables via a frame line, just
	// like `set_date(d = 0x10003060, day_of_week = Sat, day = 24,
	// month = 12, year = 1994)'.  Make this more readable.
	munch_dump_line(value);

	// FALL THROUGH
    case Struct:
    {
	_orientation  = app_data.struct_orientation;
	_member_names = app_data.show_member_names;

	bool found_struct_begin   = false;
	bool read_multiple_values = false;
	
#if LOG_CREATE_VALUES
	std::clog << mytype << " " << quote(myfull_name) << "\n";
#endif
	string member_prefix = myfull_name;
	string member_suffix = "";
	if (mytype == List)
	{
	    member_prefix = "";
	    read_multiple_values = true;
	}
	else
	{
	    // In C and Java, `*' binds tighter than `.'
	    if (member_prefix.contains('*', 0))
	    {
		if (gdb->program_language() == LANGUAGE_C)
		{
		    // Use the C `->' operator instead
		    member_prefix.del("*");
		    if (member_prefix.contains('(', 0) &&
			member_prefix.contains(')', -1))
			member_prefix = unquote(member_prefix);

#if RUNTIME_REGEX
		    static regex rxchain("[-a-zA-Z0-9::_>.`]+");
#endif
		    if (member_prefix.matches(rxchain))
		    {
			// Simple chain of identifiers - prepend `->'
			member_prefix += "->";
		    }
		    else
		    {
			member_prefix.prepend("(");
			member_prefix += ")->";
		    }
		}
		else
		{
		    member_prefix.prepend("(");
		    member_prefix += ").";
		}
	    }
	    else if (gdb->program_language() == LANGUAGE_PERL)
	    {
		// In Perl, members of A are accessed as A{'MEMBER_NAME'}
		member_prefix = normalize_base(member_prefix) + "{'";
		member_suffix = "'}";
	    }
	    else if (gdb->program_language() == LANGUAGE_PHP)
	    {
		// In PHP, members of $A are accessed as $A['MEMBER_NAME']
		member_prefix = normalize_base(member_prefix) + "['";
		member_suffix = "']";
	    }
	    else if (gdb->program_language() == LANGUAGE_FORTRAN)
	    {
		// In Fortran, members of A are accessed as A%B
		member_prefix = normalize_base(member_prefix) + "%";
	    }
	    else
	    {
		// In all other languages, members are accessed as A.B
		member_prefix = normalize_base(member_prefix) + ".";
	    }

	    // In case we do not find a struct beginning, read only one value
	    found_struct_begin = read_struct_begin(value, myaddr);
	    read_multiple_values = found_struct_begin;
	}

	// Prepend base class in case of multiple inheritance
	// FIXME: This should be passed as an argument
	static string baseclass_prefix;
	member_prefix += baseclass_prefix;
	int base_classes = 0;

	bool more_values = true;
	while (more_values)
	{
	    // In a List, we may have `member' names like `(a + b)'.
	    // Don't be picky about this.
	    bool picky = (mytype == Struct);
	    string member_name = read_member_name(value, picky);

	    if (member_name.empty())
	    {
		// Some struct stuff that is not a member
		DispValue *dv = parse_child(depth, value, myfull_name, "");

		if (dv->type() == Struct)
		{
		    // What's this - a struct within a struct?  Just
		    // adopt the members.
		    // (This happens when we finally found the struct
		    // after having read all the AIX DBX base classes.)
		    for (int i = 0; i < dv->nchildren(); i++)
		    {
			DispValue *dv2 = dv->child(i)->link();
			_children += dv2;
		    }
		    dv->unlink();
		}
		else
		{
		    _children += dv;
		}

		more_values = read_multiple_values && read_struct_next(value);
	    }
	    else if (is_BaseClass_name(member_name))
	    {
		// Base class member
		string saved_baseclass_prefix = baseclass_prefix;
		base_classes++;

		if (base_classes > 1)
		{
		    // Multiple inheritance.  Be sure to
		    // reference further members unambiguously.
		    //
		    // Note: we don't do that for the first base class,
		    // because this might turn ambiguous again.
		    //
		    // Example:
		    //
		    //    Base
		    //    |   |
		    //    I1 I2
		    //     \ /
		    //      C
		    //
		    // Members of I1::Base are not prefixed, members
		    // of I2::Base get `I2::' as base class prefix.
		    // If we did this already for the first base class,
		    // members of both I1 and I2 would get `Base::' as
		    // base class prefix.

		    switch (gdb->program_language())
		    {
		    case LANGUAGE_C: // C++
			baseclass_prefix = unquote(member_name) + "::";
			break;

		    default:
			// Do nothing (yet)
			break;
		    }
		}

		DispValue *dv = 
		    parse_child(depth, value, myfull_name, member_name);
		_children += dv;

		baseclass_prefix = saved_baseclass_prefix;

		more_values = read_multiple_values && read_struct_next(value);

		// Skip a possible `members of CLASS:' prefix
		read_members_prefix(value);

		// AIX DBX does not place a separator between base
		// classes and the other members, so we always
		// continue reading after having found a base
		// class.  After all, the own class members are
		// still missing.
		if (mytype == Struct && !found_struct_begin)
		    more_values = true;
	    }
	    else
	    {
		// Ordinary member
		string full_name = "";

		if (member_name == " ")
		{
		    // Anonymous union
		    full_name = myfull_name;
		}
		
		if (member_name.contains('.'))
		{
		    if (gdb->has_quotes())
		    {
			// The member name contains `.' => quote it.  This
			// happens with vtable pointers on Linux (`_vptr.').
			full_name = member_prefix + quote(member_name, '\'') + 
			    member_suffix;
		    }
		    else
		    {
			// JDB (and others?) prepend the class name 
			// to inherited members.  Omit this.
			full_name = 
			    member_prefix + member_name.after('.', -1) + 
			    member_suffix;
		    }
		}
		
		if (full_name.empty())
		{
		    // Ordinary member
		    full_name = member_prefix + member_name + member_suffix;
		}

		DispValue *child = 
		    parse_child(depth, value, full_name, member_name);

		if (child->type() == Text)
		{
		    // Found a text as child - child value must be empty
		    string empty = "";
		    _children += 
			parse_child(depth, empty, full_name, member_name);

		    string v = child->value();
		    strip_space(v);
		    if (!v.empty())
			_children += child;
		}
		else
		{
		    _children += child;
		}

		more_values = read_multiple_values && read_struct_next(value);
	    }

	    if (background(value.length()))
	    {
		init(parent, depth, value);
		return;
	    }
	}

	if (mytype == List && !value.empty())
	{
	    // Add remaining value as text
	    _children += parse_child(depth, value, "");
	}

	if (found_struct_begin)
	{
	    // Skip the remainder
	    read_struct_end(value);
	}

	// Expand only if at top-level.
	myexpanded = (depth == 0 || nchildren() <= 1);

#if LOG_CREATE_VALUES
	std::clog << mytype << " "
		  << quote(myfull_name)
		  << " has " << nchildren() << " members\n";
#endif

	perl_type = '%';
	break;
    }

    case Reference:
    {
	myexpanded = true;

	int sep = value.index('@');
	sep = value.index(':', sep);

	string ref = value.before(sep);
	value = value.after(sep);

	string addr = gdb->address_expr(myfull_name);

	_children += parse_child(depth, ref, addr, myfull_name, Pointer);
	_children += parse_child(depth, value, myfull_name);

	if (background(value.length()))
	{
	    init(parent, depth, value);
	    return;
	}

	perl_type = '$';	// No such thing in Perl...
	break;
    }

    case Sequence:
    case UnknownType:
	assert(0);
	abort();
    }

    // Handle trailing stuff (`sequences')
    if (parent == 0 || parent->type() != Sequence)
    {
	bool need_clear = true;
	while (sequence_pending(value, parent))
	{
	    if (need_clear)
	    {
#if LOG_CREATE_VALUES
		std::clog << "Sequence detected at " << quote(value) << "\n";
#endif

		clear();
		value = initial_value;

		mytype = Sequence;

#if LOG_CREATE_VALUES
		std::clog << mytype << " " << quote(myfull_name) << "\n";
#endif

		need_clear = false;
	    }
	    
	    const char *old_value = value.chars();

	    DispValue *dv = parse_child(depth, value, myfull_name);

	    if (value == old_value)
	    {
		// Nothing consumed - stop here
		dv->unlink();
		break;
	    }
	    else if (dv->type() == Simple && dv->value().empty())
	    {
		// Empty value - ignore
		dv->unlink();
	    }
	    else
	    {
		_children += dv;
	    }
	}

#if LOG_CREATE_VALUES
	if (!need_clear)
	{
	    std::clog << mytype << " "
		      << quote(myfull_name)
		      << " has " << nchildren() << " members\n";
	}
#endif
    }

    if (gdb->program_language() == LANGUAGE_PERL && is_perl_prefix(perl_type))
    {
	// Set new type
	if (!myfull_name.empty() && is_perl_prefix(myfull_name[0]))
	    myfull_name[0] = perl_type;
    }

    background(value.length());
    changed = true;
}
Esempio n. 14
0
// Create list of processes
static void update_processes(Widget processes, bool keep_selection)
{
    StatusDelay delay("Getting list of processes");

    string cmd = sh_command(app_data.ps_command) + " 2>&1";
    FILE *fp = popen(cmd.chars(), "r");
    if (fp == 0)
    {
	delay.outcome = strerror(errno);
	return;
    }

    StringArray all_process_list;
    int c;
    string line = "";
    bool first_line = true;

    while ((c = getc(fp)) != EOF)
    {
	if (c == '\n')
	{
	    if (first_line || valid_ps_line(line, app_data.ps_command))
		all_process_list += line;
#if 0
	    else
		std::clog << "Excluded: " << line << "\n";
#endif

	    if (first_line)
	    {
		// Find first occurrence of `PID' title
		ps_pid_index = line.index(" PID ");
		if (ps_pid_index < 0)
		    ps_pid_index = 0;
	    }

	    line = "";
	    first_line = false;
	}
	else
	{
	    line += c;
	}
    }

    pclose(fp);
    sortProcesses(all_process_list);
    DynIntArray pids(all_process_list.size());

    // If GDB cannot send a signal to the process, we cannot debug it.
    // Try a `kill -0' (via GDB, as it may be setuid) and filter out
    // all processes in the `kill' diagnostic -- that is, all
    // processes that `kill' could not send a signal.
    string kill = "kill -0";

    if (gdb->has_handler_command())
	kill = "/usr/bin/kill -0"; // Bypass built-in SUN DBX command

    int i;
    for (i = 0; i < all_process_list.size(); i++)
    {
	pids[i] = ps_pid(all_process_list[i]);
	if (pids[i])
	    kill += string(" ") + itostring(pids[i]);
    }
#if defined(__sun) 
    // bypass underlying debugger
    // Fix for Sun: use /usr/bin/kill
    string kill_result;
    {
      std::ostringstream os;
      kill += " 2>&1";
      FILE *fp = popen(kill.chars(), "r");
      if (fp != 0)
      {
	  int c;
	  while ((c = getc(fp)) != EOF)
	  {
	      os << (char)c;
	  }
	  pclose(fp);
      }
      kill_result = os;
    }
#else
    string kill_result = gdb_question(gdb->shell_command(kill));
#endif
    i = 0;
    while (i >= 0)
    {
	i = kill_result.index(rxint, i);
	if (i >= 0)
	{
	    int bad_pid = atoi(kill_result.chars() + i);
	    for (int k = 0; k < all_process_list.size(); k++)
	    {
		if (pids[k] != 0 && pids[k] == bad_pid)
		{
#if 0
		    std::clog << "Excluded: " << all_process_list[k] << "\n";
#endif
		    all_process_list[k] = NO_GDB_ANSWER;
		}
	    }
	    i++;
	}
    }

    StringArray process_list;
    for (i = 0; i < all_process_list.size(); i++)
	if (all_process_list[i] != NO_GDB_ANSWER)
	    process_list += all_process_list[i];

    // Now set the selection.
    bool *selected = new bool[process_list.size()];
    for (i = 0; i < process_list.size(); i++)
	selected[i] = false;

    int pos = -1;
    if (keep_selection)
    {
	// Preserve old selection: each PID selected before will also be
	// selected after.
	IntArray selection;
	getPIDs(processes, selection);

	for (i = 0; i < selection.size(); i++)
	{
	    for (int j = 0; j < process_list.size(); j++)
		if (selection[i] == ps_pid(process_list[j]))
		{
		    if (pos < 0)
			pos = j;
		    selected[j] = true;
		}
	}
    }

    if (pos < 0)
    {
	// Create new selection from current file and current pid.
	ProgramInfo info;

	// Check for current pid; if found, highlight it.
	for (i = 0; pos < 0 && i < process_list.size(); i++)
	{
	    if (info.pid != 0 && ps_pid(process_list[i]) == info.pid)
		pos = i;
	}

	if (pos < 0)
	{
	    // Not found? Try leftmost occurrence of process base name.
	    string current_base = basename(info.file.chars());
	    int leftmost = INT_MAX;
	    for (i = 0; i < process_list.size(); i++)
	    {
		int occurrence = process_list[i].index(current_base);
		if (occurrence >= 0 && occurrence < leftmost 
		    && ps_pid(process_list[i]) > 0)
		{
		    leftmost = occurrence;
		    pos = i;
		}
	    }
	}
    }

    if (pos >= 0)
	selected[pos] = true;

    setLabelList(processes, process_list.values(),
		 selected, process_list.size(), true, false);

    if (pos >= 0)
	ListSetAndSelectPos(processes, pos + 1);

    delete[] selected;
}
Esempio n. 15
0
void UndoBuffer::remap_breakpoint(string& cmd, int old_bp, int new_bp)
{
    const string old_num = "@" + itostring(old_bp) + "@";
    const string new_num = "@" + itostring(new_bp) + "@";
    cmd.gsub(old_num, new_num);
}
Esempio n. 16
0
bool UndoBuffer::process_command(UndoBufferEntry& entry)
{
    // Process command
    string commands;
    if (entry.has(UB_EXEC_COMMAND))
	commands = entry[UB_EXEC_COMMAND];
    else if (entry.has(UB_COMMAND))
	commands = entry[UB_COMMAND];
    else
	return true;		// Nothing to do

    entry.remove(UB_COMMAND);
    entry.remove(UB_EXEC_COMMAND);

    //string original_commands = commands;
    int bp_count = 0;
    undoing = true;

    bool confirm = false;

    if (!commands.empty() && gdb->type() == GDB)
    {
	gdb_command("show confirm", 0, get_confirm, &confirm);
	syncCommandQueue();
    }

    if (confirm)
    {
	// Turn confirmation off during undo/redo.
	gdb_question("set confirm off");
    }

    while (!commands.empty())
    {
	string cmd;
	if (commands.contains('\n'))
	    cmd = commands.before('\n');
	else
	    cmd = commands;
	commands = commands.after('\n');

	// Handle breakpoint remappings
	if (cmd.contains(REMAP_COMMAND, 0))
	{
	    int old_bp_nr = atoi(cmd.chars() + strlen(REMAP_COMMAND "@"));
	    int new_bp_nr = source_view->next_breakpoint_number() + bp_count++;

	    remap_breakpoint(old_bp_nr, new_bp_nr);
	    remap_breakpoint(commands, old_bp_nr, new_bp_nr);

	    continue;
	}

	// Replace all occurrences of `@N@' by N
#if RUNTIME_REGEX
	static regex rxnum("@[0-9]+@");
#endif
	int i;
	while ((i = index(cmd, rxnum, "@")) >= 0)
	{
	    int num = atoi(cmd.chars() + i + 1);
	    int j = cmd.index('@', i + 1);
	    cmd.at(i, j - i + 1) = itostring(num);
	}

	if (cmd.contains("set confirm", 0))
	    confirm = false;	// Don't overwrite

	// Execute command.  This will result in new redo command(s)
	// being passed to add_command().
	Command c(cmd);
	c.priority = COMMAND_PRIORITY_SYSTEM;
	gdb_command(c);

	// Wait until this command is processed
	syncCommandQueue();
    }

    if (confirm)
	gdb_question("set confirm on");

    if (!entry.has(UB_COMMAND) && !entry.has(UB_EXEC_COMMAND))
    {
	// We had an error during execution
	return false;
    }

    undoing = false;

    return true;
}
Esempio n. 17
0
	// ctor from int ...
	StrInt(int s) : snum(itostring(s)) {}
Esempio n. 18
0
// Update breakpoint information
bool BreakPoint::update(string& info_output,
			std::ostream& undo_commands,
			bool& need_total_undo)
{
    string file = file_name();
    BreakPoint new_bp(info_output, arg(), number(), file);

    bool changed       = false;
    myenabled_changed  = false;
    myposition_changed = false;
    myfile_changed     = false;
    myaddress_changed  = false;
    need_total_undo    = false;

    const string num = "@" + itostring(number()) + "@";

    if (new_bp.number() != number())
    {
	mynumber = new_bp.number();
	need_total_undo = changed = true;
    }

    if (new_bp.type() != type())
    {
	mytype = new_bp.type();
	need_total_undo = changed = myenabled_changed = true;
    }

    if (new_bp.dispo() != dispo())
    {
	need_total_undo = changed = myenabled_changed = true;
	mydispo = new_bp.dispo();
    }

    if (new_bp.watch_mode() != watch_mode())
    {
	need_total_undo = changed = myenabled_changed = true;
	mywatch_mode = new_bp.watch_mode();
    }

    if (new_bp.myenabled != myenabled)
    {
	changed = myenabled_changed = true;
	myenabled = new_bp.myenabled;

	if (myenabled)
	{
	    if (gdb->has_disable_command())
		undo_commands << gdb->disable_command(num) << "\n";
	    else
		need_total_undo = true;
	}
	else
	{
	    if (gdb->has_enable_command())
		undo_commands << gdb->enable_command(num) << "\n";
	    else
		need_total_undo = true;
	}
    }

    if (type() == BREAKPOINT)
    {
	if (new_bp.address() != address())
	{
	    changed = myaddress_changed = true;
	    myaddress = new_bp.address();
	}

	if (new_bp.func() != func())
	{
	    changed = myposition_changed = true;
	    myfunc = new_bp.func();
	}

	if (new_bp.file_name() != file_name())
	{
	    changed = myposition_changed = myfile_changed = true;
	    myfile_name = new_bp.file_name();
	}

	if (new_bp.line_nr() != line_nr())
	{
	    changed = myposition_changed = true;
	    myline_nr = new_bp.line_nr();
	}
    }
    else if (type() == WATCHPOINT)
    {
	if (new_bp.expr() != expr())
	{
	    changed = true;
	    myexpr = new_bp.expr();
	}
    }

    if (new_bp.infos() != infos())
    {
	changed = true;
	myinfos = new_bp.infos();
    }

    if (new_bp.ignore_count() != ignore_count())
    {
	if (gdb->has_ignore_command())
	    undo_commands << gdb->ignore_command(num, myignore_count) << "\n";
	else
	    need_total_undo = true;

	changed = myenabled_changed = true;
	myignore_count = new_bp.ignore_count();
    }

    if (new_bp.mycondition != mycondition)
    {
	if (gdb->has_condition_command())
	    undo_commands << gdb->condition_command(num, condition()) << "\n";
	else
	    need_total_undo = true;

	changed = myenabled_changed = true;
	mycondition = new_bp.mycondition;
    }

    if (!equal(new_bp.commands(), commands()))
    {
        if (gdb->type() == GDB || gdb->type() == PYDB || gdb->type() == BASH)
	{
	    undo_commands << "commands " << num << '\n';
	    for (int i = 0; i < commands().size(); i++)
		undo_commands << commands()[i] << '\n';
	    undo_commands << "end\n";
	}

	changed = myenabled_changed = true;
	mycommands = new_bp.commands();
    }

    return changed;
}
Esempio n. 19
0
// Create a new plot window
PlotAgent *new_plotter(const string& name, DispValue *source)
{
    static int tics = 1;

    string cmd = app_data.plot_command;
    cmd.gsub("@FONT@", make_font(app_data, FixedWidthDDDFont));

    string window_name = ddd_NAME "plot" + itostring(tics++);
    if (cmd.contains("@NAME@"))
	cmd.gsub("@NAME@", window_name);
    else
	cmd += " -name " + window_name;

    // Create shell
    PlotWindowInfo *plot = new_decoration(name);
    if (plot == 0)
	return 0;

    plot->source      = source;
    plot->window_name = window_name;
    XtVaSetValues(plot->shell, XmNuserData, XtPointer(True), XtPointer(0));

    // Pop up a working dialog
    static Widget dialog = 0;
    if (dialog == 0)
    {
	Arg args[10];
	Cardinal arg = 0;
	dialog = verify(XmCreateWorkingDialog(find_shell(),
					      XMST("launch_plot_dialog"), 
					      args, arg));
	XtUnmanageChild(XmMessageBoxGetChild(dialog,
					     XmDIALOG_OK_BUTTON));
	XtUnmanageChild(XmMessageBoxGetChild(dialog,
					     XmDIALOG_HELP_BUTTON));
    }

    XtRemoveAllCallbacks(dialog, XmNcancelCallback);
    XtAddCallback(dialog, XmNcancelCallback, CancelPlotCB, XtPointer(plot));
    plot->working_dialog = dialog;

    string base = cmd;
    if (base.contains(' '))
	base = cmd.before(' ');
    MString msg = rm("Starting ") + tt(base) + rm("...");
    XtVaSetValues(dialog, XmNmessageString, msg.xmstring(), XtPointer(0));
    manage_and_raise(dialog);
    wait_until_mapped(dialog);

    // Invoke plot process
    PlotAgent *plotter = 
	new PlotAgent(XtWidgetToApplicationContext(plot->shell), cmd);

    XtAddCallback(plot->shell, XtNpopdownCallback,
		  CancelPlotCB, XtPointer(plot));

    if (plot->area != 0)
    {
	XtAddCallback(plot->area->widget(), XmNexposeCallback,
		      ExposePlotAreaCB, XtPointer(plot));
	XtAddCallback(plot->area->widget(), XmNresizeCallback,
		      ResizePlotAreaCB, XtPointer(plot));
    }

    string init = app_data.plot_init_commands;
    init.prepend("set term " + string(app_data.plot_term_type) + "\n");
    if (!init.empty() && !init.contains('\n', -1))
	init += '\n';

    // Add trace handlers
    plotter->addHandler(Input,  TraceInputHP);     // Gnuplot => DDD
    plotter->addHandler(Output, TraceOutputHP);    // DDD => Gnuplot
    plotter->addHandler(Error,  TraceErrorHP);     // Gnuplot Errors => DDD

    // Show Gnuplot Errors in status line
    plotter->addHandler(Error,  SetStatusHP,       (void *)plot);

    // Handle death
    plotter->addHandler(Died, PlotterNotFoundHP, (void *)plot);
    plotter->addHandler(Died, DeletePlotterHP,   (void *)plot);

    if (plot->area != 0)
	plotter->addHandler(Plot, GetPlotHP, (void *)plot);

    plotter->start_with(init);
    plot->plotter = plotter;

    return plotter;
}
Esempio n. 20
0
void BreakPoint::process_perl(string& info_output)
{
    // Format: [FILE:]
    //          LINE_NO: LINE
    //           INFO 1
    //           INFO 2 ...

    if (!info_output.contains(' ', 0))
    {
	const string first_line = info_output.before('\n');
	if (first_line.contains(':', -1))
	{
	    // Get leading file name
	    myfile_name = first_line.before(':');
	    info_output = info_output.after('\n');
	}
    }

    static const StringArray empty;
    mycommands = empty;
    myline_nr = atoi(info_output.chars());
    info_output = info_output.after('\n');
    bool break_seen = false;
    while (info_output.contains("  ", 0))
    {
	string info = info_output.before('\n');
	info_output = info_output.after('\n');

	strip_space(info);
	if (info.contains("break if ", 0))
	{
	    string cond = info.after(" if ");
	    while (cond.contains('(', 0) && cond.contains(')', -1))
		cond = unquote(cond);
	    if (cond == "1")
		cond = "";
	    mycondition = cond;
	    break_seen = true;
	}
	else if (info.contains("action: ", 0))
	{
	    string commands = info.after(':');
	    strip_space(commands);

	    if (commands.contains("d " + itostring(line_nr())))
		mydispo = BPDEL; // Temporary breakpoint

	    string command = "";
	    while (!commands.empty())
	    {
		const string token = read_token(commands);
		if (token != ";")
		    command += token;

		if (token == ";" || commands.empty())
		{
		    strip_space(command);
		    if (!command.empty())
		    {
			mycommands += command;
			command = "";
		    }
		}
	    }
	}
	else
	{
	    myinfos += info + '\n';
	}
    }

    if (!break_seen)
	mytype = ACTIONPOINT;
}
Esempio n. 21
0
// Return commands to restore this breakpoint, using the dummy number
// NR.  If AS_DUMMY is set, delete the breakpoint immediately in order
// to increase the breakpoint number.  If ADDR is set, use ADDR as
// (fake) address.  If COND is set, use COND as (fake) condition.
// Return true iff successful.
bool BreakPoint::get_state(std::ostream& os, int nr, bool as_dummy,
			   string pos, string cond)
{
    if (pos.empty())
    { 
	if (line_nr() > 0)
	    pos = file_name() + ":" + itostring(line_nr());
	else
	    pos = string('*') + address();
    }

    if (cond == char(-1))
	cond = real_condition();

    const string num = "@" + itostring(nr) + "@";

    switch (gdb->type())
    {
    case BASH:
    case GDB:
    case MAKE:
    case PYDB:
    case DBG:
    {
	switch (type())
	{
	case BREAKPOINT:
	{
	    switch (dispo())
	    {
	    case BPKEEP:
	    case BPDIS:
		os << "break " << pos << "\n";
		break;

	    case BPDEL:
		os << "tbreak " << pos << "\n";
		break;
	    }
	    break;
	}

	case WATCHPOINT:
	{
	    os << gdb->watch_command(expr(), watch_mode()) << "\n";
	    break;
	}

	case TRACEPOINT:
	case ACTIONPOINT:
	{
	    // Not handled - FIXME
	    break;
	}
	}

	if (!as_dummy)
	{
	    // Extra infos
	    if (!enabled() && gdb->has_disable_command())
		os << gdb->disable_command(num) << "\n";
	    int ignore = ignore_count();
	    if (ignore > 0 && gdb->has_ignore_command())
		os << gdb->ignore_command(num, ignore) << "\n";
	    if (!cond.empty() && gdb->has_condition_command())
		os << gdb->condition_command(num, cond) << "\n";
	    if (commands().size() != 0)
	    {
		os << "commands " << num << "\n";
		for (int i = 0; i < commands().size(); i++)
		    os << commands()[i] << "\n";
		os << "end\n";
	    }
	}
	break;
    }

    case DBX:
    {
	string cond_suffix = "";
	if (!cond.empty())
	{
	    if (gdb->has_handler_command())
		cond_suffix = " -if " + cond;
	    else
		cond_suffix = " if " + cond;
	}

	switch (type())
	{
	case BREAKPOINT:
	    if (!func().empty())
	    {
		os << "stop in " << func() << "\n";
	    }
	    else if (pos.contains('*', 0))
	    {
		os << "stop at " << pos.after('*') << cond_suffix << '\n';
	    }
	    else
	    {
		os << "file "    << pos.before(':') << "\n";
		os << "stop at " << pos.after(':')  << cond_suffix << "\n";
	    }
	    break;

	case WATCHPOINT:
	    os << "stop " << expr() << cond_suffix << '\n';
	    break;

	case TRACEPOINT:
	case ACTIONPOINT:
	{
	    // Not handled - FIXME
	    break;
	}
	}

	if (!as_dummy)
	{
	    // Extra infos
	    if (!enabled() && gdb->has_disable_command())
		os << gdb->disable_command(num) << "\n";
	    int ignore = ignore_count();
	    if (ignore > 0 && gdb->has_ignore_command())
		os << gdb->ignore_command(num, ignore) << "\n";
	}
	break;
    }

    case JDB:
    {
	os << "stop at " << pos << "\n";
	break;
    }

    case XDB:
    {
	string cond_suffix;
	if (!cond.empty() && !gdb->has_condition_command())
	    cond_suffix = " {if " + cond + " {} {Q;c}}";

	if (pos.contains('*', 0))
	    os << "ba " << pos.after('*') << cond_suffix << '\n';
	else
	    os << "b " << pos << cond_suffix << "\n";

	if (!as_dummy)
	{
	    // Extra infos
	    if (!enabled() && gdb->has_disable_command())
		os << gdb->disable_command(num) << "\n";
	    int ignore = ignore_count();
	    if (ignore > 0 && gdb->has_ignore_command())
		os << gdb->ignore_command(num, ignore) << "\n";
	}
	break;
    }

    case PERL:
    {
	string cond_suffix;
	if (!cond.empty())
	    cond_suffix = " " + cond;

	os << "f " << pos.before(':') << "\n";

	if (type() == BREAKPOINT)
	    os << "b " << pos.after(':')  << cond_suffix << "\n";

	if (commands().size() != 0)
	{
	    os << "a " << pos.after(':') << " ";
	    for (int i = 0; i < commands().size(); i++)
		os << commands()[i] << ";";
	    os << "\n";
	}

	break;
    }
    }

    if (as_dummy && gdb->has_delete_command())
    {
	// Delete the breakpoint just created
	os << gdb->delete_command(num) << "\n";
    }

    return true;
}
Esempio n. 22
0
string dbx_lookup(const string& func_name, bool silent)
{
    // Protect against `1' or `' being looked up as function names
    if (!func_name.contains(rxidentifier, 0))
	return "";		// Bad function name

    if (pos_cache.has(func_name))
    {
	string pos = pos_cache[func_name];
	if (silent || !pos.empty())
	    return pos;
    }

    string reply;
    switch (gdb->type())
    {
    case DBG:
    case DBX:
    case GDB:
    case JDB:
    case PYDB:
	reply = gdb_question("list " + func_name, 0, true);
	break;

    case XDB:
	reply = gdb_question("v " + func_name, 0, true);
	break;

    case PERL:
	reply = gdb_question("l " + func_name, 0, true);
	break;

    case BASH:
	reply = gdb_question("l " + func_name, 0, true);
	break;

    case MAKE:
	reply = gdb_question("target " + func_name, 0, true);
	break;
    }

    if (reply == NO_GDB_ANSWER)
    {
	// post_gdb_busy();
	return "";
    }

    string file = "";
    int line    = 0;
    switch (gdb->type())
    {
    case GDB:
    case PYDB:	// XXX
    {
	file = reply.from('\"');
	file = file.before('\"');
	const string line_s = reply.after("Line ");
	line = atoi(line_s.chars());
	break;
    }

    case DBX:
	line = line_of_listing(reply, silent);
	if (line > 0)
	{
	    file = gdb_question("file");
	    strip_trailing_space(file);
	}
	break;

    case BASH:
    case DBG:
    case JDB:
    case MAKE:
    case PERL:
	line = line_of_listing(reply, silent);
	file = source_view->line_of_cursor();
	file = file.before(':');
	break;

    case XDB:
    {
#if RUNTIME_REGEX
	static regex rxcolons("[^:]*:[^:]*: *[0-9][0-9]*.*");
#endif
	if (reply.matches(rxcolons))
	{
	    file = reply.before(':');
	    reply = reply.after(':'); // Skip file
	    reply = reply.after(':'); // Skip function
	    strip_leading_space(reply);
	    const string line_s = reply.before(':');
	    line = atoi(line_s.chars());
	}
	else
	{
	    // post_gdb_message(reply);
	    return "";
	}
	break;
    }
    }

    string pos = "";
    if (line > 0)
	pos = file + ":" + itostring(line);

    pos_cache[func_name] = pos;
    return pos;
}
Esempio n. 23
0
void PosBuffer::filter_dbx(string& answer)
{
    string file;		// File name found
    string line;		// Line number found

    // When reaching a breakpoint, DBX issues the breakpoint
    // number before the status line.  Check for this and
    // initialize defaults from breakpoint position.
    strip_leading_space(answer);
    if (answer.contains('(', 0) || answer.contains('[', 0))
    {
	// Get breakpoint position
	string ans = answer;
	int num = read_positive_nr(ans);
	string pos = source_view->bp_pos(num);
	if (!pos.empty())
	{
	    file = pos.before(':');
	    line = pos.after(':');
	}
    }

    // DEC DBX way issue warnings like
    // `warning: "./cxxtest.C":157 has no code associated with it'
    // right within the position info.

    int start_of_warning = answer.index("\nwarning");
    if (start_of_warning >= 0)
    {
	int open_bracket  = answer.index('[');
	int close_bracket = answer.index(']');
	if (open_bracket >= 0 && open_bracket < start_of_warning &&
	    close_bracket >= 0 && close_bracket > start_of_warning)
	{
	    // Remove warning

	    int end_of_warning = answer.index('\n', start_of_warning + 1);
	    while (end_of_warning < int(answer.length()) && 
		   answer[end_of_warning] == '\n')
		end_of_warning++;

	    while (start_of_warning > 0 && 
		   answer[start_of_warning - 1] == '\n')
		start_of_warning--;

	    int warning_length = end_of_warning - start_of_warning;
	    answer.at(start_of_warning, warning_length) = "";
	}
    }

#if RUNTIME_REGEX
    static regex rxdbxfunc2(
	".*line  *[1-9][0-9]*  *in  *(file  *)?\"[^\"]*\"\n.*");
#endif
    if (already_read != PosComplete && answer.matches(rxdbxfunc2))
    {
	// AIX DBX issues `up', `down' and `func' output
	// in the format `FUNCTION(ARGS), line LINE in "FILE"'.
	// SUN DBX uses `line LINE in file "FILE"' instead.
	// We check for the `line LINE' part.

	line = answer.after(" line ");
	line = line.through(rxint);

	file = answer.after('\"');
	file = file.before('\"');

	if (!line.empty())
	{
	    already_read = PosComplete;
	    // answer = answer.after("\n");
	}
    }

#if RUNTIME_REGEX
    static regex rxdbxpos("[[][^]]*:[1-9][0-9]*[^]]*[]].*");
#endif
    int dbxpos_index = -1;
    if (already_read != PosComplete && 
	(dbxpos_index = index(answer, rxdbxpos, "[")) >= 0)
    {
	// DEC DBX issues breakpoint lines in the format
	// "[new_tree:113 ,0x400858] \ttree->right = NULL;"
		
	line = answer.from(dbxpos_index);
	if (line.contains("[#", 0))
	{
	    // This is a Ladebug breakpoint, no position info.
	}
	else
	{
	    // Note that the function name may contain "::" sequences.
	    while (line.contains("::"))
		line = line.after("::");
	    line = line.after(":");
	    line = line.through(rxint);
	    if (!line.empty())
	    {
		if (answer.index('\n', dbxpos_index) >= 0)
		{
		    already_read = PosComplete;

		    // Strip position info and line
		    strip_leading_space(answer);
		    if (answer.contains('[', 0))
			answer = answer.after("\n");
		}
		else
		{
		    // Wait for `\n' such that we can delete the line
		    answer_buffer = answer;
		    answer = "";
		    already_read = PosPart;
		    return;
		}
	    }
	}
    }

    if (already_read != PosComplete && 
	(answer.contains("stopped in ") || 
	 answer.contains("stopped at ")))
    {
	int stopped_index = answer.index("stopped");
	assert(stopped_index >= 0);

	// Stop reached
	// AIX DBX issues lines like
	// `[4] stopped in unnamed block $b382 at line 4259 in file
	//      "/msdev/sms/ms7/riosqa/src/tffi/fi2tofu.c" ($t1)'
	int in_file_index = answer.index("in file ", stopped_index);
	int bracket_index = answer.index("[", stopped_index);

	if (in_file_index >= 0)
	{
	    // File name given
	    file = answer.from(in_file_index);
	    file = file.after("in file ");
	    if (file.contains('\n'))
		file = file.before('\n');
	    if (file.contains('"', 0))
	    {
		file = file.after('"');
		file = file.before('"');
	    }
	}
	else if (bracket_index >= 0)
	{
	    // DEC DBX and SGI DBX output format:
	    // `[3] Process  1852 (cxxtest) 
	    // stopped at [::main:266 ,0x1000a028]'
	    line = answer.after(bracket_index);
	    func_buffer = line;
	    while (line.contains("::"))
		line = line.after("::");
	    line = line.from(":");
	    func_buffer = func_buffer.before(line);
	    line = line.after(":");
	    line = line.through(rxint);
	    // answer = answer.after("\n");
	}
	else
	{
	    // Function name given
	    string func = answer.after(stopped_index);
	    func = func.after("stopped");
	    if (func.contains(" at "))
		func = func.before(" at ");
	    func_buffer = func;
	}

	if (!func_buffer.empty())
	{
	    // With DEC's `ladebug', the function name is fully qualified,
	    // as in `stopped at [void tree_test(void):277 0x120003f44]'
	    // We use only the base name (`tree_test' in this case).

	    // (We could avoid this if `ladebug' offered a way to look
	    // up fully qualified names.  Does it? - AZ)
	    if (func_buffer.contains('('))
		func_buffer = func_buffer.before('(');
	    while (func_buffer.contains(' '))
		func_buffer = func_buffer.after(' ');
	}

	if (line.empty())
	{
	    line = answer.after("at line ", stopped_index);
	    line = line.through(rxint);
	    if ((!file.empty() || !func_buffer.empty()) &&
		!answer.contains("at line "))
		line = "0";
	}

	if (!line.empty())
	    already_read = PosComplete;
    }

#if RUNTIME_REGEX
    static regex rxdbxfunc("[a-zA-Z_][^[]*: *[1-9][0-9]*  *.*");
#endif
    if (already_read != PosComplete && answer.matches(rxdbxfunc))
    {
	// DEC DBX issues `up', `down' and `func' output
	// in the format `FUNCTION: LINE  TEXT'
		
	// Note that the function name may contain "::" sequences.
	line = answer;
	while (line.contains("::"))
	    line = line.after("::");

	line = line.after(":");
	strip_leading_space(line);
	if (line.contains(rxint, 0))
	{
	    line = line.through(rxint);
	    if (!line.empty())
	    {
		if (answer.contains('\n'))
		{
		    // Got it!
		    already_read = PosComplete;
		    answer = answer.after("\n");
		}
		else
		{
		    // Wait for `\n' such that we can delete the line
		    answer_buffer = answer;
		    answer = "";
		    already_read = PosPart;
		    return;
		}
	    }
	}
    }

    if (already_read != PosComplete && 
	answer.contains("Current function is "))
    {
	// Up/Down command entered
	string nr = answer.after("\n");
	if (!nr.empty())
	{
	    line = itostring(atoi(nr.chars()));
	    already_read = PosComplete;
		    
	    // Show current function only
	    answer = answer.from("Current function is ");
	    answer = answer.through("\n");
	    func_buffer = answer.after("function is ");
	    func_buffer = func_buffer.before("\n");
	}
	else
	{
	    answer_buffer = answer;
	    answer = "";
	    already_read = PosPart;
	    return;
	}
    }

    if (already_read != PosComplete && 
	(!answer.contains('\n') ||
	 (answer.contains('[') && !answer.contains(']'))))
    {
	// Position info is incomplete
	answer_buffer = answer;
	answer = "";
	already_read = PosPart;
	return;
    }

    if (already_read == PosComplete && !line.empty())
    {
	if (!file.empty())
	    pos_buffer = file + ":" + line;
	else
	    pos_buffer = line;
    }

    if (already_read == PosComplete && pos_buffer.empty())
	already_read = Null;
}
Esempio n. 24
0
// Answer GDB question
static void select_from_gdb(const string& question, string& reply)
{
    int count       = question.freq('\n') + 1;
    string *choices = new string[count];
    bool *selected  = new bool[count];

    split(question, choices, count, '\n');

    // Highlight choice #1 by default
    for (int i = 0; i < count; i++)
    {
	if (!has_nr(choices[i]))
	{
	    // Choice has no number (prompt) - remove it
	    for (int j = i; j < count - 1; j++)
		choices[j] = choices[j + 1];
	    count--;
	    i--;
	}
	else
	{
	    selected[i] = (get_positive_nr(choices[i]) == 1);
	}
    }

    if (count < 2)
    {
	// Nothing to choose from
	if (count == 1)
	{
	    // Take the first choice.
	    reply = itostring(atoi(choices[0].chars())) + "\n";
	}
	
	delete[] choices;
	delete[] selected;
	return;
    }

    // Popup selection dialog
    static string selection_reply;

    if (gdb_selection_dialog == 0)
    {
	Arg args[10];
	Cardinal arg = 0;
	XtSetArg(args[arg], XmNautoUnmanage, False); arg++;

	gdb_selection_dialog = 
	    verify(XmCreateSelectionDialog(find_shell(gdb_w),
					   XMST("gdb_selection_dialog"),
					   args, arg));
	Delay::register_shell(gdb_selection_dialog);

	XtUnmanageChild(XmSelectionBoxGetChild(gdb_selection_dialog,
					       XmDIALOG_TEXT));
	XtUnmanageChild(XmSelectionBoxGetChild(gdb_selection_dialog, 
					       XmDIALOG_SELECTION_LABEL));
	XtUnmanageChild(XmSelectionBoxGetChild(gdb_selection_dialog, 
					       XmDIALOG_APPLY_BUTTON));

	gdb_selection_list_w = XmSelectionBoxGetChild(gdb_selection_dialog, 
						      XmDIALOG_LIST);
	XtVaSetValues(gdb_selection_list_w,
		      XmNselectionPolicy, XmSINGLE_SELECT,
		      XtPointer(0));
	XtAddCallback(gdb_selection_dialog,
		      XmNokCallback, SelectCB, &selection_reply);
	XtAddCallback(gdb_selection_dialog,
		      XmNcancelCallback, CancelCB, &selection_reply);
	XtAddCallback(gdb_selection_dialog,
		      XmNhelpCallback, ImmediateHelpCB, 0);
    }

    setLabelList(gdb_selection_list_w, choices, selected, count, false, false);

    delete[] choices;
    delete[] selected;

    manage_and_raise(gdb_selection_dialog);

    selection_reply = "";
    while (selection_reply.empty() 
	   && gdb->running() && !gdb->isReadyWithPrompt())
	XtAppProcessEvent(XtWidgetToApplicationContext(gdb_w), XtIMAll);

    // Found a reply - return
    reply = selection_reply;
}