mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
8d7493201c
This patch is part of the make-gdb-buildable-in-C++ effort. The idea is to change some calls to the xmalloc family of functions to calls to the equivalents in the XNEW family. This avoids adding an explicit cast, so it keeps the code a bit more readable. Some of them also map relatively well to a C++ equivalent (XNEW (struct foo) -> new foo), so it will be possible to do scripted replacements if needed. I only changed calls that were obviously allocating memory for one or multiple "objects". Allocation of variable sizes (such as strings or buffer handling) will be for later (and won't use XNEW). - xmalloc (sizeof (struct foo)) -> XNEW (struct foo) - xmalloc (num * sizeof (struct foo)) -> XNEWVEC (struct foo, num) - xcalloc (1, sizeof (struct foo)) -> XCNEW (struct foo) - xcalloc (num, sizeof (struct foo)) -> XCNEWVEC (struct foo, num) - xrealloc (p, num * sizeof (struct foo) -> XRESIZEVEC (struct foo, p, num) - obstack_alloc (ob, sizeof (struct foo)) -> XOBNEW (ob, struct foo) - obstack_alloc (ob, num * sizeof (struct foo)) -> XOBNEWVEC (ob, struct foo, num) - alloca (sizeof (struct foo)) -> XALLOCA (struct foo) - alloca (num * sizeof (struct foo)) -> XALLOCAVEC (struct foo, num) Some instances of xmalloc followed by memset to zero the buffer were replaced by XCNEW or XCNEWVEC. I regtested on x86-64, Ubuntu 14.04, but the patch touches many architecture-specific files. For those I'll have to rely on the buildbot or people complaining that I broke their gdb. gdb/ChangeLog: * aarch64-linux-nat.c (aarch64_add_process): Likewise. * aarch64-tdep.c (aarch64_gdbarch_init): Likewise. * ada-exp.y (write_ambiguous_var): Likewise. * ada-lang.c (resolve_subexp): Likewise. (user_select_syms): Likewise. (assign_aggregate): Likewise. (ada_evaluate_subexp): Likewise. (cache_symbol): Likewise. * addrmap.c (allocate_key): Likewise. (addrmap_create_mutable): Likewise. * aix-thread.c (sync_threadlists): Likewise. * alpha-tdep.c (alpha_push_dummy_call): Likewise. (alpha_gdbarch_init): Likewise. * amd64-windows-tdep.c (amd64_windows_push_arguments): Likewise. * arm-linux-nat.c (arm_linux_add_process): Likewise. * arm-linux-tdep.c (arm_linux_displaced_step_copy_insn): Likewise. * arm-tdep.c (push_stack_item): Likewise. (arm_displaced_step_copy_insn): Likewise. (arm_gdbarch_init): Likewise. (_initialize_arm_tdep): Likewise. * avr-tdep.c (push_stack_item): Likewise. * ax-general.c (new_agent_expr): Likewise. * block.c (block_initialize_namespace): Likewise. * breakpoint.c (alloc_counted_command_line): Likewise. (update_dprintf_command_list): Likewise. (parse_breakpoint_sals): Likewise. (decode_static_tracepoint_spec): Likewise. (until_break_command): Likewise. (clear_command): Likewise. (update_global_location_list): Likewise. (get_breakpoint_objfile_data) Likewise. * btrace.c (ftrace_new_function): Likewise. (btrace_set_insn_history): Likewise. (btrace_set_call_history): Likewise. * buildsym.c (add_symbol_to_list): Likewise. (record_pending_block): Likewise. (start_subfile): Likewise. (start_buildsym_compunit): Likewise. (push_subfile): Likewise. (end_symtab_get_static_block): Likewise. (buildsym_init): Likewise. * cli/cli-cmds.c (source_command): Likewise. * cli/cli-decode.c (add_cmd): Likewise. * cli/cli-script.c (build_command_line): Likewise. (setup_user_args): Likewise. (realloc_body_list): Likewise. (process_next_line): Likewise. (copy_command_lines): Likewise. * cli/cli-setshow.c (do_set_command): Likewise. * coff-pe-read.c (read_pe_exported_syms): Likewise. * coffread.c (coff_locate_sections): Likewise. (coff_symtab_read): Likewise. (coff_read_struct_type): Likewise. * common/cleanups.c (make_my_cleanup2): Likewise. * common/common-exceptions.c (throw_it): Likewise. * common/filestuff.c (make_cleanup_close): Likewise. * common/format.c (parse_format_string): Likewise. * common/queue.h (DEFINE_QUEUE_P): Likewise. * compile/compile-object-load.c (munmap_list_add): Likewise. (compile_object_load): Likewise. * compile/compile-object-run.c (compile_object_run): Likewise. * compile/compile.c (append_args): Likewise. * corefile.c (specify_exec_file_hook): Likewise. * cp-support.c (make_symbol_overload_list): Likewise. * cris-tdep.c (push_stack_item): Likewise. (cris_gdbarch_init): Likewise. * ctf.c (ctf_trace_file_writer_new): Likewise. * dbxread.c (init_header_files): Likewise. (add_new_header_file): Likewise. (init_bincl_list): Likewise. (dbx_end_psymtab): Likewise. (start_psymtab): Likewise. (dbx_end_psymtab): Likewise. * dcache.c (dcache_init): Likewise. * dictionary.c (dict_create_hashed): Likewise. (dict_create_hashed_expandable): Likewise. (dict_create_linear): Likewise. (dict_create_linear_expandable): Likewise. * dtrace-probe.c (dtrace_process_dof_probe): Likewise. * dummy-frame.c (register_dummy_frame_dtor): Likewise. * dwarf2-frame-tailcall.c (cache_new_ref1): Likewise. * dwarf2-frame.c (dwarf2_build_frame_info): Likewise. (decode_frame_entry_1): Likewise. * dwarf2expr.c (new_dwarf_expr_context): Likewise. * dwarf2loc.c (dwarf2_compile_expr_to_ax): Likewise. * dwarf2read.c (dwarf2_has_info): Likewise. (create_signatured_type_table_from_index): Likewise. (dwarf2_read_index): Likewise. (dw2_get_file_names_reader): Likewise. (create_all_type_units): Likewise. (read_cutu_die_from_dwo): Likewise. (init_tu_and_read_dwo_dies): Likewise. (init_cutu_and_read_dies): Likewise. (create_all_comp_units): Likewise. (queue_comp_unit): Likewise. (inherit_abstract_dies): Likewise. (read_call_site_scope): Likewise. (dwarf2_add_field): Likewise. (dwarf2_add_typedef): Likewise. (dwarf2_add_member_fn): Likewise. (attr_to_dynamic_prop): Likewise. (abbrev_table_alloc_abbrev): Likewise. (abbrev_table_read_table): Likewise. (add_include_dir): Likewise. (add_file_name): Likewise. (dwarf_decode_line_header): Likewise. (dwarf2_const_value_attr): Likewise. (dwarf_alloc_block): Likewise. (parse_macro_definition): Likewise. (set_die_type): Likewise. (write_psymtabs_to_index): Likewise. (create_cus_from_index): Likewise. (dwarf2_create_include_psymtab): Likewise. (process_psymtab_comp_unit_reader): Likewise. (build_type_psymtab_dependencies): Likewise. (read_comp_units_from_section): Likewise. (compute_compunit_symtab_includes): Likewise. (create_dwo_unit_in_dwp_v1): Likewise. (create_dwo_unit_in_dwp_v2): Likewise. (read_func_scope): Likewise. (process_structure_scope): Likewise. (mark_common_block_symbol_computed): Likewise. (load_partial_dies): Likewise. (dwarf2_symbol_mark_computed): Likewise. * elfread.c (elf_symfile_segments): Likewise. (elf_read_minimal_symbols): Likewise. * environ.c (make_environ): Likewise. * eval.c (evaluate_subexp_standard): Likewise. * event-loop.c (create_file_handler): Likewise. (create_async_signal_handler): Likewise. (create_async_event_handler): Likewise. (create_timer): Likewise. * exec.c (build_section_table): Likewise. * fbsd-nat.c (fbsd_remember_child): Likewise. * fork-child.c (fork_inferior): Likewise. * frv-tdep.c (new_variant): Likewise. * gdbarch.sh (gdbarch_alloc): Likewise. (append_name): Likewise. * gdbtypes.c (rank_function): Likewise. (copy_type_recursive): Likewise. (add_dyn_prop): Likewise. * gnu-nat.c (make_proc): Likewise. (make_inf): Likewise. (gnu_write_inferior): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise. (build_std_type_info_type): Likewise. * guile/scm-param.c (compute_enum_list): Likewise. * guile/scm-utils.c (gdbscm_parse_function_args): Likewise. * guile/scm-value.c (gdbscm_value_call): Likewise. * h8300-tdep.c (h8300_gdbarch_init): Likewise. * hppa-tdep.c (hppa_init_objfile_priv_data): Likewise. (read_unwind_info): Likewise. * ia64-tdep.c (ia64_gdbarch_init): Likewise. * infcall.c (dummy_frame_context_saver_setup): Likewise. (call_function_by_hand_dummy): Likewise. * infcmd.c (step_once): Likewise. (finish_forward): Likewise. (attach_command): Likewise. (notice_new_inferior): Likewise. * inferior.c (add_inferior_silent): Likewise. * infrun.c (add_displaced_stepping_state): Likewise. (save_infcall_control_state): Likewise. (save_inferior_ptid): Likewise. (_initialize_infrun): Likewise. * jit.c (bfd_open_from_target_memory): Likewise. (jit_gdbarch_data_init): Likewise. * language.c (add_language): Likewise. * linespec.c (decode_line_2): Likewise. * linux-nat.c (add_to_pid_list): Likewise. (add_initial_lwp): Likewise. * linux-thread-db.c (add_thread_db_info): Likewise. (record_thread): Likewise. (info_auto_load_libthread_db): Likewise. * m32c-tdep.c (m32c_gdbarch_init): Likewise. * m68hc11-tdep.c (m68hc11_gdbarch_init): Likewise. * m68k-tdep.c (m68k_gdbarch_init): Likewise. * m88k-tdep.c (m88k_analyze_prologue): Likewise. * macrocmd.c (macro_define_command): Likewise. * macroexp.c (gather_arguments): Likewise. * macroscope.c (sal_macro_scope): Likewise. * macrotab.c (new_macro_table): Likewise. * mdebugread.c (push_parse_stack): Likewise. (parse_partial_symbols): Likewise. (parse_symbol): Likewise. (psymtab_to_symtab_1): Likewise. (new_block): Likewise. (new_psymtab): Likewise. (mdebug_build_psymtabs): Likewise. (add_pending): Likewise. (elfmdebug_build_psymtabs): Likewise. * mep-tdep.c (mep_gdbarch_init): Likewise. * mi/mi-main.c (mi_execute_command): Likewise. * mi/mi-parse.c (mi_parse_argv): Likewise. * minidebug.c (lzma_open): Likewise. * minsyms.c (terminate_minimal_symbol_table): Likewise. * mips-linux-nat.c (mips_linux_insert_watchpoint): Likewise. * mips-tdep.c (mips_gdbarch_init): Likewise. * mn10300-tdep.c (mn10300_gdbarch_init): Likewise. * msp430-tdep.c (msp430_gdbarch_init): Likewise. * mt-tdep.c (mt_registers_info): Likewise. * nat/aarch64-linux.c (aarch64_linux_new_thread): Likewise. * nat/linux-btrace.c (linux_enable_bts): Likewise. (linux_enable_pt): Likewise. * nat/linux-osdata.c (linux_xfer_osdata_processes): Likewise. (linux_xfer_osdata_processgroups): Likewise. * nios2-tdep.c (nios2_gdbarch_init): Likewise. * nto-procfs.c (procfs_meminfo): Likewise. * objc-lang.c (start_msglist): Likewise. (selectors_info): Likewise. (classes_info): Likewise. (find_methods): Likewise. * objfiles.c (allocate_objfile): Likewise. (update_section_map): Likewise. * osabi.c (gdbarch_register_osabi): Likewise. (gdbarch_register_osabi_sniffer): Likewise. * parse.c (start_arglist): Likewise. * ppc-linux-nat.c (hwdebug_find_thread_points_by_tid): Likewise. (hwdebug_insert_point): Likewise. * printcmd.c (display_command): Likewise. (ui_printf): Likewise. * procfs.c (create_procinfo): Likewise. (load_syscalls): Likewise. (proc_get_LDT_entry): Likewise. (proc_update_threads): Likewise. * prologue-value.c (make_pv_area): Likewise. (pv_area_store): Likewise. * psymtab.c (extend_psymbol_list): Likewise. (init_psymbol_list): Likewise. (allocate_psymtab): Likewise. * python/py-inferior.c (add_thread_object): Likewise. * python/py-param.c (compute_enum_values): Likewise. * python/py-value.c (valpy_call): Likewise. * python/py-varobj.c (py_varobj_iter_next): Likewise. * python/python.c (ensure_python_env): Likewise. * record-btrace.c (record_btrace_start_replaying): Likewise. * record-full.c (record_full_reg_alloc): Likewise. (record_full_mem_alloc): Likewise. (record_full_end_alloc): Likewise. (record_full_core_xfer_partial): Likewise. * regcache.c (get_thread_arch_aspace_regcache): Likewise. * remote-fileio.c (remote_fileio_init_fd_map): Likewise. * remote-notif.c (remote_notif_state_allocate): Likewise. * remote.c (demand_private_info): Likewise. (remote_notif_stop_alloc_reply): Likewise. (remote_enable_btrace): Likewise. * reverse.c (save_bookmark_command): Likewise. * rl78-tdep.c (rl78_gdbarch_init): Likewise. * rx-tdep.c (rx_gdbarch_init): Likewise. * s390-linux-nat.c (s390_insert_watchpoint): Likewise. * ser-go32.c (dos_get_tty_state): Likewise. (dos_copy_tty_state): Likewise. * ser-mingw.c (ser_windows_open): Likewise. (ser_console_wait_handle): Likewise. (ser_console_get_tty_state): Likewise. (make_pipe_state): Likewise. (net_windows_open): Likewise. * ser-unix.c (hardwire_get_tty_state): Likewise. (hardwire_copy_tty_state): Likewise. * solib-aix.c (solib_aix_new_lm_info): Likewise. * solib-dsbt.c (dsbt_current_sos): Likewise. (dsbt_relocate_main_executable): Likewise. * solib-frv.c (frv_current_sos): Likewise. (frv_relocate_main_executable): Likewise. * solib-spu.c (spu_bfd_fopen): Likewise. * solib-svr4.c (lm_info_read): Likewise. (svr4_copy_library_list): Likewise. (svr4_default_sos): Likewise. * source.c (find_source_lines): Likewise. (line_info): Likewise. (add_substitute_path_rule): Likewise. * spu-linux-nat.c (spu_bfd_open): Likewise. * spu-tdep.c (info_spu_dma_cmdlist): Likewise. * stabsread.c (dbx_lookup_type): Likewise. (read_type): Likewise. (read_member_functions): Likewise. (read_struct_fields): Likewise. (read_baseclasses): Likewise. (read_args): Likewise. (_initialize_stabsread): Likewise. * stack.c (func_command): Likewise. * stap-probe.c (handle_stap_probe): Likewise. * symfile.c (addrs_section_sort): Likewise. (addr_info_make_relative): Likewise. (load_section_callback): Likewise. (add_symbol_file_command): Likewise. (init_filename_language_table): Likewise. * symtab.c (create_filename_seen_cache): Likewise. (sort_search_symbols_remove_dups): Likewise. (search_symbols): Likewise. * target.c (make_cleanup_restore_target_terminal): Likewise. * thread.c (new_thread): Likewise. (enable_thread_stack_temporaries): Likewise. (make_cleanup_restore_current_thread): Likewise. (thread_apply_all_command): Likewise. * tic6x-tdep.c (tic6x_gdbarch_init): Likewise. * top.c (gdb_readline_wrapper): Likewise. * tracefile-tfile.c (tfile_trace_file_writer_new): Likewise. * tracepoint.c (trace_find_line_command): Likewise. (all_tracepoint_actions_and_cleanup): Likewise. (make_cleanup_restore_current_traceframe): Likewise. (get_uploaded_tp): Likewise. (get_uploaded_tsv): Likewise. * tui/tui-data.c (tui_alloc_generic_win_info): Likewise. (tui_alloc_win_info): Likewise. (tui_alloc_content): Likewise. (tui_add_content_elements): Likewise. * tui/tui-disasm.c (tui_find_disassembly_address): Likewise. (tui_set_disassem_content): Likewise. * ui-file.c (ui_file_new): Likewise. (stdio_file_new): Likewise. (tee_file_new): Likewise. * utils.c (make_cleanup_restore_integer): Likewise. (add_internal_problem_command): Likewise. * v850-tdep.c (v850_gdbarch_init): Likewise. * valops.c (find_oload_champ): Likewise. * value.c (allocate_value_lazy): Likewise. (record_latest_value): Likewise. (create_internalvar): Likewise. * varobj.c (install_variable): Likewise. (new_variable): Likewise. (new_root_variable): Likewise. (cppush): Likewise. (_initialize_varobj): Likewise. * windows-nat.c (windows_make_so): Likewise. * x86-nat.c (x86_add_process): Likewise. * xcoffread.c (arrange_linetable): Likewise. (allocate_include_entry): Likewise. (process_linenos): Likewise. (SYMBOL_DUP): Likewise. (xcoff_start_psymtab): Likewise. (xcoff_end_psymtab): Likewise. * xml-support.c (gdb_xml_parse_attr_ulongest): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * gdbarch.c: Regenerate. * gdbarch.h: Regenerate. gdb/gdbserver/ChangeLog: * ax.c (gdb_parse_agent_expr): Likewise. (compile_bytecodes): Likewise. * dll.c (loaded_dll): Likewise. * event-loop.c (append_callback_event): Likewise. (create_file_handler): Likewise. (create_file_event): Likewise. * hostio.c (handle_open): Likewise. * inferiors.c (add_thread): Likewise. (add_process): Likewise. * linux-aarch64-low.c (aarch64_linux_new_process): Likewise. * linux-arm-low.c (arm_new_process): Likewise. (arm_new_thread): Likewise. * linux-low.c (add_to_pid_list): Likewise. (linux_add_process): Likewise. (handle_extended_wait): Likewise. (add_lwp): Likewise. (enqueue_one_deferred_signal): Likewise. (enqueue_pending_signal): Likewise. (linux_resume_one_lwp_throw): Likewise. (linux_resume_one_thread): Likewise. (linux_read_memory): Likewise. (linux_write_memory): Likewise. * linux-mips-low.c (mips_linux_new_process): Likewise. (mips_linux_new_thread): Likewise. (mips_add_watchpoint): Likewise. * linux-x86-low.c (initialize_low_arch): Likewise. * lynx-low.c (lynx_add_process): Likewise. * mem-break.c (set_raw_breakpoint_at): Likewise. (set_breakpoint): Likewise. (add_condition_to_breakpoint): Likewise. (add_commands_to_breakpoint): Likewise. (clone_agent_expr): Likewise. (clone_one_breakpoint): Likewise. * regcache.c (new_register_cache): Likewise. * remote-utils.c (look_up_one_symbol): Likewise. * server.c (queue_stop_reply): Likewise. (start_inferior): Likewise. (queue_stop_reply_callback): Likewise. (handle_target_event): Likewise. * spu-low.c (fetch_ppc_memory): Likewise. (store_ppc_memory): Likewise. * target.c (set_target_ops): Likewise. * thread-db.c (thread_db_load_search): Likewise. (try_thread_db_load_1): Likewise. * tracepoint.c (add_tracepoint): Likewise. (add_tracepoint_action): Likewise. (create_trace_state_variable): Likewise. (cmd_qtdpsrc): Likewise. (cmd_qtro): Likewise. (add_while_stepping_state): Likewise. * win32-low.c (child_add_thread): Likewise. (get_image_name): Likewise.
1597 lines
41 KiB
C
1597 lines
41 KiB
C
/* Scheme interface to values.
|
||
|
||
Copyright (C) 2008-2015 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
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/>. */
|
||
|
||
/* See README file in this directory for implementation notes, coding
|
||
conventions, et.al. */
|
||
|
||
#include "defs.h"
|
||
#include "arch-utils.h"
|
||
#include "charset.h"
|
||
#include "cp-abi.h"
|
||
#include "infcall.h"
|
||
#include "symtab.h" /* Needed by language.h. */
|
||
#include "language.h"
|
||
#include "valprint.h"
|
||
#include "value.h"
|
||
#include "guile-internal.h"
|
||
|
||
/* The <gdb:value> smob. */
|
||
|
||
typedef struct _value_smob
|
||
{
|
||
/* This always appears first. */
|
||
gdb_smob base;
|
||
|
||
/* Doubly linked list of values in values_in_scheme.
|
||
IWBN to use a chained_gdb_smob instead, which is doable, it just requires
|
||
a bit more casting than normal. */
|
||
struct _value_smob *next;
|
||
struct _value_smob *prev;
|
||
|
||
struct value *value;
|
||
|
||
/* These are cached here to avoid making multiple copies of them.
|
||
Plus computing the dynamic_type can be a bit expensive.
|
||
We use #f to indicate that the value doesn't exist (e.g. value doesn't
|
||
have an address), so we need another value to indicate that we haven't
|
||
computed the value yet. For this we use SCM_UNDEFINED. */
|
||
SCM address;
|
||
SCM type;
|
||
SCM dynamic_type;
|
||
} value_smob;
|
||
|
||
static const char value_smob_name[] = "gdb:value";
|
||
|
||
/* The tag Guile knows the value smob by. */
|
||
static scm_t_bits value_smob_tag;
|
||
|
||
/* List of all values which are currently exposed to Scheme. It is
|
||
maintained so that when an objfile is discarded, preserve_values
|
||
can copy the values' types if needed. */
|
||
static value_smob *values_in_scheme;
|
||
|
||
/* Keywords used by Scheme procedures in this file. */
|
||
static SCM type_keyword;
|
||
static SCM encoding_keyword;
|
||
static SCM errors_keyword;
|
||
static SCM length_keyword;
|
||
|
||
/* Possible #:errors values. */
|
||
static SCM error_symbol;
|
||
static SCM escape_symbol;
|
||
static SCM substitute_symbol;
|
||
|
||
/* Administrivia for value smobs. */
|
||
|
||
/* Iterate over all the <gdb:value> objects, calling preserve_one_value on
|
||
each.
|
||
This is the extension_language_ops.preserve_values "method". */
|
||
|
||
void
|
||
gdbscm_preserve_values (const struct extension_language_defn *extlang,
|
||
struct objfile *objfile, htab_t copied_types)
|
||
{
|
||
value_smob *iter;
|
||
|
||
for (iter = values_in_scheme; iter; iter = iter->next)
|
||
preserve_one_value (iter->value, objfile, copied_types);
|
||
}
|
||
|
||
/* Helper to add a value_smob to the global list. */
|
||
|
||
static void
|
||
vlscm_remember_scheme_value (value_smob *v_smob)
|
||
{
|
||
v_smob->next = values_in_scheme;
|
||
if (v_smob->next)
|
||
v_smob->next->prev = v_smob;
|
||
v_smob->prev = NULL;
|
||
values_in_scheme = v_smob;
|
||
}
|
||
|
||
/* Helper to remove a value_smob from the global list. */
|
||
|
||
static void
|
||
vlscm_forget_value_smob (value_smob *v_smob)
|
||
{
|
||
/* Remove SELF from the global list. */
|
||
if (v_smob->prev)
|
||
v_smob->prev->next = v_smob->next;
|
||
else
|
||
{
|
||
gdb_assert (values_in_scheme == v_smob);
|
||
values_in_scheme = v_smob->next;
|
||
}
|
||
if (v_smob->next)
|
||
v_smob->next->prev = v_smob->prev;
|
||
}
|
||
|
||
/* The smob "free" function for <gdb:value>. */
|
||
|
||
static size_t
|
||
vlscm_free_value_smob (SCM self)
|
||
{
|
||
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (self);
|
||
|
||
vlscm_forget_value_smob (v_smob);
|
||
value_free (v_smob->value);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* The smob "print" function for <gdb:value>. */
|
||
|
||
static int
|
||
vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
|
||
{
|
||
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (self);
|
||
char *s = NULL;
|
||
struct value_print_options opts;
|
||
|
||
if (pstate->writingp)
|
||
gdbscm_printf (port, "#<%s ", value_smob_name);
|
||
|
||
get_user_print_options (&opts);
|
||
opts.deref_ref = 0;
|
||
|
||
/* pstate->writingp = zero if invoked by display/~A, and nonzero if
|
||
invoked by write/~S. What to do here may need to evolve.
|
||
IWBN if we could pass an argument to format that would we could use
|
||
instead of writingp. */
|
||
opts.raw = !!pstate->writingp;
|
||
|
||
TRY
|
||
{
|
||
struct ui_file *stb = mem_fileopen ();
|
||
struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
|
||
|
||
common_val_print (v_smob->value, stb, 0, &opts, current_language);
|
||
s = ui_file_xstrdup (stb, NULL);
|
||
|
||
do_cleanups (old_chain);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
if (s != NULL)
|
||
{
|
||
scm_puts (s, port);
|
||
xfree (s);
|
||
}
|
||
|
||
if (pstate->writingp)
|
||
scm_puts (">", port);
|
||
|
||
scm_remember_upto_here_1 (self);
|
||
|
||
/* Non-zero means success. */
|
||
return 1;
|
||
}
|
||
|
||
/* The smob "equalp" function for <gdb:value>. */
|
||
|
||
static SCM
|
||
vlscm_equal_p_value_smob (SCM v1, SCM v2)
|
||
{
|
||
const value_smob *v1_smob = (value_smob *) SCM_SMOB_DATA (v1);
|
||
const value_smob *v2_smob = (value_smob *) SCM_SMOB_DATA (v2);
|
||
int result = 0;
|
||
|
||
TRY
|
||
{
|
||
result = value_equal (v1_smob->value, v2_smob->value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return scm_from_bool (result);
|
||
}
|
||
|
||
/* Low level routine to create a <gdb:value> object. */
|
||
|
||
static SCM
|
||
vlscm_make_value_smob (void)
|
||
{
|
||
value_smob *v_smob = (value_smob *)
|
||
scm_gc_malloc (sizeof (value_smob), value_smob_name);
|
||
SCM v_scm;
|
||
|
||
/* These must be filled in by the caller. */
|
||
v_smob->value = NULL;
|
||
v_smob->prev = NULL;
|
||
v_smob->next = NULL;
|
||
|
||
/* These are lazily computed. */
|
||
v_smob->address = SCM_UNDEFINED;
|
||
v_smob->type = SCM_UNDEFINED;
|
||
v_smob->dynamic_type = SCM_UNDEFINED;
|
||
|
||
v_scm = scm_new_smob (value_smob_tag, (scm_t_bits) v_smob);
|
||
gdbscm_init_gsmob (&v_smob->base);
|
||
|
||
return v_scm;
|
||
}
|
||
|
||
/* Return non-zero if SCM is a <gdb:value> object. */
|
||
|
||
int
|
||
vlscm_is_value (SCM scm)
|
||
{
|
||
return SCM_SMOB_PREDICATE (value_smob_tag, scm);
|
||
}
|
||
|
||
/* (value? object) -> boolean */
|
||
|
||
static SCM
|
||
gdbscm_value_p (SCM scm)
|
||
{
|
||
return scm_from_bool (vlscm_is_value (scm));
|
||
}
|
||
|
||
/* Create a new <gdb:value> object that encapsulates VALUE.
|
||
The value is released from the all_values chain so its lifetime is not
|
||
bound to the execution of a command. */
|
||
|
||
SCM
|
||
vlscm_scm_from_value (struct value *value)
|
||
{
|
||
/* N.B. It's important to not cause any side-effects until we know the
|
||
conversion worked. */
|
||
SCM v_scm = vlscm_make_value_smob ();
|
||
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (v_scm);
|
||
|
||
v_smob->value = value;
|
||
release_value_or_incref (value);
|
||
vlscm_remember_scheme_value (v_smob);
|
||
|
||
return v_scm;
|
||
}
|
||
|
||
/* Returns the <gdb:value> object in SELF.
|
||
Throws an exception if SELF is not a <gdb:value> object. */
|
||
|
||
static SCM
|
||
vlscm_get_value_arg_unsafe (SCM self, int arg_pos, const char *func_name)
|
||
{
|
||
SCM_ASSERT_TYPE (vlscm_is_value (self), self, arg_pos, func_name,
|
||
value_smob_name);
|
||
|
||
return self;
|
||
}
|
||
|
||
/* Returns a pointer to the value smob of SELF.
|
||
Throws an exception if SELF is not a <gdb:value> object. */
|
||
|
||
static value_smob *
|
||
vlscm_get_value_smob_arg_unsafe (SCM self, int arg_pos, const char *func_name)
|
||
{
|
||
SCM v_scm = vlscm_get_value_arg_unsafe (self, arg_pos, func_name);
|
||
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (v_scm);
|
||
|
||
return v_smob;
|
||
}
|
||
|
||
/* Return the value field of V_SCM, an object of type <gdb:value>.
|
||
This exists so that we don't have to export the struct's contents. */
|
||
|
||
struct value *
|
||
vlscm_scm_to_value (SCM v_scm)
|
||
{
|
||
value_smob *v_smob;
|
||
|
||
gdb_assert (vlscm_is_value (v_scm));
|
||
v_smob = (value_smob *) SCM_SMOB_DATA (v_scm);
|
||
return v_smob->value;
|
||
}
|
||
|
||
/* Value methods. */
|
||
|
||
/* (make-value x [#:type type]) -> <gdb:value> */
|
||
|
||
static SCM
|
||
gdbscm_make_value (SCM x, SCM rest)
|
||
{
|
||
struct gdbarch *gdbarch = get_current_arch ();
|
||
const struct language_defn *language = current_language;
|
||
const SCM keywords[] = { type_keyword, SCM_BOOL_F };
|
||
int type_arg_pos = -1;
|
||
SCM type_scm = SCM_UNDEFINED;
|
||
SCM except_scm, result;
|
||
type_smob *t_smob;
|
||
struct type *type = NULL;
|
||
struct value *value;
|
||
struct cleanup *cleanups;
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "#O", rest,
|
||
&type_arg_pos, &type_scm);
|
||
|
||
if (type_arg_pos > 0)
|
||
{
|
||
t_smob = tyscm_get_type_smob_arg_unsafe (type_scm, type_arg_pos,
|
||
FUNC_NAME);
|
||
type = tyscm_type_smob_type (t_smob);
|
||
}
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
value = vlscm_convert_typed_value_from_scheme (FUNC_NAME, SCM_ARG1, x,
|
||
type_arg_pos, type_scm, type,
|
||
&except_scm,
|
||
gdbarch, language);
|
||
if (value == NULL)
|
||
{
|
||
do_cleanups (cleanups);
|
||
gdbscm_throw (except_scm);
|
||
}
|
||
|
||
result = vlscm_scm_from_value (value);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
return result;
|
||
}
|
||
|
||
/* (make-lazy-value <gdb:type> address) -> <gdb:value> */
|
||
|
||
static SCM
|
||
gdbscm_make_lazy_value (SCM type_scm, SCM address_scm)
|
||
{
|
||
type_smob *t_smob;
|
||
struct type *type;
|
||
ULONGEST address;
|
||
struct value *value = NULL;
|
||
SCM result;
|
||
struct cleanup *cleanups;
|
||
|
||
t_smob = tyscm_get_type_smob_arg_unsafe (type_scm, SCM_ARG1, FUNC_NAME);
|
||
type = tyscm_type_smob_type (t_smob);
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, NULL, "U",
|
||
address_scm, &address);
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
/* There's no (current) need to wrap this in a TRY_CATCH, but for consistency
|
||
and future-proofing we do. */
|
||
TRY
|
||
{
|
||
value = value_from_contents_and_address (type, NULL, address);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
result = vlscm_scm_from_value (value);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
return result;
|
||
}
|
||
|
||
/* (value-optimized-out? <gdb:value>) -> boolean */
|
||
|
||
static SCM
|
||
gdbscm_value_optimized_out_p (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
int opt = 0;
|
||
|
||
TRY
|
||
{
|
||
opt = value_optimized_out (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return scm_from_bool (opt);
|
||
}
|
||
|
||
/* (value-address <gdb:value>) -> integer
|
||
Returns #f if the value doesn't have one. */
|
||
|
||
static SCM
|
||
gdbscm_value_address (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
|
||
if (SCM_UNBNDP (v_smob->address))
|
||
{
|
||
struct value *res_val = NULL;
|
||
struct cleanup *cleanup
|
||
= make_cleanup_value_free_to_mark (value_mark ());
|
||
SCM address;
|
||
|
||
TRY
|
||
{
|
||
res_val = value_addr (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
address = SCM_BOOL_F;
|
||
}
|
||
END_CATCH
|
||
|
||
if (res_val != NULL)
|
||
address = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanup);
|
||
|
||
if (gdbscm_is_exception (address))
|
||
gdbscm_throw (address);
|
||
|
||
v_smob->address = address;
|
||
}
|
||
|
||
return v_smob->address;
|
||
}
|
||
|
||
/* (value-dereference <gdb:value>) -> <gdb:value>
|
||
Given a value of a pointer type, apply the C unary * operator to it. */
|
||
|
||
static SCM
|
||
gdbscm_value_dereference (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
SCM result;
|
||
struct value *res_val = NULL;
|
||
struct cleanup *cleanups;
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
TRY
|
||
{
|
||
res_val = value_ind (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-referenced-value <gdb:value>) -> <gdb:value>
|
||
Given a value of a reference type, return the value referenced.
|
||
The difference between this function and gdbscm_value_dereference is that
|
||
the latter applies * unary operator to a value, which need not always
|
||
result in the value referenced.
|
||
For example, for a value which is a reference to an 'int' pointer ('int *'),
|
||
gdbscm_value_dereference will result in a value of type 'int' while
|
||
gdbscm_value_referenced_value will result in a value of type 'int *'. */
|
||
|
||
static SCM
|
||
gdbscm_value_referenced_value (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
SCM result;
|
||
struct value *res_val = NULL;
|
||
struct cleanup *cleanups;
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
TRY
|
||
{
|
||
switch (TYPE_CODE (check_typedef (value_type (value))))
|
||
{
|
||
case TYPE_CODE_PTR:
|
||
res_val = value_ind (value);
|
||
break;
|
||
case TYPE_CODE_REF:
|
||
res_val = coerce_ref (value);
|
||
break;
|
||
default:
|
||
error (_("Trying to get the referenced value from a value which is"
|
||
" neither a pointer nor a reference"));
|
||
}
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-type <gdb:value>) -> <gdb:type> */
|
||
|
||
static SCM
|
||
gdbscm_value_type (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
|
||
if (SCM_UNBNDP (v_smob->type))
|
||
v_smob->type = tyscm_scm_from_type (value_type (value));
|
||
|
||
return v_smob->type;
|
||
}
|
||
|
||
/* (value-dynamic-type <gdb:value>) -> <gdb:type> */
|
||
|
||
static SCM
|
||
gdbscm_value_dynamic_type (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct type *type = NULL;
|
||
|
||
if (! SCM_UNBNDP (v_smob->dynamic_type))
|
||
return v_smob->dynamic_type;
|
||
|
||
TRY
|
||
{
|
||
struct cleanup *cleanup
|
||
= make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
type = value_type (value);
|
||
type = check_typedef (type);
|
||
|
||
if (((TYPE_CODE (type) == TYPE_CODE_PTR)
|
||
|| (TYPE_CODE (type) == TYPE_CODE_REF))
|
||
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT))
|
||
{
|
||
struct value *target;
|
||
int was_pointer = TYPE_CODE (type) == TYPE_CODE_PTR;
|
||
|
||
if (was_pointer)
|
||
target = value_ind (value);
|
||
else
|
||
target = coerce_ref (value);
|
||
type = value_rtti_type (target, NULL, NULL, NULL);
|
||
|
||
if (type)
|
||
{
|
||
if (was_pointer)
|
||
type = lookup_pointer_type (type);
|
||
else
|
||
type = lookup_reference_type (type);
|
||
}
|
||
}
|
||
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
|
||
type = value_rtti_type (value, NULL, NULL, NULL);
|
||
else
|
||
{
|
||
/* Re-use object's static type. */
|
||
type = NULL;
|
||
}
|
||
|
||
do_cleanups (cleanup);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
if (type == NULL)
|
||
v_smob->dynamic_type = gdbscm_value_type (self);
|
||
else
|
||
v_smob->dynamic_type = tyscm_scm_from_type (type);
|
||
|
||
return v_smob->dynamic_type;
|
||
}
|
||
|
||
/* A helper function that implements the various cast operators. */
|
||
|
||
static SCM
|
||
vlscm_do_cast (SCM self, SCM type_scm, enum exp_opcode op,
|
||
const char *func_name)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
type_smob *t_smob
|
||
= tyscm_get_type_smob_arg_unsafe (type_scm, SCM_ARG2, FUNC_NAME);
|
||
struct type *type = tyscm_type_smob_type (t_smob);
|
||
SCM result;
|
||
struct value *res_val = NULL;
|
||
struct cleanup *cleanups;
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
TRY
|
||
{
|
||
if (op == UNOP_DYNAMIC_CAST)
|
||
res_val = value_dynamic_cast (type, value);
|
||
else if (op == UNOP_REINTERPRET_CAST)
|
||
res_val = value_reinterpret_cast (type, value);
|
||
else
|
||
{
|
||
gdb_assert (op == UNOP_CAST);
|
||
res_val = value_cast (type, value);
|
||
}
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
gdb_assert (res_val != NULL);
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-cast <gdb:value> <gdb:type>) -> <gdb:value> */
|
||
|
||
static SCM
|
||
gdbscm_value_cast (SCM self, SCM new_type)
|
||
{
|
||
return vlscm_do_cast (self, new_type, UNOP_CAST, FUNC_NAME);
|
||
}
|
||
|
||
/* (value-dynamic-cast <gdb:value> <gdb:type>) -> <gdb:value> */
|
||
|
||
static SCM
|
||
gdbscm_value_dynamic_cast (SCM self, SCM new_type)
|
||
{
|
||
return vlscm_do_cast (self, new_type, UNOP_DYNAMIC_CAST, FUNC_NAME);
|
||
}
|
||
|
||
/* (value-reinterpret-cast <gdb:value> <gdb:type>) -> <gdb:value> */
|
||
|
||
static SCM
|
||
gdbscm_value_reinterpret_cast (SCM self, SCM new_type)
|
||
{
|
||
return vlscm_do_cast (self, new_type, UNOP_REINTERPRET_CAST, FUNC_NAME);
|
||
}
|
||
|
||
/* (value-field <gdb:value> string) -> <gdb:value>
|
||
Given string name of an element inside structure, return its <gdb:value>
|
||
object. */
|
||
|
||
static SCM
|
||
gdbscm_value_field (SCM self, SCM field_scm)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
char *field = NULL;
|
||
struct value *res_val = NULL;
|
||
SCM result;
|
||
struct cleanup *cleanups;
|
||
|
||
SCM_ASSERT_TYPE (scm_is_string (field_scm), field_scm, SCM_ARG2, FUNC_NAME,
|
||
_("string"));
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
field = gdbscm_scm_to_c_string (field_scm);
|
||
make_cleanup (xfree, field);
|
||
|
||
TRY
|
||
{
|
||
struct value *tmp = value;
|
||
|
||
res_val = value_struct_elt (&tmp, NULL, field, NULL, NULL);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
gdb_assert (res_val != NULL);
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-subscript <gdb:value> integer|<gdb:value>) -> <gdb:value>
|
||
Return the specified value in an array. */
|
||
|
||
static SCM
|
||
gdbscm_value_subscript (SCM self, SCM index_scm)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct value *index = NULL;
|
||
struct value *res_val = NULL;
|
||
struct type *type = value_type (value);
|
||
struct gdbarch *gdbarch;
|
||
SCM result, except_scm;
|
||
struct cleanup *cleanups;
|
||
|
||
/* The sequencing here, as everywhere else, is important.
|
||
We can't have existing cleanups when a Scheme exception is thrown. */
|
||
|
||
SCM_ASSERT (type != NULL, self, SCM_ARG2, FUNC_NAME);
|
||
gdbarch = get_type_arch (type);
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
index = vlscm_convert_value_from_scheme (FUNC_NAME, SCM_ARG2, index_scm,
|
||
&except_scm,
|
||
gdbarch, current_language);
|
||
if (index == NULL)
|
||
{
|
||
do_cleanups (cleanups);
|
||
gdbscm_throw (except_scm);
|
||
}
|
||
|
||
TRY
|
||
{
|
||
struct value *tmp = value;
|
||
|
||
/* Assume we are attempting an array access, and let the value code
|
||
throw an exception if the index has an invalid type.
|
||
Check the value's type is something that can be accessed via
|
||
a subscript. */
|
||
tmp = coerce_ref (tmp);
|
||
type = check_typedef (value_type (tmp));
|
||
if (TYPE_CODE (type) != TYPE_CODE_ARRAY
|
||
&& TYPE_CODE (type) != TYPE_CODE_PTR)
|
||
error (_("Cannot subscript requested type"));
|
||
|
||
res_val = value_subscript (tmp, value_as_long (index));
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
gdb_assert (res_val != NULL);
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-call <gdb:value> arg-list) -> <gdb:value>
|
||
Perform an inferior function call on the value. */
|
||
|
||
static SCM
|
||
gdbscm_value_call (SCM self, SCM args)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *function = v_smob->value;
|
||
struct value *mark = value_mark ();
|
||
struct type *ftype = NULL;
|
||
long args_count;
|
||
struct value **vargs = NULL;
|
||
SCM result = SCM_BOOL_F;
|
||
|
||
TRY
|
||
{
|
||
ftype = check_typedef (value_type (function));
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
SCM_ASSERT_TYPE (TYPE_CODE (ftype) == TYPE_CODE_FUNC, self,
|
||
SCM_ARG1, FUNC_NAME,
|
||
_("function (value of TYPE_CODE_FUNC)"));
|
||
|
||
SCM_ASSERT_TYPE (gdbscm_is_true (scm_list_p (args)), args,
|
||
SCM_ARG2, FUNC_NAME, _("list"));
|
||
|
||
args_count = scm_ilength (args);
|
||
if (args_count > 0)
|
||
{
|
||
struct gdbarch *gdbarch = get_current_arch ();
|
||
const struct language_defn *language = current_language;
|
||
SCM except_scm;
|
||
long i;
|
||
|
||
vargs = XALLOCAVEC (struct value *, args_count);
|
||
for (i = 0; i < args_count; i++)
|
||
{
|
||
SCM arg = scm_car (args);
|
||
|
||
vargs[i] = vlscm_convert_value_from_scheme (FUNC_NAME,
|
||
GDBSCM_ARG_NONE, arg,
|
||
&except_scm,
|
||
gdbarch, language);
|
||
if (vargs[i] == NULL)
|
||
gdbscm_throw (except_scm);
|
||
|
||
args = scm_cdr (args);
|
||
}
|
||
gdb_assert (gdbscm_is_true (scm_null_p (args)));
|
||
}
|
||
|
||
TRY
|
||
{
|
||
struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark);
|
||
struct value *return_value;
|
||
|
||
return_value = call_function_by_hand (function, args_count, vargs);
|
||
result = vlscm_scm_from_value (return_value);
|
||
do_cleanups (cleanup);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value->bytevector <gdb:value>) -> bytevector */
|
||
|
||
static SCM
|
||
gdbscm_value_to_bytevector (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct type *type;
|
||
size_t length = 0;
|
||
const gdb_byte *contents = NULL;
|
||
SCM bv;
|
||
|
||
type = value_type (value);
|
||
|
||
TRY
|
||
{
|
||
type = check_typedef (type);
|
||
length = TYPE_LENGTH (type);
|
||
contents = value_contents (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
bv = scm_c_make_bytevector (length);
|
||
memcpy (SCM_BYTEVECTOR_CONTENTS (bv), contents, length);
|
||
|
||
return bv;
|
||
}
|
||
|
||
/* Helper function to determine if a type is "int-like". */
|
||
|
||
static int
|
||
is_intlike (struct type *type, int ptr_ok)
|
||
{
|
||
return (TYPE_CODE (type) == TYPE_CODE_INT
|
||
|| TYPE_CODE (type) == TYPE_CODE_ENUM
|
||
|| TYPE_CODE (type) == TYPE_CODE_BOOL
|
||
|| TYPE_CODE (type) == TYPE_CODE_CHAR
|
||
|| (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR));
|
||
}
|
||
|
||
/* (value->bool <gdb:value>) -> boolean
|
||
Throws an error if the value is not integer-like. */
|
||
|
||
static SCM
|
||
gdbscm_value_to_bool (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct type *type;
|
||
LONGEST l = 0;
|
||
|
||
type = value_type (value);
|
||
|
||
TRY
|
||
{
|
||
type = check_typedef (type);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
SCM_ASSERT_TYPE (is_intlike (type, 1), self, SCM_ARG1, FUNC_NAME,
|
||
_("integer-like gdb value"));
|
||
|
||
TRY
|
||
{
|
||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||
l = value_as_address (value);
|
||
else
|
||
l = value_as_long (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return scm_from_bool (l != 0);
|
||
}
|
||
|
||
/* (value->integer <gdb:value>) -> integer
|
||
Throws an error if the value is not integer-like. */
|
||
|
||
static SCM
|
||
gdbscm_value_to_integer (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct type *type;
|
||
LONGEST l = 0;
|
||
|
||
type = value_type (value);
|
||
|
||
TRY
|
||
{
|
||
type = check_typedef (type);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
SCM_ASSERT_TYPE (is_intlike (type, 1), self, SCM_ARG1, FUNC_NAME,
|
||
_("integer-like gdb value"));
|
||
|
||
TRY
|
||
{
|
||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||
l = value_as_address (value);
|
||
else
|
||
l = value_as_long (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
if (TYPE_UNSIGNED (type))
|
||
return gdbscm_scm_from_ulongest (l);
|
||
else
|
||
return gdbscm_scm_from_longest (l);
|
||
}
|
||
|
||
/* (value->real <gdb:value>) -> real
|
||
Throws an error if the value is not a number. */
|
||
|
||
static SCM
|
||
gdbscm_value_to_real (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct type *type;
|
||
DOUBLEST d = 0;
|
||
|
||
type = value_type (value);
|
||
|
||
TRY
|
||
{
|
||
type = check_typedef (type);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
SCM_ASSERT_TYPE (is_intlike (type, 0) || TYPE_CODE (type) == TYPE_CODE_FLT,
|
||
self, SCM_ARG1, FUNC_NAME, _("number"));
|
||
|
||
TRY
|
||
{
|
||
d = value_as_double (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
/* TODO: Is there a better way to check if the value fits? */
|
||
if (d != (double) d)
|
||
gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
|
||
_("number can't be converted to a double"));
|
||
|
||
return scm_from_double (d);
|
||
}
|
||
|
||
/* (value->string <gdb:value>
|
||
[#:encoding encoding]
|
||
[#:errors #f | 'error | 'substitute]
|
||
[#:length length])
|
||
-> string
|
||
Return Unicode string with value's contents, which must be a string.
|
||
|
||
If ENCODING is not given, the string is assumed to be encoded in
|
||
the target's charset.
|
||
|
||
ERRORS is one of #f, 'error or 'substitute.
|
||
An error setting of #f means use the default, which is Guile's
|
||
%default-port-conversion-strategy when using Guile >= 2.0.6, or 'error if
|
||
using an earlier version of Guile. Earlier versions do not properly
|
||
support obtaining the default port conversion strategy.
|
||
If the default is not one of 'error or 'substitute, 'substitute is used.
|
||
An error setting of "error" causes an exception to be thrown if there's
|
||
a decoding error. An error setting of "substitute" causes invalid
|
||
characters to be replaced with "?".
|
||
|
||
If LENGTH is provided, only fetch string to the length provided.
|
||
LENGTH must be a Scheme integer, it can't be a <gdb:value> integer. */
|
||
|
||
static SCM
|
||
gdbscm_value_to_string (SCM self, SCM rest)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
const SCM keywords[] = {
|
||
encoding_keyword, errors_keyword, length_keyword, SCM_BOOL_F
|
||
};
|
||
int encoding_arg_pos = -1, errors_arg_pos = -1, length_arg_pos = -1;
|
||
char *encoding = NULL;
|
||
SCM errors = SCM_BOOL_F;
|
||
int length = -1;
|
||
gdb_byte *buffer = NULL;
|
||
const char *la_encoding = NULL;
|
||
struct type *char_type = NULL;
|
||
SCM result;
|
||
struct cleanup *cleanups;
|
||
|
||
/* The sequencing here, as everywhere else, is important.
|
||
We can't have existing cleanups when a Scheme exception is thrown. */
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "#sOi", rest,
|
||
&encoding_arg_pos, &encoding,
|
||
&errors_arg_pos, &errors,
|
||
&length_arg_pos, &length);
|
||
|
||
cleanups = make_cleanup (xfree, encoding);
|
||
|
||
if (errors_arg_pos > 0
|
||
&& errors != SCM_BOOL_F
|
||
&& !scm_is_eq (errors, error_symbol)
|
||
&& !scm_is_eq (errors, substitute_symbol))
|
||
{
|
||
SCM excp
|
||
= gdbscm_make_out_of_range_error (FUNC_NAME, errors_arg_pos, errors,
|
||
_("invalid error kind"));
|
||
|
||
do_cleanups (cleanups);
|
||
gdbscm_throw (excp);
|
||
}
|
||
if (errors == SCM_BOOL_F)
|
||
{
|
||
/* N.B. scm_port_conversion_strategy in Guile versions prior to 2.0.6
|
||
will throw a Scheme error when passed #f. */
|
||
if (gdbscm_guile_version_is_at_least (2, 0, 6))
|
||
errors = scm_port_conversion_strategy (SCM_BOOL_F);
|
||
else
|
||
errors = error_symbol;
|
||
}
|
||
/* We don't assume anything about the result of scm_port_conversion_strategy.
|
||
From this point on, if errors is not 'errors, use 'substitute. */
|
||
|
||
TRY
|
||
{
|
||
LA_GET_STRING (value, &buffer, &length, &char_type, &la_encoding);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
/* If errors is "error" scm_from_stringn may throw a Scheme exception.
|
||
Make sure we don't leak. This is done via scm_dynwind_begin, et.al. */
|
||
discard_cleanups (cleanups);
|
||
|
||
scm_dynwind_begin (0);
|
||
|
||
gdbscm_dynwind_xfree (encoding);
|
||
gdbscm_dynwind_xfree (buffer);
|
||
|
||
result = scm_from_stringn ((const char *) buffer,
|
||
length * TYPE_LENGTH (char_type),
|
||
(encoding != NULL && *encoding != '\0'
|
||
? encoding
|
||
: la_encoding),
|
||
scm_is_eq (errors, error_symbol)
|
||
? SCM_FAILED_CONVERSION_ERROR
|
||
: SCM_FAILED_CONVERSION_QUESTION_MARK);
|
||
|
||
scm_dynwind_end ();
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value->lazy-string <gdb:value> [#:encoding encoding] [#:length length])
|
||
-> <gdb:lazy-string>
|
||
Return a Scheme object representing a lazy_string_object type.
|
||
A lazy string is a pointer to a string with an optional encoding and length.
|
||
If ENCODING is not given, the target's charset is used.
|
||
If LENGTH is provided then the length parameter is set to LENGTH, otherwise
|
||
length will be set to -1 (first null of appropriate with).
|
||
LENGTH must be a Scheme integer, it can't be a <gdb:value> integer. */
|
||
|
||
static SCM
|
||
gdbscm_value_to_lazy_string (SCM self, SCM rest)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
const SCM keywords[] = { encoding_keyword, length_keyword, SCM_BOOL_F };
|
||
int encoding_arg_pos = -1, length_arg_pos = -1;
|
||
char *encoding = NULL;
|
||
int length = -1;
|
||
SCM result = SCM_BOOL_F; /* -Wall */
|
||
struct cleanup *cleanups;
|
||
struct gdb_exception except = exception_none;
|
||
|
||
/* The sequencing here, as everywhere else, is important.
|
||
We can't have existing cleanups when a Scheme exception is thrown. */
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "#si", rest,
|
||
&encoding_arg_pos, &encoding,
|
||
&length_arg_pos, &length);
|
||
|
||
cleanups = make_cleanup (xfree, encoding);
|
||
|
||
TRY
|
||
{
|
||
struct cleanup *inner_cleanup
|
||
= make_cleanup_value_free_to_mark (value_mark ());
|
||
|
||
if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
|
||
value = value_ind (value);
|
||
|
||
result = lsscm_make_lazy_string (value_address (value), length,
|
||
encoding, value_type (value));
|
||
|
||
do_cleanups (inner_cleanup);
|
||
}
|
||
CATCH (ex, RETURN_MASK_ALL)
|
||
{
|
||
except = ex;
|
||
}
|
||
END_CATCH
|
||
|
||
do_cleanups (cleanups);
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (value-lazy? <gdb:value>) -> boolean */
|
||
|
||
static SCM
|
||
gdbscm_value_lazy_p (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
|
||
return scm_from_bool (value_lazy (value));
|
||
}
|
||
|
||
/* (value-fetch-lazy! <gdb:value>) -> unspecified */
|
||
|
||
static SCM
|
||
gdbscm_value_fetch_lazy_x (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
|
||
TRY
|
||
{
|
||
if (value_lazy (value))
|
||
value_fetch_lazy (value);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
|
||
/* (value-print <gdb:value>) -> string */
|
||
|
||
static SCM
|
||
gdbscm_value_print (SCM self)
|
||
{
|
||
value_smob *v_smob
|
||
= vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||
struct value *value = v_smob->value;
|
||
struct value_print_options opts;
|
||
char *s = NULL;
|
||
SCM result;
|
||
|
||
get_user_print_options (&opts);
|
||
opts.deref_ref = 0;
|
||
|
||
TRY
|
||
{
|
||
struct ui_file *stb = mem_fileopen ();
|
||
struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
|
||
|
||
common_val_print (value, stb, 0, &opts, current_language);
|
||
s = ui_file_xstrdup (stb, NULL);
|
||
|
||
do_cleanups (old_chain);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
/* Use SCM_FAILED_CONVERSION_QUESTION_MARK to ensure this doesn't
|
||
throw an error if the encoding fails.
|
||
IWBN to use scm_take_locale_string here, but we'd have to temporarily
|
||
override the default port conversion handler because contrary to
|
||
documentation it doesn't necessarily free the input string. */
|
||
result = scm_from_stringn (s, strlen (s), host_charset (),
|
||
SCM_FAILED_CONVERSION_QUESTION_MARK);
|
||
xfree (s);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (parse-and-eval string) -> <gdb:value>
|
||
Parse a string and evaluate the string as an expression. */
|
||
|
||
static SCM
|
||
gdbscm_parse_and_eval (SCM expr_scm)
|
||
{
|
||
char *expr_str;
|
||
struct value *res_val = NULL;
|
||
SCM result;
|
||
struct cleanup *cleanups;
|
||
|
||
/* The sequencing here, as everywhere else, is important.
|
||
We can't have existing cleanups when a Scheme exception is thrown. */
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "s",
|
||
expr_scm, &expr_str);
|
||
|
||
cleanups = make_cleanup_value_free_to_mark (value_mark ());
|
||
make_cleanup (xfree, expr_str);
|
||
|
||
TRY
|
||
{
|
||
res_val = parse_and_eval (expr_str);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
|
||
}
|
||
END_CATCH
|
||
|
||
gdb_assert (res_val != NULL);
|
||
result = vlscm_scm_from_value (res_val);
|
||
|
||
do_cleanups (cleanups);
|
||
|
||
if (gdbscm_is_exception (result))
|
||
gdbscm_throw (result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* (history-ref integer) -> <gdb:value>
|
||
Return the specified value from GDB's value history. */
|
||
|
||
static SCM
|
||
gdbscm_history_ref (SCM index)
|
||
{
|
||
int i;
|
||
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
|
||
|
||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "i", index, &i);
|
||
|
||
TRY
|
||
{
|
||
res_val = access_value_history (i);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return vlscm_scm_from_value (res_val);
|
||
}
|
||
|
||
/* (history-append! <gdb:value>) -> index
|
||
Append VALUE to GDB's value history. Return its index in the history. */
|
||
|
||
static SCM
|
||
gdbscm_history_append_x (SCM value)
|
||
{
|
||
int res_index = -1;
|
||
struct value *v;
|
||
value_smob *v_smob;
|
||
|
||
v_smob = vlscm_get_value_smob_arg_unsafe (value, SCM_ARG1, FUNC_NAME);
|
||
v = v_smob->value;
|
||
|
||
TRY
|
||
{
|
||
res_index = record_latest_value (v);
|
||
}
|
||
CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||
}
|
||
END_CATCH
|
||
|
||
return scm_from_int (res_index);
|
||
}
|
||
|
||
/* Initialize the Scheme value code. */
|
||
|
||
static const scheme_function value_functions[] =
|
||
{
|
||
{ "value?", 1, 0, 0, gdbscm_value_p,
|
||
"\
|
||
Return #t if the object is a <gdb:value> object." },
|
||
|
||
{ "make-value", 1, 0, 1, gdbscm_make_value,
|
||
"\
|
||
Create a <gdb:value> representing object.\n\
|
||
Typically this is used to convert numbers and strings to\n\
|
||
<gdb:value> objects.\n\
|
||
\n\
|
||
Arguments: object [#:type <gdb:type>]" },
|
||
|
||
{ "value-optimized-out?", 1, 0, 0, gdbscm_value_optimized_out_p,
|
||
"\
|
||
Return #t if the value has been optimizd out." },
|
||
|
||
{ "value-address", 1, 0, 0, gdbscm_value_address,
|
||
"\
|
||
Return the address of the value." },
|
||
|
||
{ "value-type", 1, 0, 0, gdbscm_value_type,
|
||
"\
|
||
Return the type of the value." },
|
||
|
||
{ "value-dynamic-type", 1, 0, 0, gdbscm_value_dynamic_type,
|
||
"\
|
||
Return the dynamic type of the value." },
|
||
|
||
{ "value-cast", 2, 0, 0, gdbscm_value_cast,
|
||
"\
|
||
Cast the value to the supplied type.\n\
|
||
\n\
|
||
Arguments: <gdb:value> <gdb:type>" },
|
||
|
||
{ "value-dynamic-cast", 2, 0, 0, gdbscm_value_dynamic_cast,
|
||
"\
|
||
Cast the value to the supplied type, as if by the C++\n\
|
||
dynamic_cast operator.\n\
|
||
\n\
|
||
Arguments: <gdb:value> <gdb:type>" },
|
||
|
||
{ "value-reinterpret-cast", 2, 0, 0, gdbscm_value_reinterpret_cast,
|
||
"\
|
||
Cast the value to the supplied type, as if by the C++\n\
|
||
reinterpret_cast operator.\n\
|
||
\n\
|
||
Arguments: <gdb:value> <gdb:type>" },
|
||
|
||
{ "value-dereference", 1, 0, 0, gdbscm_value_dereference,
|
||
"\
|
||
Return the result of applying the C unary * operator to the value." },
|
||
|
||
{ "value-referenced-value", 1, 0, 0, gdbscm_value_referenced_value,
|
||
"\
|
||
Given a value of a reference type, return the value referenced.\n\
|
||
The difference between this function and value-dereference is that\n\
|
||
the latter applies * unary operator to a value, which need not always\n\
|
||
result in the value referenced.\n\
|
||
For example, for a value which is a reference to an 'int' pointer ('int *'),\n\
|
||
value-dereference will result in a value of type 'int' while\n\
|
||
value-referenced-value will result in a value of type 'int *'." },
|
||
|
||
{ "value-field", 2, 0, 0, gdbscm_value_field,
|
||
"\
|
||
Return the specified field of the value.\n\
|
||
\n\
|
||
Arguments: <gdb:value> string" },
|
||
|
||
{ "value-subscript", 2, 0, 0, gdbscm_value_subscript,
|
||
"\
|
||
Return the value of the array at the specified index.\n\
|
||
\n\
|
||
Arguments: <gdb:value> integer" },
|
||
|
||
{ "value-call", 2, 0, 0, gdbscm_value_call,
|
||
"\
|
||
Perform an inferior function call taking the value as a pointer to the\n\
|
||
function to call.\n\
|
||
Each element of the argument list must be a <gdb:value> object or an object\n\
|
||
that can be converted to one.\n\
|
||
The result is the value returned by the function.\n\
|
||
\n\
|
||
Arguments: <gdb:value> arg-list" },
|
||
|
||
{ "value->bool", 1, 0, 0, gdbscm_value_to_bool,
|
||
"\
|
||
Return the Scheme boolean representing the GDB value.\n\
|
||
The value must be \"integer like\". Pointers are ok." },
|
||
|
||
{ "value->integer", 1, 0, 0, gdbscm_value_to_integer,
|
||
"\
|
||
Return the Scheme integer representing the GDB value.\n\
|
||
The value must be \"integer like\". Pointers are ok." },
|
||
|
||
{ "value->real", 1, 0, 0, gdbscm_value_to_real,
|
||
"\
|
||
Return the Scheme real number representing the GDB value.\n\
|
||
The value must be a number." },
|
||
|
||
{ "value->bytevector", 1, 0, 0, gdbscm_value_to_bytevector,
|
||
"\
|
||
Return a Scheme bytevector with the raw contents of the GDB value.\n\
|
||
No transformation, endian or otherwise, is performed." },
|
||
|
||
{ "value->string", 1, 0, 1, gdbscm_value_to_string,
|
||
"\
|
||
Return the Unicode string of the value's contents.\n\
|
||
If ENCODING is not given, the string is assumed to be encoded in\n\
|
||
the target's charset.\n\
|
||
An error setting \"error\" causes an exception to be thrown if there's\n\
|
||
a decoding error. An error setting of \"substitute\" causes invalid\n\
|
||
characters to be replaced with \"?\". The default is \"error\".\n\
|
||
If LENGTH is provided, only fetch string to the length provided.\n\
|
||
\n\
|
||
Arguments: <gdb:value>\n\
|
||
[#:encoding encoding] [#:errors \"error\"|\"substitute\"]\n\
|
||
[#:length length]" },
|
||
|
||
{ "value->lazy-string", 1, 0, 1, gdbscm_value_to_lazy_string,
|
||
"\
|
||
Return a Scheme object representing a lazily fetched Unicode string\n\
|
||
of the value's contents.\n\
|
||
If ENCODING is not given, the string is assumed to be encoded in\n\
|
||
the target's charset.\n\
|
||
If LENGTH is provided, only fetch string to the length provided.\n\
|
||
\n\
|
||
Arguments: <gdb:value> [#:encoding encoding] [#:length length]" },
|
||
|
||
{ "value-lazy?", 1, 0, 0, gdbscm_value_lazy_p,
|
||
"\
|
||
Return #t if the value is lazy (not fetched yet from the inferior).\n\
|
||
A lazy value is fetched when needed, or when the value-fetch-lazy! function\n\
|
||
is called." },
|
||
|
||
{ "make-lazy-value", 2, 0, 0, gdbscm_make_lazy_value,
|
||
"\
|
||
Create a <gdb:value> that will be lazily fetched from the target.\n\
|
||
\n\
|
||
Arguments: <gdb:type> address" },
|
||
|
||
{ "value-fetch-lazy!", 1, 0, 0, gdbscm_value_fetch_lazy_x,
|
||
"\
|
||
Fetch the value from the inferior, if it was lazy.\n\
|
||
The result is \"unspecified\"." },
|
||
|
||
{ "value-print", 1, 0, 0, gdbscm_value_print,
|
||
"\
|
||
Return the string representation (print form) of the value." },
|
||
|
||
{ "parse-and-eval", 1, 0, 0, gdbscm_parse_and_eval,
|
||
"\
|
||
Evaluates string in gdb and returns the result as a <gdb:value> object." },
|
||
|
||
{ "history-ref", 1, 0, 0, gdbscm_history_ref,
|
||
"\
|
||
Return the specified value from GDB's value history." },
|
||
|
||
{ "history-append!", 1, 0, 0, gdbscm_history_append_x,
|
||
"\
|
||
Append the specified value onto GDB's value history." },
|
||
|
||
END_FUNCTIONS
|
||
};
|
||
|
||
void
|
||
gdbscm_initialize_values (void)
|
||
{
|
||
value_smob_tag = gdbscm_make_smob_type (value_smob_name,
|
||
sizeof (value_smob));
|
||
scm_set_smob_free (value_smob_tag, vlscm_free_value_smob);
|
||
scm_set_smob_print (value_smob_tag, vlscm_print_value_smob);
|
||
scm_set_smob_equalp (value_smob_tag, vlscm_equal_p_value_smob);
|
||
|
||
gdbscm_define_functions (value_functions, 1);
|
||
|
||
type_keyword = scm_from_latin1_keyword ("type");
|
||
encoding_keyword = scm_from_latin1_keyword ("encoding");
|
||
errors_keyword = scm_from_latin1_keyword ("errors");
|
||
length_keyword = scm_from_latin1_keyword ("length");
|
||
|
||
error_symbol = scm_from_latin1_symbol ("error");
|
||
escape_symbol = scm_from_latin1_symbol ("escape");
|
||
substitute_symbol = scm_from_latin1_symbol ("substitute");
|
||
}
|