/* Data structures associated with breakpoints in GDB.
- Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame.h"
#include "value.h"
-#include "vec.h"
#include "ax.h"
#include "command.h"
-#include "break-common.h"
+#include "gdbsupport/break-common.h"
#include "probe.h"
#include "location.h"
#include <vector>
+#include "gdbsupport/array-view.h"
+#include "gdbsupport/function-view.h"
+#include "cli/cli-script.h"
-struct value;
struct block;
struct gdbpy_breakpoint_object;
struct gdbscm_breakpoint_object;
struct bp_location;
struct linespec_result;
struct linespec_sals;
+struct inferior;
+
+/* Enum for exception-handling support in 'catch throw', 'catch rethrow',
+ 'catch catch' and the MI equivalent. */
+
+enum exception_event_kind
+{
+ EX_EVENT_THROW,
+ EX_EVENT_RETHROW,
+ EX_EVENT_CATCH
+};
/* Why are we removing the breakpoint from the target? */
bp_loc_other /* Miscellaneous... */
};
-/* This structure is a collection of function pointers that, if
- available, will be called instead of performing the default action
- for this bp_loc_type. */
-
-struct bp_location_ops
-{
- /* Destructor. Releases everything from SELF (but not SELF
- itself). */
- void (*dtor) (struct bp_location *self);
-};
-
class bp_location
{
public:
bp_location () = default;
- bp_location (const bp_location_ops *ops, breakpoint *owner);
+ /* Construct a bp_location with the type inferred from OWNER's
+ type. */
+ explicit bp_location (breakpoint *owner);
+
+ /* Construct a bp_location with type TYPE. */
+ bp_location (breakpoint *owner, bp_loc_type type);
+
+ virtual ~bp_location ();
/* Chain pointer to the next breakpoint location for
the same parent breakpoint. */
bp_location *next = NULL;
- /* Methods associated with this location. */
- const bp_location_ops *ops = NULL;
-
/* The reference count. */
int refc = 0;
agent_expr_up cmd_bytecode;
/* Signals that breakpoint conditions and/or commands need to be
- re-synched with the target. This has no use other than
+ re-synced with the target. This has no use other than
target-side breakpoints. */
bool needs_update = false;
/* Is this particular location enabled. */
bool enabled = false;
- /* Nonzero if this breakpoint is now inserted. */
+ /* True if this breakpoint is now inserted. */
bool inserted = false;
- /* Nonzero if this is a permanent breakpoint. There is a breakpoint
+ /* True if this is a permanent breakpoint. There is a breakpoint
instruction hard-wired into the target's code. Don't try to
write another breakpoint instruction on top of it, or restore its
value. Step over it using the architecture's
gdbarch_skip_permanent_breakpoint method. */
bool permanent = false;
- /* Nonzero if this is not the first breakpoint in the list
+ /* True if this is not the first breakpoint in the list
for the given address. location of tracepoint can _never_
be duplicated with other locations of tracepoints and other
kinds of breakpoints, because two locations at the same
to find the corresponding source file name. */
struct symtab *symtab = NULL;
+
+ /* The symbol found by the location parser, if any. This may be used to
+ ascertain when an event location was set at a different location than
+ the one originally selected by parsing, e.g., inlined symbols. */
+ const struct symbol *symbol = NULL;
+
+ /* Similarly, the minimal symbol found by the location parser, if
+ any. This may be used to ascertain if the location was
+ originally set on a GNU ifunc symbol. */
+ const minimal_symbol *msymbol = NULL;
+
+ /* The objfile the symbol or minimal symbol were found in. */
+ const struct objfile *objfile = NULL;
};
/* The possible return values for print_bpstat, print_it_normal,
struct breakpoint_ops
{
- /* Destructor. Releases everything from SELF (but not SELF
- itself). */
- void (*dtor) (struct breakpoint *self);
-
/* Allocate a location for this breakpoint. */
struct bp_location * (*allocate_location) (struct breakpoint *);
which the inferior stopped, and WS is the target_waitstatus
describing the event. */
int (*breakpoint_hit) (const struct bp_location *bl,
- struct address_space *aspace,
+ const address_space *aspace,
CORE_ADDR bp_addr,
const struct target_waitstatus *ws);
This function is called inside `create_breakpoint'. */
void (*create_breakpoints_sal) (struct gdbarch *,
struct linespec_result *,
- char *, char *,
+ gdb::unique_xmalloc_ptr<char>,
+ gdb::unique_xmalloc_ptr<char>,
enum bptype, enum bpdisp, int, int,
int, const struct breakpoint_ops *,
int, int, int, unsigned);
/* Given the location (second parameter), this method decodes it and
- provides the SAL locations related to it. For ordinary
+ returns the SAL locations related to it. For ordinary
breakpoints, it calls `decode_line_full'. If SEARCH_PSPACE is
not NULL, symbol search is restricted to just that program space.
This function is called inside `location_to_sals'. */
- void (*decode_location) (struct breakpoint *b,
- const struct event_location *location,
- struct program_space *search_pspace,
- struct symtabs_and_lines *sals);
+ std::vector<symtab_and_line> (*decode_location)
+ (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace);
/* Return true if this breakpoint explains a signal. See
bpstat_explains_signal. */
watch_triggered_yes
};
-typedef struct bp_location *bp_location_p;
-DEF_VEC_P(bp_location_p);
-
-/* A reference-counted struct command_line. This lets multiple
- breakpoints share a single command list. This is an implementation
- detail to the breakpoints module. */
-struct counted_command_line;
-
/* Some targets (e.g., embedded PowerPC) need two debug registers to set
a watchpoint over a memory region. If this flag is true, GDB will use
- only one register per watchpoint, thus assuming that all acesses that
+ only one register per watchpoint, thus assuming that all accesses that
modify a memory location happen at its starting address. */
-extern int target_exact_watchpoints;
+extern bool target_exact_watchpoints;
/* Note that the ->silent field is not currently used by any commands
(though the code is in there if it was to be, and set_raw_breakpoint
struct breakpoint
{
+ virtual ~breakpoint ();
+
/* Methods associated with this breakpoint. */
const breakpoint_ops *ops = NULL;
/* Chain of command lines to execute when this breakpoint is
hit. */
- counted_command_line *commands = NULL;
+ counted_command_line commands;
/* Stack depth (address of frame). If nonzero, break only if fp
equals this. */
struct frame_id frame_id = null_frame_id;
event_location_up location;
/* The filter that should be passed to decode_line_full when
- re-setting this breakpoint. This may be NULL, but otherwise is
- allocated with xmalloc. */
- char *filter = NULL;
+ re-setting this breakpoint. This may be NULL. */
+ gdb::unique_xmalloc_ptr<char> filter;
/* For a ranged breakpoint, the location we used to find the end of
the range. */
gdbscm_breakpoint_object *scm_bp_object = NULL;
};
-/* An instance of this type is used to represent a watchpoint. It
- includes a "struct breakpoint" as a kind of base class; users
- downcast to "struct breakpoint *" when needed. */
+/* An instance of this type is used to represent a watchpoint. */
-struct watchpoint
+struct watchpoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
+ ~watchpoint () override;
/* String form of exp to use for displaying to the user (malloc'd),
or NULL if none. */
/* Value of the watchpoint the last time we checked it, or NULL when
we do not know the value yet or the value was not readable. VAL
is never lazy. */
- struct value *val;
- /* Nonzero if VAL is valid. If VAL_VALID is set but VAL is NULL,
+ value_ref_ptr val;
+
+ /* True if VAL is valid. If VAL_VALID is set but VAL is NULL,
then an error occurred reading the value. */
- int val_valid;
+ bool val_valid;
/* When watching the location of a bitfield, contains the offset and size of
the bitfield. Otherwise contains 0. */
/* Return true if BPT is either a software breakpoint or a hardware
breakpoint. */
-extern int is_breakpoint (const struct breakpoint *bpt);
+extern bool is_breakpoint (const struct breakpoint *bpt);
-/* Returns true if BPT is really a watchpoint. */
+/* Return true if BPT is of any watchpoint kind, hardware or
+ software. */
-extern int is_watchpoint (const struct breakpoint *bpt);
+extern bool is_watchpoint (const struct breakpoint *bpt);
+
+/* Return true if BPT is a C++ exception catchpoint (catch
+ catch/throw/rethrow). */
+
+extern bool is_exception_catchpoint (breakpoint *bp);
/* An instance of this type is used to represent all kinds of
- tracepoints. It includes a "struct breakpoint" as a kind of base
- class; users downcast to "struct breakpoint *" when needed. */
+ tracepoints. */
-struct tracepoint
+struct tracepoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
-
/* Number of times this tracepoint should single-step and collect
additional data. */
long step_count;
ULONGEST traceframe_usage;
/* The static tracepoint marker id, if known. */
- char *static_trace_marker_id;
+ std::string static_trace_marker_id;
/* LTTng/UST allow more than one marker with the same ID string,
although it unadvised because it confuses tools. When setting
int static_trace_marker_id_idx;
};
-typedef struct breakpoint *breakpoint_p;
-DEF_VEC_P(breakpoint_p);
\f
/* The following stuff is an abstract data type "bpstat" ("breakpoint
status"). This provides the ability to determine whether we have
is part of the bpstat is copied as well. */
extern bpstat bpstat_copy (bpstat);
-extern bpstat bpstat_stop_status (struct address_space *aspace,
- CORE_ADDR pc, ptid_t ptid,
+/* Build the (raw) bpstat chain for the stop information given by ASPACE,
+ BP_ADDR, and WS. Returns the head of the bpstat chain. */
+
+extern bpstat build_bpstat_chain (const address_space *aspace,
+ CORE_ADDR bp_addr,
const struct target_waitstatus *ws);
+
+/* Get a bpstat associated with having just stopped at address
+ BP_ADDR in thread PTID. STOP_CHAIN may be supplied as a previously
+ computed stop chain or NULL, in which case the stop chain will be
+ computed using build_bpstat_chain.
+
+ Determine whether we stopped at a breakpoint, etc, or whether we
+ don't understand this stop. Result is a chain of bpstat's such
+ that:
+
+ if we don't understand the stop, the result is a null pointer.
+
+ if we understand why we stopped, the result is not null.
+
+ Each element of the chain refers to a particular breakpoint or
+ watchpoint at which we have stopped. (We may have stopped for
+ several reasons concurrently.)
+
+ Each element of the chain has valid next, breakpoint_at,
+ commands, FIXME??? fields. */
+
+extern bpstat bpstat_stop_status (const address_space *aspace,
+ CORE_ADDR pc, thread_info *thread,
+ const struct target_waitstatus *ws,
+ bpstat stop_chain = NULL);
\f
/* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task).
/* Used for BPSTAT_WHAT_SET_LONGJMP_RESUME and
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME. True if we are handling a
longjmp, false if we are handling an exception. */
- int is_longjmp;
+ bool is_longjmp;
};
/* Tell what to do about this bpstat. */
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
bpstat bpstat_find_breakpoint (bpstat, struct breakpoint *);
-/* Nonzero if a signal that we got in target_wait() was due to
+/* True if a signal that we got in target_wait() was due to
circumstances explained by the bpstat; the signal is therefore not
random. */
-extern int bpstat_explains_signal (bpstat, enum gdb_signal);
+extern bool bpstat_explains_signal (bpstat, enum gdb_signal);
-/* Nonzero is this bpstat causes a stop. */
-extern int bpstat_causes_stop (bpstat);
+/* True if this bpstat causes a stop. */
+extern bool bpstat_causes_stop (bpstat);
-/* Nonzero if we should step constantly (e.g. watchpoints on machines
+/* True if we should step constantly (e.g. watchpoints on machines
without hardware support). This isn't related to a specific bpstat,
just to things like whether watchpoints are set. */
-extern int bpstat_should_step (void);
+extern bool bpstat_should_step ();
/* Print a message indicating what happened. Returns nonzero to
say that only the source line should be printed after this (zero
struct bpstats
{
+ bpstats ();
+ bpstats (struct bp_location *bl, bpstat **bs_link_pointer);
+ ~bpstats ();
+
+ bpstats (const bpstats &);
+ bpstats &operator= (const bpstats &) = delete;
+
/* Linked list because there can be more than one breakpoint at
the same place, and a bpstat reflects the fact that all have
been hit. */
struct breakpoint *breakpoint_at;
/* The associated command list. */
- struct counted_command_line *commands;
+ counted_command_line commands;
/* Old value associated with a watchpoint. */
- struct value *old_val;
+ value_ref_ptr old_val;
/* Nonzero if this breakpoint tells us to print the frame. */
char print;
extern int program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address);
-extern enum breakpoint_here breakpoint_here_p (struct address_space *,
+extern enum breakpoint_here breakpoint_here_p (const address_space *,
CORE_ADDR);
/* Return true if an enabled breakpoint exists in the range defined by
ADDR and LEN, in ASPACE. */
-extern int breakpoint_in_range_p (struct address_space *aspace,
+extern int breakpoint_in_range_p (const address_space *aspace,
CORE_ADDR addr, ULONGEST len);
-extern int moribund_breakpoint_here_p (struct address_space *, CORE_ADDR);
+extern int moribund_breakpoint_here_p (const address_space *, CORE_ADDR);
-extern int breakpoint_inserted_here_p (struct address_space *, CORE_ADDR);
-
-extern int regular_breakpoint_inserted_here_p (struct address_space *,
- CORE_ADDR);
+extern int breakpoint_inserted_here_p (const address_space *,
+ CORE_ADDR);
-extern int software_breakpoint_inserted_here_p (struct address_space *,
+extern int software_breakpoint_inserted_here_p (const address_space *,
CORE_ADDR);
/* Return non-zero iff there is a hardware breakpoint inserted at
PC. */
-extern int hardware_breakpoint_inserted_here_p (struct address_space *,
+extern int hardware_breakpoint_inserted_here_p (const address_space *,
CORE_ADDR);
/* Check whether any location of BP is inserted at PC. */
extern int breakpoint_has_location_inserted_here (struct breakpoint *bp,
- struct address_space *aspace,
+ const address_space *aspace,
CORE_ADDR pc);
-extern int single_step_breakpoint_inserted_here_p (struct address_space *,
+extern int single_step_breakpoint_inserted_here_p (const address_space *,
CORE_ADDR);
/* Returns true if there's a hardware watchpoint or access watchpoint
inserted in the range defined by ADDR and LEN. */
-extern int hardware_watchpoint_inserted_in_range (struct address_space *,
+extern int hardware_watchpoint_inserted_in_range (const address_space *,
CORE_ADDR addr,
ULONGEST len);
if ASPACE1 matches ASPACE2. On targets that have global
breakpoints, the address space doesn't really matter. */
-extern int breakpoint_address_match (struct address_space *aspace1,
+extern int breakpoint_address_match (const address_space *aspace1,
CORE_ADDR addr1,
- struct address_space *aspace2,
+ const address_space *aspace2,
CORE_ADDR addr2);
-extern void until_break_command (char *, int, int);
+extern void until_break_command (const char *, int, int);
/* Initialize a struct bp_location. */
-extern void update_breakpoint_locations (struct breakpoint *b,
- struct program_space *filter_pspace,
- struct symtabs_and_lines sals,
- struct symtabs_and_lines sals_end);
+extern void update_breakpoint_locations
+ (struct breakpoint *b,
+ struct program_space *filter_pspace,
+ gdb::array_view<const symtab_and_line> sals,
+ gdb::array_view<const symtab_and_line> sals_end);
extern void breakpoint_re_set (void);
extern void breakpoint_re_set_thread (struct breakpoint *);
-extern struct breakpoint *set_momentary_breakpoint
+extern void delete_breakpoint (struct breakpoint *);
+
+struct breakpoint_deleter
+{
+ void operator() (struct breakpoint *b) const
+ {
+ delete_breakpoint (b);
+ }
+};
+
+typedef std::unique_ptr<struct breakpoint, breakpoint_deleter> breakpoint_up;
+
+extern breakpoint_up set_momentary_breakpoint
(struct gdbarch *, struct symtab_and_line, struct frame_id, enum bptype);
-extern struct breakpoint *set_momentary_breakpoint_at_pc
+extern breakpoint_up set_momentary_breakpoint_at_pc
(struct gdbarch *, CORE_ADDR pc, enum bptype type);
extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt);
extern void breakpoint_init_inferior (enum inf_context);
-extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *);
-
-extern void delete_breakpoint (struct breakpoint *);
-
extern void breakpoint_auto_delete (bpstat);
typedef void (*walk_bp_location_callback) (struct bp_location *, void *);
NOT be deallocated after use. */
const char *bpdisp_text (enum bpdisp disp);
-extern void break_command (char *, int);
+extern void break_command (const char *, int);
-extern void hbreak_command_wrapper (char *, int);
-extern void thbreak_command_wrapper (char *, int);
-extern void rbreak_command_wrapper (char *, int);
-extern void watch_command_wrapper (char *, int, int);
-extern void awatch_command_wrapper (char *, int, int);
-extern void rwatch_command_wrapper (char *, int, int);
-extern void tbreak_command (char *, int);
+extern void watch_command_wrapper (const char *, int, int);
+extern void awatch_command_wrapper (const char *, int, int);
+extern void rwatch_command_wrapper (const char *, int, int);
+extern void tbreak_command (const char *, int);
extern struct breakpoint_ops base_breakpoint_ops;
extern struct breakpoint_ops bkpt_breakpoint_ops;
extern void
add_catch_command (const char *name, const char *docstring,
- cmd_sfunc_ftype *sfunc,
+ cmd_const_sfunc_ftype *sfunc,
completer_ftype *completer,
void *user_data_catch,
void *user_data_tcatch);
init_ada_exception_breakpoint (struct breakpoint *b,
struct gdbarch *gdbarch,
struct symtab_and_line sal,
- char *addr_string,
+ const char *addr_string,
const struct breakpoint_ops *ops,
int tempflag,
int enabled,
the internal breakpoint count. If UPDATE_GLL is non-zero,
update_global_location_list will be called. */
-extern void install_breakpoint (int internal, struct breakpoint *b,
+extern void install_breakpoint (int internal, std::unique_ptr<breakpoint> &&b,
int update_gll);
+/* Returns the breakpoint ops appropriate for use with with LOCATION and
+ according to IS_TRACEPOINT. Use this to ensure, for example, that you pass
+ the correct ops to create_breakpoint for probe locations. If LOCATION is
+ NULL, returns bkpt_breakpoint_ops (or tracepoint_breakpoint_ops, if
+ IS_TRACEPOINT is true). */
+
+extern const struct breakpoint_ops *breakpoint_ops_for_event_location
+ (const struct event_location *location, bool is_tracepoint);
+
/* Flags that can be passed down to create_breakpoint, etc., to affect
breakpoint creation in several ways. */
extern int create_breakpoint (struct gdbarch *gdbarch,
const struct event_location *location,
- char *cond_string, int thread,
- char *extra_string,
+ const char *cond_string, int thread,
+ const char *extra_string,
int parse_extra,
int tempflag, enum bptype wanted_type,
int ignore_count,
extern int remove_breakpoints (void);
-extern int remove_breakpoints_pid (int pid);
+/* Remove breakpoints of inferior INF. */
-/* This function can be used to physically insert eventpoints from the
- specified traced inferior process, without modifying the breakpoint
- package's state. This can be useful for those targets which
- support following the processes of a fork() or vfork() system call,
- when both of the resulting two processes are to be followed. */
-extern int reattach_breakpoints (int);
+extern void remove_breakpoints_inf (inferior *inf);
/* This function can be used to update the breakpoint package's state
after an exec() system call has been executed.
extern void enable_breakpoint (struct breakpoint *);
extern void breakpoint_set_commands (struct breakpoint *b,
- command_line_up &&commands);
+ counted_command_line &&commands);
extern void breakpoint_set_silent (struct breakpoint *b, int silent);
extern void disable_breakpoints_in_shlibs (void);
-/* This function returns TRUE if ep is a catchpoint. */
-extern int is_catchpoint (struct breakpoint *);
+/* This function returns true if B is a catchpoint. */
+
+extern bool is_catchpoint (struct breakpoint *b);
/* Shared helper function (MI and CLI) for creating and installing
a shared object event catchpoint. */
extern void add_solib_catchpoint (const char *arg, int is_load, int is_temp,
int enabled);
-/* Enable breakpoints and delete when hit. Called with ARG == NULL
- deletes all breakpoints. */
-extern void delete_command (char *arg, int from_tty);
-
/* Create and insert a new software single step breakpoint for the
current thread. May be called multiple times; each time will add a
new location to the set of potential addresses the next instruction
is at. */
extern void insert_single_step_breakpoint (struct gdbarch *,
- struct address_space *,
+ const address_space *,
CORE_ADDR);
/* Insert all software single step breakpoints for the current frame.
/* Find a tracepoint by parsing a number in the supplied string. */
extern struct tracepoint *
- get_tracepoint_by_number (char **arg,
+ get_tracepoint_by_number (const char **arg,
number_or_range_parser *parser);
-/* Return a vector of all tracepoints currently defined. The vector
- is newly allocated; the caller should free when done with it. */
-extern VEC(breakpoint_p) *all_tracepoints (void);
+/* Return a vector of all tracepoints currently defined. */
+extern std::vector<breakpoint *> all_tracepoints (void);
+
+/* Return true if B is of tracepoint kind. */
-extern int is_tracepoint (const struct breakpoint *b);
+extern bool is_tracepoint (const struct breakpoint *b);
-/* Return a vector of all static tracepoints defined at ADDR. The
- vector is newly allocated; the caller should free when done with
- it. */
-extern VEC(breakpoint_p) *static_tracepoints_here (CORE_ADDR addr);
+/* Return a vector of all static tracepoints defined at ADDR. */
+extern std::vector<breakpoint *> static_tracepoints_here (CORE_ADDR addr);
-/* Function that can be passed to read_command_line to validate
- that each command is suitable for tracepoint command list. */
-extern void check_tracepoint_command (char *line, void *closure);
+/* Create an instance of this to start registering breakpoint numbers
+ for a later "commands" command. */
-/* Call at the start and end of an "rbreak" command to register
- breakpoint numbers for a later "commands" command. */
-extern void start_rbreak_breakpoints (void);
-extern void end_rbreak_breakpoints (void);
+class scoped_rbreak_breakpoints
+{
+public:
+
+ scoped_rbreak_breakpoints ();
+ ~scoped_rbreak_breakpoints ();
+
+ DISABLE_COPY_AND_ASSIGN (scoped_rbreak_breakpoints);
+};
/* Breakpoint iterator function.
returned. This can be useful for implementing a search for a
breakpoint with arbitrary attributes, or for applying an operation
to every breakpoint. */
-extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
- void *), void *);
+extern struct breakpoint *iterate_over_breakpoints
+ (gdb::function_view<bool (breakpoint *)>);
/* Nonzero if the specified PC cannot be a location where functions
have been inlined. */
-extern int pc_at_non_inline_function (struct address_space *aspace,
+extern int pc_at_non_inline_function (const address_space *aspace,
CORE_ADDR pc,
const struct target_waitstatus *ws);
UIOUT iff debugging multiple threads. */
extern void maybe_print_thread_hit_breakpoint (struct ui_out *uiout);
+/* Print the specified breakpoint. */
+extern void print_breakpoint (breakpoint *bp);
+
+/* Command element for the 'commands' command. */
+extern cmd_list_element *commands_cmd_element;
+
+/* Whether to use the fixed output when printing information about a
+ multi-location breakpoint (see PR 9659). */
+
+extern bool fix_multi_location_breakpoint_output_globally;
+
+/* Deal with "catch catch", "catch throw", and "catch rethrow" commands and
+ the MI equivalents. Sets up to catch events of type EX_EVENT. When
+ TEMPFLAG is true only the next matching event is caught after which the
+ catch-point is deleted. If REGEX is not NULL then only exceptions whose
+ type name matches REGEX will trigger the event. */
+
+extern void catch_exception_event (enum exception_event_kind ex_event,
+ const char *regex, bool tempflag,
+ int from_tty);
+
#endif /* !defined (BREAKPOINT_H) */