gem-graph-client/libide/debugger/ide-debugger-breakpoint.c

977 lines
27 KiB
C

/* ide-debugger-breakpoint.c
*
* Copyright 2017-2019 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "ide-debugger-breakpoint"
#include "config.h"
#include "ide-debugger-breakpoint.h"
#include "ide-debugger-private.h"
#include "ide-debugger-types.h"
typedef struct
{
gchar *function;
gchar *id;
gchar *file;
gchar *spec;
gchar *thread;
guint line;
IdeDebuggerDisposition disposition : 8;
IdeDebuggerBreakMode mode : 8;
guint enabled : 1;
IdeDebuggerAddress address;
gint64 count;
} IdeDebuggerBreakpointPrivate;
enum {
PROP_0,
PROP_ADDRESS,
PROP_COUNT,
PROP_DISPOSITION,
PROP_ENABLED,
PROP_FILE,
PROP_FUNCTION,
PROP_ID,
PROP_LINE,
PROP_MODE,
PROP_SPEC,
PROP_THREAD,
N_PROPS
};
enum {
RESET,
N_SIGNALS
};
G_DEFINE_TYPE_WITH_PRIVATE (IdeDebuggerBreakpoint, ide_debugger_breakpoint, G_TYPE_OBJECT)
static GParamSpec *properties [N_PROPS];
static guint signals [N_SIGNALS];
static void
ide_debugger_breakpoint_real_reset (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_assert (IDE_IS_DEBUGGER_BREAKPOINT (self));
g_clear_pointer (&priv->id, g_free);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
}
static void
ide_debugger_breakpoint_finalize (GObject *object)
{
IdeDebuggerBreakpoint *self = (IdeDebuggerBreakpoint *)object;
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_clear_pointer (&priv->function, g_free);
g_clear_pointer (&priv->id, g_free);
g_clear_pointer (&priv->file, g_free);
g_clear_pointer (&priv->spec, g_free);
g_clear_pointer (&priv->thread, g_free);
G_OBJECT_CLASS (ide_debugger_breakpoint_parent_class)->finalize (object);
}
static void
ide_debugger_breakpoint_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
IdeDebuggerBreakpoint *self = IDE_DEBUGGER_BREAKPOINT (object);
switch (prop_id)
{
case PROP_ADDRESS:
g_value_set_uint64 (value, ide_debugger_breakpoint_get_address (self));
break;
case PROP_ID:
g_value_set_string (value, ide_debugger_breakpoint_get_id (self));
break;
case PROP_COUNT:
g_value_set_int64 (value, ide_debugger_breakpoint_get_count (self));
break;
case PROP_DISPOSITION:
g_value_set_enum (value, ide_debugger_breakpoint_get_disposition (self));
break;
case PROP_ENABLED:
g_value_set_boolean (value, ide_debugger_breakpoint_get_enabled (self));
break;
case PROP_FILE:
g_value_set_string (value, ide_debugger_breakpoint_get_file (self));
break;
case PROP_FUNCTION:
g_value_set_string (value, ide_debugger_breakpoint_get_function (self));
break;
case PROP_LINE:
g_value_set_uint (value, ide_debugger_breakpoint_get_line (self));
break;
case PROP_MODE:
g_value_set_enum (value, ide_debugger_breakpoint_get_mode (self));
break;
case PROP_SPEC:
g_value_set_string (value, ide_debugger_breakpoint_get_spec (self));
break;
case PROP_THREAD:
g_value_set_string (value, ide_debugger_breakpoint_get_thread (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_debugger_breakpoint_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
IdeDebuggerBreakpoint *self = IDE_DEBUGGER_BREAKPOINT (object);
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
switch (prop_id)
{
case PROP_ADDRESS:
ide_debugger_breakpoint_set_address (self, g_value_get_uint64 (value));
break;
case PROP_ID:
priv->id = g_value_dup_string (value);
break;
case PROP_COUNT:
ide_debugger_breakpoint_set_count (self, g_value_get_int64 (value));
break;
case PROP_DISPOSITION:
ide_debugger_breakpoint_set_disposition (self, g_value_get_enum (value));
break;
case PROP_ENABLED:
ide_debugger_breakpoint_set_enabled (self, g_value_get_boolean (value));
break;
case PROP_FILE:
ide_debugger_breakpoint_set_file (self, g_value_get_string (value));
break;
case PROP_FUNCTION:
ide_debugger_breakpoint_set_function (self, g_value_get_string (value));
break;
case PROP_LINE:
ide_debugger_breakpoint_set_line (self, g_value_get_uint (value));
break;
case PROP_MODE:
ide_debugger_breakpoint_set_mode (self, g_value_get_enum (value));
break;
case PROP_SPEC:
ide_debugger_breakpoint_set_spec (self, g_value_get_string (value));
break;
case PROP_THREAD:
ide_debugger_breakpoint_set_thread (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_debugger_breakpoint_class_init (IdeDebuggerBreakpointClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = ide_debugger_breakpoint_finalize;
object_class->get_property = ide_debugger_breakpoint_get_property;
object_class->set_property = ide_debugger_breakpoint_set_property;
klass->reset = ide_debugger_breakpoint_real_reset;
/**
* IdeDebuggerBreakpoint:address:
*
* The address of the breakpoint, if available.
*
* Builder only supports up to 64-bit addresses at this time.
*
* Since: 3.32
*/
properties [PROP_ADDRESS] =
g_param_spec_uint64 ("address",
"Address",
"The address of the breakpoint",
0, G_MAXUINT64, IDE_DEBUGGER_ADDRESS_INVALID,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:count:
*
* The number of times the breakpoint has been reached.
*
* This is backend specific, and may not be supported by all backends.
*
* Since: 3.32
*/
properties [PROP_COUNT] =
g_param_spec_int64 ("count",
"Count",
"The number of times the breakpoint has hit",
0, G_MAXINT64, 0,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:disposition:
*
* This property describes what should happen to the breakpoint upon the
* next stop of the debugger.
*
* Generally, breakpoints are kept. But some backends allow you to remove
* a breakpoint upon the next stop of the debugger or when the breakpoint
* is next reached.
*
* This is backend specific, and not all values may be supported by all
* backends.
*
* Since: 3.32
*/
properties [PROP_DISPOSITION] =
g_param_spec_enum ("disposition",
"Disposition",
"The disposition of the breakpoint",
IDE_TYPE_DEBUGGER_DISPOSITION,
IDE_DEBUGGER_DISPOSITION_KEEP,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:enabled:
*
* This property is %TRUE when the breakpoint is enabled.
*
* Since: 3.32
*/
properties [PROP_ENABLED] =
g_param_spec_boolean ("enabled",
"Enabled",
"Enabled",
TRUE,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:function:
*
* The name of the function containing the breakpoint.
*
* The value of this is backend specific and may look vastly different
* based on the language being debugged.
*
* Since: 3.32
*/
properties [PROP_FUNCTION] =
g_param_spec_string ("function",
"Function",
"Function",
NULL,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:id:
*
* The identifier of the breakpoint.
*
* This is backend specific.
*
* Since: 3.32
*/
properties [PROP_ID] =
g_param_spec_string ("id",
"Identifier",
"The identifier for the breakpoint",
NULL,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:file:
*
* The file containing the breakpoint, if any.
*
* If the breakpoint exists at an assembly instruction that cannot be
* represented by a file, this will be %NULL.
*
* Since: 3.32
*/
properties [PROP_FILE] =
g_param_spec_string ("file",
"File",
"The file containing the breakpoint",
NULL,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:line:
*
* The line number within #IdeDebuggerBreakpoint:file where the
* breakpoint exists.
*
* Since: 3.32
*/
properties [PROP_LINE] =
g_param_spec_uint ("line",
"Line",
"Line",
0, G_MAXUINT, 0,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:mode:
*
* The mode of the breakpoint, such as a breakpoint, countpoint, or watchpoint.
*
* Since: 3.32
*/
properties [PROP_MODE] =
g_param_spec_enum ("mode",
"Mode",
"The breakpoint mode",
IDE_TYPE_DEBUGGER_BREAK_MODE,
IDE_DEBUGGER_BREAK_BREAKPOINT,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:spec:
*
* The specification for the breakpoint, which may be used by watchpoints
* to determine of the breakpoint should be applied while executing.
*
* Since: 3.32
*/
properties [PROP_SPEC] =
g_param_spec_string ("spec",
"Spec",
"The specification for a data breakpoint",
NULL,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
/**
* IdeDebuggerBreakpoint:thread:
*
* The thread the breakpoint is currently stopped in, or %NULL.
*
* Since: 3.32
*/
properties [PROP_THREAD] =
g_param_spec_string ("thread",
"Thread",
"Thread",
NULL,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
/**
* IdeDebuggerBreakpoint::reset:
* @self: An #IdeDebuggerBreakpoint
*
* The "reset" signal is emitted after the debugger has exited so that the
* breakpoint can reset any internal state. This allows the breakpoint to be
* propagated to the next debugger instance, allowing the user to move
* between debugger sessions without loosing state.
*
* Since: 3.32
*/
signals [RESET] =
g_signal_new ("reset",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IdeDebuggerBreakpointClass, reset),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
ide_debugger_breakpoint_init (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
priv->disposition = IDE_DEBUGGER_DISPOSITION_KEEP;
priv->enabled = TRUE;
priv->mode = IDE_DEBUGGER_BREAK_BREAKPOINT;
}
IdeDebuggerBreakpoint *
ide_debugger_breakpoint_new (const gchar *id)
{
return g_object_new (IDE_TYPE_DEBUGGER_BREAKPOINT,
"id", id,
NULL);
}
/**
* ide_debugger_breakpoint_get_id:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the identifier for the breakpoint that is backend specific.
*
* Returns: the id of the breakpoint
*
* Since: 3.32
*/
const gchar *
ide_debugger_breakpoint_get_id (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
return priv->id;
}
/**
* ide_debugger_breakpoint_get_address:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "address" property, which defines where the breakpoint is
* located in memory.
*
* Builder only supports up to 64-bit addresses at this time.
*
* Returns: The address of the breakpoint, if any.
*
* Since: 3.32
*/
IdeDebuggerAddress
ide_debugger_breakpoint_get_address (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), IDE_DEBUGGER_ADDRESS_INVALID);
return priv->address;
}
/**
* ide_debugger_breakpoint_set_address:
* @self: An #IdeDebuggerBreakpoint
* @address: The address of the breakpoint
*
* Sets the address of the breakpoint, if any.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_address (IdeDebuggerBreakpoint *self,
IdeDebuggerAddress address)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (priv->address != address)
{
priv->address = address;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ADDRESS]);
}
}
/**
* ide_debugger_breakpoint_get_file:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the file that contains the breakpoint. This may be %NULL, particularly
* if the breakpoint does not exist with in a known file, such as at a memory
* address.
*
* Returns: (nullable): The file containing the breakpoint, or %NULL
*
* Since: 3.32
*/
const gchar *
ide_debugger_breakpoint_get_file (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
return priv->file;
}
/**
* ide_debugger_breakpoint_set_file:
* @self: An #IdeDebuggerBreakpoint
* @file: (nullable): the file containing the breakpoint, or %NULL
*
* Sets the file that contains the breakpoint, if any.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_file (IdeDebuggerBreakpoint *self,
const gchar *file)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (g_strcmp0 (file, priv->file) != 0)
{
g_free (priv->file);
priv->file = g_strdup (file);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]);
}
}
/**
* ide_debugger_breakpoint_get_spec:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "spec" property of the breakpoint.
*
* The spec is used when the #IdeDebuggerBreakMode is
* %IDE_DEBUGGER_BREAK_WATCHPOINT.
*
* Returns: (nullable): A string containing the spec, or %NULL
*
* Since: 3.32
*/
const gchar *
ide_debugger_breakpoint_get_spec (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
return priv->spec;
}
/**
* ide_debugger_breakpoint_set_spec:
* @self: An #IdeDebuggerBreakpoint
* @spec: (nullable): the specification or %NULL
*
* Sets the specification for the debugger breakpoint. This describes
* a statement which the debugger can use to determine of the breakpoint
* should be applied when stopping the debugger.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_spec (IdeDebuggerBreakpoint *self,
const gchar *spec)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (g_strcmp0 (spec, priv->spec) != 0)
{
g_free (priv->spec);
priv->spec = g_strdup (spec);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPEC]);
}
}
/**
* ide_debugger_breakpoint_get_count:
*
* Gets the number of times the breakpoint has been reached, if supported
* by the debugger backend.
*
* Returns: An integer greater than or equal to zero representing the
* number of times the breakpoint has been reached.
*
* Since: 3.32
*/
gint64
ide_debugger_breakpoint_get_count (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
return priv->count;
}
/**
* ide_debugger_breakpoint_set_count:
*
* Sets the number of times the breakpoint has been reached if the
* breakpoint is a countpoint (or if the backend supports counting of
* regular breakpoints).
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_count (IdeDebuggerBreakpoint *self,
gint64 count)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (priv->count != count)
{
priv->count = count;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_COUNT]);
}
}
/**
* ide_debugger_breakpoint_get_mode:
*
* Gets teh mode for the breakpoint. This describes if the breakpoint
* is a normal breakpoint type, countpoint, or watchpoint.
*
* See also: #IdeDebuggerBreakMode
*
* Returns: The mode of the breakpoint
*
* Since: 3.32
*/
IdeDebuggerBreakMode
ide_debugger_breakpoint_get_mode (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
return priv->mode;
}
/**
* ide_debugger_breakpoint_set_mode:
* @self: An #IdeDebuggerBreakpoint
* @mode: An #IdeDebuggerBreakMode
*
* Sets the "mode" property for the breakpoint.
*
* This should represent the mode for which the breakpoint is used.
*
* For example, if it is a countpoint (a breakpoint which increments a
* counter), you would use %IDE_DEBUGGER_BREAK_COUNTPOINT.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_mode (IdeDebuggerBreakpoint *self,
IdeDebuggerBreakMode mode)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
g_return_if_fail (IDE_IS_DEBUGGER_BREAK_MODE (mode));
if (priv->mode != mode)
{
priv->mode = mode;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MODE]);
}
}
/**
* ide_debugger_breakpoint_get_disposition:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "disposition" property of the breakpoint.
*
* Returns: An #IdeDebugerDisposition
*
* Since: 3.32
*/
IdeDebuggerDisposition
ide_debugger_breakpoint_get_disposition (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
return priv->disposition;
}
/**
* ide_debugger_breakpoint_set_disposition:
* @self: an #IdeDebuggerBreakpoint
* @disposition: an #IdeDebuggerDisposition
*
* Sets the "disposition" property.
*
* The disposition property is used to to track what should happen to a
* breakpoint when movements are made in the debugger.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_disposition (IdeDebuggerBreakpoint *self,
IdeDebuggerDisposition disposition)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
g_return_if_fail (IDE_IS_DEBUGGER_DISPOSITION (disposition));
if (disposition != priv->disposition)
{
priv->disposition = disposition;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPOSITION]);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ENABLED]);
}
}
/**
* ide_debugger_breakpoint_get_enabled:
*
* Checks if the breakpoint is enabled.
*
* Returns: %TRUE if the breakpoint is enabled
*
* Since: 3.32
*/
gboolean
ide_debugger_breakpoint_get_enabled (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), FALSE);
return priv->enabled;
}
/**
* ide_debugger_breakpoint_set_enabled:
* @self: a #IdeDebuggerBreakpoint
* @enabled: if the breakpoint is enabled
*
* Sets the enabled state of the breakpoint instance.
*
* You must call ide_debugger_breakpoint_modify_breakpoint_async() to actually
* modify the breakpoint in the backend.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_enabled (IdeDebuggerBreakpoint *self,
gboolean enabled)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
enabled = !!enabled;
if (priv->enabled != enabled)
{
priv->enabled = enabled;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ENABLED]);
}
}
/**
* ide_debugger_breakpoint_get_function:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "function" property of the breakpoint.
*
* This is a user-readable value representing the name of the function.
*
* Since: 3.32
*/
const gchar *
ide_debugger_breakpoint_get_function (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
return priv->function;
}
/**
* ide_debugger_breakpoint_set_function:
* @self: An #IdeDebuggerBreakpoint
* @function: (nullable): the name of the function, or %NULL
*
* Sets the "function" property, which is a user-readable value representing
* the name of the function.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_function (IdeDebuggerBreakpoint *self,
const gchar *function)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (g_strcmp0 (function, priv->function) != 0)
{
g_free (priv->function);
priv->function = g_strdup (function);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FUNCTION]);
}
}
/**
* ide_debugger_breakpoint_get_line:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "line" property, which is the line number within the file
* that contains the breakpoint.
*
* This value is indexed from 1, and 0 indicates that the value is unset.
*
* Returns: An integer greater than 0 if set, otherwise 0.
*
* Since: 3.32
*/
guint
ide_debugger_breakpoint_get_line (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
return priv->line;
}
/**
* ide_debugger_breakpoint_set_line:
* @self: An #IdeDebuggerBreakpoint
*
* Sets the line for the breakpoint. A value of 0 means the line is unset.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_line (IdeDebuggerBreakpoint *self,
guint line)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (priv->line != line)
{
priv->line = line;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LINE]);
}
}
/**
* ide_debugger_breakpoint_get_thread:
* @self: An #IdeDebuggerBreakpoint
*
* Gets the "thread" property, which is the thread the breakpoint is
* currently stopped in (if any).
*
* Returns: (nullable): the thread identifier or %NULL
*
* Since: 3.32
*/
const gchar *
ide_debugger_breakpoint_get_thread (IdeDebuggerBreakpoint *self)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
return priv->thread;
}
/**
* ide_debugger_breakpoint_set_thread:
*
* Sets the thread that the breakpoint is currently stopped in.
*
* This should generally only be used by debugger implementations.
*
* Since: 3.32
*/
void
ide_debugger_breakpoint_set_thread (IdeDebuggerBreakpoint *self,
const gchar *thread)
{
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
if (g_strcmp0 (priv->thread, thread) != 0)
{
g_free (priv->thread);
priv->thread = g_strdup (thread);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_THREAD]);
}
}
gint
ide_debugger_breakpoint_compare (IdeDebuggerBreakpoint *a,
IdeDebuggerBreakpoint *b)
{
IdeDebuggerBreakpointPrivate *priv_a = ide_debugger_breakpoint_get_instance_private (a);
IdeDebuggerBreakpointPrivate *priv_b = ide_debugger_breakpoint_get_instance_private (b);
if (a == b)
return 0;
/* Rely on pointer comparison for breakpoints that
* don't yet have an identifier.
*/
if (priv_a->id == NULL && priv_b->id == NULL)
return a - b;
if (priv_a->id && priv_b->id)
{
if (g_ascii_isdigit (*priv_a->id) && g_ascii_isdigit (*priv_b->id))
return g_ascii_strtoll (priv_a->id, NULL, 10) -
g_ascii_strtoll (priv_b->id, NULL, 10);
}
return g_strcmp0 (priv_a->id, priv_b->id);
}
void
_ide_debugger_breakpoint_reset (IdeDebuggerBreakpoint *self)
{
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
g_signal_emit (self, signals [RESET], 0);
}