aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/Makefile.in20
-rw-r--r--gdb/NEWS11
-rw-r--r--gdb/README24
-rw-r--r--gdb/ada-lang.c37
-rw-r--r--gdb/amd64-tdep.c13
-rw-r--r--gdb/ax-gdb.c3
-rw-r--r--gdb/c-typeprint.c11
-rw-r--r--gdb/config.in3
-rwxr-xr-xgdb/configure124
-rw-r--r--gdb/configure.ac92
-rw-r--r--gdb/configure.tgt20
-rw-r--r--gdb/doc/gdb.texinfo8
-rw-r--r--gdb/dwarf2/read-debug-names.c20
-rw-r--r--gdb/dwarf2/read-gdb-index.c9
-rw-r--r--gdb/dwarf2/read.c32
-rw-r--r--gdb/dwarf2/read.h30
-rw-r--r--gdb/eval.c2
-rw-r--r--gdb/event-top.c3
-rw-r--r--gdb/f-typeprint.c11
-rw-r--r--gdb/frame.c32
-rw-r--r--gdb/frame.h3
-rw-r--r--gdb/gdbtypes.c90
-rw-r--r--gdb/gdbtypes.h18
-rw-r--r--gdb/guile/scm-type.c2
-rw-r--r--gdb/i386-tdep.c29
-rw-r--r--gdb/i386-tdep.h84
-rw-r--r--gdb/macroscope.c6
-rw-r--r--gdb/main.c4
-rw-r--r--gdb/mdebugread.c2
-rw-r--r--gdb/nat/aarch64-hw-point.c6
-rw-r--r--gdb/ppc-sysv-tdep.c6
-rw-r--r--gdb/printcmd.c8
-rw-r--r--gdb/python/lib/gdb/dap/varref.py4
-rw-r--r--gdb/python/lib/gdb/printing.py14
-rw-r--r--gdb/python/py-finishbreakpoint.c6
-rw-r--r--gdb/python/py-type.c11
-rw-r--r--gdb/rust-lang.c16
-rw-r--r--gdb/source.c28
-rw-r--r--gdb/stabsread.c5
-rw-r--r--gdb/stack.c38
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array.exp40
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/proc.adb22
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/value.adb21
-rw-r--r--gdb/testsuite/gdb.ada/return-small-char-array/value.ads20
-rw-r--r--gdb/testsuite/gdb.base/color-prompt.exp29
-rw-r--r--gdb/testsuite/gdb.base/default.exp53
-rw-r--r--gdb/testsuite/gdb.base/dlmopen.exp22
-rw-r--r--gdb/testsuite/gdb.base/exprs.exp5
-rw-r--r--gdb/testsuite/gdb.base/readline-ask.exp2
-rw-r--r--gdb/testsuite/gdb.base/readline.exp2
-rw-r--r--gdb/testsuite/gdb.base/source-search.c127
-rw-r--r--gdb/testsuite/gdb.base/source-search.exp106
-rw-r--r--gdb/testsuite/gdb.base/style.exp2
-rw-r--r--gdb/testsuite/gdb.base/tls-common.exp.tcl2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj-lib.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.exp2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.exp2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj1.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj2.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj3.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.c2
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.exp2
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-unaligned.c37
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-unaligned.exp111
-rw-r--r--gdb/testsuite/gdb.cp/method-ref-return.cc42
-rw-r--r--gdb/testsuite/gdb.cp/method-ref-return.exp70
-rw-r--r--gdb/testsuite/gdb.dap/scopes.c2
-rw-r--r--gdb/testsuite/gdb.dap/scopes.exp44
-rw-r--r--gdb/testsuite/gdb.gdb/python-helper.exp2
-rw-r--r--gdb/testsuite/gdb.gdb/selftest.exp2
-rw-r--r--gdb/testsuite/gdb.guile/scm-parameter.exp85
-rw-r--r--gdb/testsuite/gdb.python/py-parameter.exp5
-rw-r--r--gdb/testsuite/gdb.tui/basic.exp6
-rw-r--r--gdb/testsuite/gdb.tui/color-prompt.exp10
-rw-r--r--gdb/testsuite/gdb.tui/color-prompt.exp.tcl80
-rwxr-xr-xgdb/testsuite/gdb.tui/gdb.tcl20
-rw-r--r--gdb/testsuite/gdb.tui/main-2.exp4
-rw-r--r--gdb/testsuite/gdb.tui/main.exp5
-rw-r--r--gdb/testsuite/gdb.tui/new-layout.exp3
-rw-r--r--gdb/testsuite/gdb.tui/pr30056.exp5
-rw-r--r--gdb/testsuite/gdb.tui/source-search.c127
-rw-r--r--gdb/testsuite/gdb.tui/source-search.exp71
-rw-r--r--gdb/testsuite/gdb.tui/tui-disasm-styling.exp3
-rw-r--r--gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp10
-rw-r--r--gdb/testsuite/gdb.tui/tui-mode-switch.exp57
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm-2.exp70
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm.exp16
-rw-r--r--gdb/testsuite/lib/selftest-support.exp46
-rw-r--r--gdb/testsuite/lib/tuiterm.exp2411
-rw-r--r--gdb/top.c7
-rw-r--r--gdb/tracepoint.c8
-rw-r--r--gdb/tui/tui-disasm.c34
-rw-r--r--gdb/tui/tui-status.c8
-rw-r--r--gdb/tui/tui-winsource.c4
-rw-r--r--gdb/tui/tui.c13
-rw-r--r--gdb/valops.c12
98 files changed, 3246 insertions, 1542 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fc0c565..7654fb1 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -907,13 +907,22 @@ ALL_TARGET_OBS = \
vax-tdep.o \
windows-tdep.o \
x86-tdep.o \
- xcoffread.o \
xstormy16-tdep.o \
xtensa-config.o \
xtensa-linux-tdep.o \
xtensa-tdep.o \
z80-tdep.o
+# Object files for reading specific types of debug information.
+coff_SRCS = coffread.c coff-pe-read.c
+dbx_SRCS = dbxread.c
+elf_SRCS = elfread.c stap-probe.c dtrace-probe.c
+macho_SRCS = machoread.c
+mips_SRCS = mipsread.c
+xcoff_SRCS = xcoffread.c
+FORMAT_SRCS = @FORMAT_SRCS@
+FORMAT_OBS = $(patsubst %.c,%.o,$(FORMAT_SRCS))
+
# The following native-target dependent variables are defined on
# configure.nat.
NAT_FILE = @NAT_FILE@
@@ -1070,8 +1079,6 @@ COMMON_SFILES = \
c-varobj.c \
charset.c \
cli-out.c \
- coff-pe-read.c \
- coffread.c \
complaints.c \
completer.c \
copying.c \
@@ -1085,7 +1092,6 @@ COMMON_SFILES = \
d-lang.c \
d-namespace.c \
d-valprint.c \
- dbxread.c \
dcache.c \
debug.c \
debuginfod-support.c \
@@ -1150,7 +1156,6 @@ COMMON_SFILES = \
memtag.c \
minidebug.c \
minsyms.c \
- mipsread.c \
namespace.c \
objc-lang.c \
objfiles.c \
@@ -1243,7 +1248,6 @@ SFILES = \
d-exp.y \
dtrace-probe.c \
elf-none-tdep.c \
- elfread.c \
f-exp.y \
gcore-elf.c \
gdb.c \
@@ -1870,7 +1874,6 @@ ALLDEPFILES = \
x86-gnu-nat.c \
x86-nat.c \
x86-tdep.c \
- xcoffread.c \
xstormy16-tdep.c \
xtensa-config.c \
xtensa-linux-nat.c \
@@ -1925,7 +1928,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
$(patsubst %.c,%.o,$(COMMON_SFILES)) \
$(SUBDIR_CLI_OBS) \
$(SUBDIR_MI_OBS) \
- $(SUBDIR_TARGET_OBS)
+ $(SUBDIR_TARGET_OBS) \
+ $(FORMAT_OBS)
SUBDIRS = doc @subdirs@ data-directory
CLEANDIRS = $(SUBDIRS)
diff --git a/gdb/NEWS b/gdb/NEWS
index 4c9aed4..a8c1731 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -224,6 +224,17 @@ vFile:stat
* Support for stabs debugging format and the a.out/dbx object format is
deprecated, and will be removed in GDB 18.
+* Configure changes
+
+--enable-binary-file-formats=[FORMAT,...]
+--enable-binary-file-formats=all
+ A user can now decide to only compile support for certain file formats.
+ The available formats at this point are: dbx, coff, xcoff, elf, mach-o
+ and mips. Some targets require specific file formats to be available,
+ and in such cases, the configure script will warn the user and add
+ support anyway. By default, all formats will be compiled in, to
+ continue the behavior from before adding the switch.
+
* A new configure option was added, allowing support for the compile
subsystem to be disabled at configure time, in the form of
--disable-gdb-compile.
diff --git a/gdb/README b/gdb/README
index eca4181c..5dc2e7e 100644
--- a/gdb/README
+++ b/gdb/README
@@ -417,6 +417,30 @@ more obscure GDB `configure' options are not listed here.
There is no convenient way to generate a list of all available
targets.
+`--enable-binary-file-formats=FORMAT,FORMAT,...'
+`--enable-binary-file-formats=all'
+ Configure GDB to only be be able to read selected file formats.
+ The special value "all" causes all file formats to be compiled
+ in, and is the the default behavior of the option. This option
+ is meant for advanced users who are sure of what they expect,
+ if you are unsure which options you will need on your debugging
+ sessions, we recommend that you not use this feature. The
+ accepted options are:
+ * coff: Main format on Windows systems, this is required to
+ compile with windows target support;
+ * dbx (also known as a.out): Legacy file format, this is
+ recommended if you know you will be dealing with this
+ file format;
+ * elf: Main format on Linux systems, this is heavily
+ recommended when compiling with linux support;
+ * macho: Main format on MacOS systems, this is heavily
+ recommended when compiling for those targets;
+ * mips (also known as ecoff): Main file format for targets
+ running on MIPS CPUs, this is heavily recommended when
+ supporting those targets;
+ * xcoff: Main format on AIX systems, this is required to
+ compile for AIX targets and rs6000 CPUs.
+
`--with-gdb-datadir=PATH'
Set the GDB-specific data directory. GDB will look here for
certain supporting files or scripts. This defaults to the `gdb'
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 329d114..1955169 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1677,8 +1677,6 @@ ada_decode_symbol (const struct general_symbol_info *arg)
void
ada_fixup_array_indexes_type (struct type *index_desc_type)
{
- int i;
-
if (index_desc_type == NULL)
return;
gdb_assert (index_desc_type->num_fields () > 0);
@@ -1696,13 +1694,13 @@ ada_fixup_array_indexes_type (struct type *index_desc_type)
return;
/* Fixup each field of INDEX_DESC_TYPE. */
- for (i = 0; i < index_desc_type->num_fields (); i++)
+ for (auto &field : index_desc_type->fields ())
{
- const char *name = index_desc_type->field (i).name ();
+ const char *name = field.name ();
struct type *raw_type = ada_check_typedef (ada_find_any_type (name));
if (raw_type)
- index_desc_type->field (i).set_type (raw_type);
+ field.set_type (raw_type);
}
}
@@ -7080,17 +7078,16 @@ ada_search_struct_field (const char *name, struct value *arg, int offset,
else if (ada_is_variant_part (type, i))
{
/* PNH: Do we ever get here? See find_struct_field. */
- int j;
struct type *field_type = ada_check_typedef (type->field (i).type ());
int var_offset = offset + type->field (i).loc_bitpos () / 8;
- for (j = 0; j < field_type->num_fields (); j += 1)
+ for (const auto &field : field_type->fields ())
{
- struct value *v = ada_search_struct_field /* Force line
- break. */
- (name, arg,
- var_offset + field_type->field (j).loc_bitpos () / 8,
- field_type->field (j).type ());
+ struct value *v
+ = (ada_search_struct_field
+ (name, arg,
+ var_offset + field.loc_bitpos () / 8,
+ field.type ()));
if (v != NULL)
return v;
@@ -8182,12 +8179,11 @@ ada_is_redundant_index_type_desc (struct type *array_type,
struct type *desc_type)
{
struct type *this_layer = check_typedef (array_type);
- int i;
- for (i = 0; i < desc_type->num_fields (); i++)
+ for (const auto &field : desc_type->fields ())
{
if (!ada_is_redundant_range_encoding (this_layer->index_type (),
- desc_type->field (i).type ()))
+ field.type ()))
return 0;
this_layer = check_typedef (this_layer->target_type ());
}
@@ -8784,9 +8780,9 @@ ada_atr_enum_val (struct expression *exp, enum noside noside, struct type *type,
error (_("'Enum_Val requires integral argument"));
LONGEST value = value_as_long (arg);
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () == value)
+ if (field.loc_enumval () == value)
return value_from_longest (original_type, value);
}
@@ -10502,7 +10498,6 @@ static LONGEST
convert_char_literal (struct type *type, LONGEST val)
{
char name[12];
- int f;
if (type == NULL)
return val;
@@ -10519,17 +10514,17 @@ convert_char_literal (struct type *type, LONGEST val)
else
xsnprintf (name, sizeof (name), "QWW%08lx", (unsigned long) val);
size_t len = strlen (name);
- for (f = 0; f < type->num_fields (); f += 1)
+ for (const auto &field : type->fields ())
{
/* Check the suffix because an enum constant in a package will
have a name like "pkg__QUxx". This is safe enough because we
already have the correct type, and because mangling means
there can't be clashes. */
- const char *ename = type->field (f).name ();
+ const char *ename = field.name ();
size_t elen = strlen (ename);
if (elen >= len && strcmp (name, ename + elen - len) == 0)
- return type->field (f).loc_enumval ();
+ return field.loc_enumval ();
}
return val;
}
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 82dd1e0..d5ea4af 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -513,20 +513,19 @@ amd64_has_unaligned_fields (struct type *type)
if (type->code () == TYPE_CODE_STRUCT
|| type->code () == TYPE_CODE_UNION)
{
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- struct type *subtype = check_typedef (type->field (i).type ());
+ struct type *subtype = check_typedef (field.type ());
/* Ignore static fields, empty fields (for example nested
empty structures), and bitfields (these are handled by
the caller). */
- if (type->field (i).is_static ()
- || (type->field (i).bitsize () == 0
- && subtype->length () == 0)
- || type->field (i).is_packed ())
+ if (field.is_static ()
+ || (field.bitsize () == 0 && subtype->length () == 0)
+ || field.is_packed ())
continue;
- int bitpos = type->field (i).loc_bitpos ();
+ int bitpos = field.loc_bitpos ();
if (bitpos % 8 != 0)
return true;
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 08f542c..57626ab 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -538,8 +538,7 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
break;
case LOC_CONST_BYTES:
- internal_error (_("gen_var_ref: LOC_CONST_BYTES "
- "symbols are not supported"));
+ error (_("gen_var_ref: LOC_CONST_BYTES symbols are not supported"));
/* Variable at a fixed location in memory. Easy. */
case LOC_STATIC:
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index df7bdbe..b6b3f6b 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -251,8 +251,8 @@ cp_type_print_method_args (struct type *mtype, const char *prefix,
enum language language,
const struct type_print_options *flags)
{
- struct field *args = mtype->fields ();
- int nargs = mtype->num_fields ();
+ auto args = mtype->fields ();
+ int nargs = args.size ();
int varargs = mtype->has_varargs ();
int i;
@@ -515,16 +515,15 @@ c_type_print_args (struct type *type, struct ui_file *stream,
int linkage_name, enum language language,
const struct type_print_options *flags)
{
- int i;
int printed_any = 0;
gdb_printf (stream, "(");
- for (i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
struct type *param_type;
- if (type->field (i).is_artificial () && linkage_name)
+ if (field.is_artificial () && linkage_name)
continue;
if (printed_any)
@@ -533,7 +532,7 @@ c_type_print_args (struct type *type, struct ui_file *stream,
stream->wrap_here (4);
}
- param_type = type->field (i).type ();
+ param_type = field.type ();
if (language == language_cplus && linkage_name)
{
diff --git a/gdb/config.in b/gdb/config.in
index 149aeaf..efc3100 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -745,6 +745,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+/* Which binary file formats were requested at configure time. */
+#undef SUPPORTED_BINARY_FILE_FORMATS
+
/* automatically load a system-wide gdbinit file */
#undef SYSTEM_GDBINIT
diff --git a/gdb/configure b/gdb/configure
index 8fc3b04..cdea00f 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -706,6 +706,7 @@ LIBGUI
LTLIBLZMA
LIBLZMA
HAVE_LIBLZMA
+FORMAT_SRCS
SER_HARDWIRE
WERROR_CFLAGS
WARN_CFLAGS
@@ -932,6 +933,7 @@ with_relocated_sources
with_auto_load_dir
with_auto_load_safe_path
enable_targets
+enable_binary_file_formats
enable_gdb_mdebug_support
enable_gdb_dwarf_support
with_amd_dbgapi
@@ -1645,6 +1647,10 @@ Optional Features:
--disable-nls do not use Native Language Support
--enable-targets=TARGETS
alternative target configurations
+ --enable-binary-file-formats=FORMATS
+ enable support for selected file formats (default
+ 'all') available formats: coff, dbx, elf, macho,
+ mips, xcoff, all
--enable-gdb-mdebug-support
Enable support for the mdebug debuginfo format
(default 'yes')
@@ -11507,7 +11513,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11510 "configure"
+#line 11516 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11613,7 +11619,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11616 "configure"
+#line 11622 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -24882,6 +24888,18 @@ esac
fi
+# Check whether --enable-binary_file_formats was given.
+if test "${enable_binary_file_formats+set}" = set; then :
+ enableval=$enable_binary_file_formats; case "${enableval}" in
+ yes | "") as_fn_error $? "enable-binary-file-formats option must specify file formats or 'all'" "$LINENO" 5
+ ;;
+ no) enable_binary_file_formats= ;;
+ *) enable_binary_file_formats=$enableval ;;
+esac
+else
+ enable_binary_file_formats=all
+fi
+
# Check whether to support mdebug/ecoff debug information.
# Check whether --enable-gdb-mdebug-support was given.
@@ -24986,10 +25004,21 @@ TARGET_OBS=
all_targets=
HAVE_NATIVE_GCORE_TARGET=
+# File formats that will be enabled based on the selected
+# target(s). These are chosen because they are required to
+# compile one or more of the selected targets.
+target_formats=
+
+# If all targets were requested, this is all formats that should
+# accompany them. These are just the ones required for compilation
+# to succeed, not the formats suggested based on targets.
+all_target_formats="coff xcoff"
+
for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
do
if test "$targ_alias" = "all"; then
all_targets=true
+ target_formats=$all_target_formats
else
# Canonicalize the secondary target names.
result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -31628,6 +31657,12 @@ fi
# Note that WIN32APILIBS is set by GDB_AC_COMMON.
WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
+# Object files to be used when building with support for all file formats.
+# This should not have elf or macho, as support for those formats depends
+# on BFD enabling them as well.
+all_binary_file_srcs="\$(dbx_SRCS) \$(mips_SRCS) \$(coff_SRCS) \$(xcoff_SRCS)"
+
+bfd_supports_elf=no
# Add ELF support to GDB, but only if BFD includes ELF support.
OLD_CFLAGS=$CFLAGS
@@ -31645,7 +31680,7 @@ WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
CC="./libtool --quiet --mode=link $CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ELF support in BFD" >&5
$as_echo_n "checking for ELF support in BFD... " >&6; }
-if ${gdb_cv_var_elf+:} false; then :
+if ${gdb_cv_var_bfd_elf+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -31664,24 +31699,23 @@ return bfd_get_elf_phdr_upper_bound (NULL);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- gdb_cv_var_elf=yes
+ gdb_cv_var_bfd_elf=yes
else
- gdb_cv_var_elf=no
+ gdb_cv_var_bfd_elf=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_elf" >&5
-$as_echo "$gdb_cv_var_elf" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_bfd_elf" >&5
+$as_echo "$gdb_cv_var_bfd_elf" >&6; }
CC=$OLD_CC
CFLAGS=$OLD_CFLAGS
LDFLAGS=$OLD_LDFLAGS
LIBS=$OLD_LIBS
-if test "$gdb_cv_var_elf" = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o \
- gcore-elf.o elf-none-tdep.o"
+if test "$gdb_cv_var_bfd_elf" = yes; then
+ CONFIG_OBS="$CONFIG_OBS gcore-elf.o elf-none-tdep.o"
$as_echo "#define HAVE_ELF 1" >>confdefs.h
@@ -31744,9 +31778,12 @@ if test "$ac_res" != no; then :
fi
fi
+ bfd_supports_elf=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(elf_SRCS)"
fi
# Add macho support to GDB, but only if BFD includes it.
+bfd_supports_macho=no
OLD_CFLAGS=$CFLAGS
OLD_LDFLAGS=$LDFLAGS
@@ -31763,7 +31800,7 @@ fi
CC="./libtool --quiet --mode=link $CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mach-O support in BFD" >&5
$as_echo_n "checking for Mach-O support in BFD... " >&6; }
-if ${gdb_cv_var_macho+:} false; then :
+if ${gdb_cv_var_bfd_macho+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -31782,30 +31819,81 @@ return bfd_mach_o_lookup_command (NULL, 0, NULL);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- gdb_cv_var_macho=yes
+ gdb_cv_var_bfd_macho=yes
else
- gdb_cv_var_macho=no
+ gdb_cv_var_bfd_macho=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_macho" >&5
-$as_echo "$gdb_cv_var_macho" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_bfd_macho" >&5
+$as_echo "$gdb_cv_var_bfd_macho" >&6; }
CC=$OLD_CC
CFLAGS=$OLD_CFLAGS
LDFLAGS=$OLD_LDFLAGS
LIBS=$OLD_LIBS
-if test "$gdb_cv_var_macho" = yes; then
- CONFIG_OBS="$CONFIG_OBS machoread.o"
+if test "$gdb_cv_var_bfd_macho" = yes; then
+ bfd_supports_macho=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(macho_SRCS)"
fi
+FORMAT_SRCS=
+
+if test "$enable_binary_file_formats" != "all"; then
+ # Formats that are required by some requested target(s).
+ # Warn users that they are added, so no one is surprised.
+ for req in $target_formats; do
+ case ,$enable_binary_file_formats, in
+ *,$req,*)
+ # Do nothing.
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"$req is required to support one or more requested targets. Adding it\"" >&5
+$as_echo "$as_me: WARNING: \"$req is required to support one or more requested targets. Adding it\"" >&2;}
+ enable_binary_file_formats="${enable_binary_file_formats},$req"
+ ;;
+ esac
+ done
+
+
+cat >>confdefs.h <<_ACEOF
+#define SUPPORTED_BINARY_FILE_FORMATS "$enable_binary_file_formats"
+_ACEOF
+
+fi
+
+enable_binary_file_formats=$(echo $enable_binary_file_formats | sed 's/,/ /g')
+
+# Go through all requested and required binary file formats to compile
+# GDB, and double check that we can compile them.
+for format in $enable_binary_file_formats
+do
+ if test "$format" = "elf" && test "$bfd_supports_elf" != "yes"; then
+ as_fn_error but BFD does not support it." "\"elf support was requested" "$LINENO" 5;
+ elif test "$format" = "macho" && test "$bfd_supports_macho" != "yes"; then
+ as_fn_error but BFD does not support it." "\"Mach-O support was requested" "$LINENO" 5;
+ fi
+
+ if test "$format" = "all"; then
+ FORMAT_SRCS="$all_binary_file_srcs"
+ # We don't break here in case the user requested Mach-O or ELF, but
+ # BFD is not configured to support it. If we were to break, we would
+ # silently drop the requested support instead of erroring out.
+ else
+ fmt=$(echo "$format _SRCS" | sed 's/ //')
+ FORMAT_SRCS="$FORMAT_SRCS \$($fmt)"
+ fi
+done
+
+
+
# Add any host-specific objects to GDB.
CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
# If building on ELF, look for lzma support for embedded compressed debug info.
-if test "$gdb_cv_var_elf" = yes; then
+if test "$gdb_cv_var_bfd_elf" = yes; then
# Check whether --with-lzma was given.
if test "${with_lzma+set}" = set; then :
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 226e27e..2ef53fe 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -191,6 +191,16 @@ AS_HELP_STRING([--enable-targets=TARGETS], [alternative target configurations]),
;;
esac])
+AC_ARG_ENABLE(binary_file_formats,
+ AS_HELP_STRING([--enable-binary-file-formats=FORMATS],
+ [enable support for selected file formats (default 'all')
+ available formats: coff, dbx, elf, macho, mips, xcoff, all]),
+[case "${enableval}" in
+ yes | "") AC_MSG_ERROR(enable-binary-file-formats option must specify file formats or 'all')
+ ;;
+ no) enable_binary_file_formats= ;;
+ *) enable_binary_file_formats=$enableval ;;
+esac], [enable_binary_file_formats=all])
# Check whether to support mdebug/ecoff debug information.
AC_ARG_ENABLE(gdb-mdebug-support,
@@ -240,10 +250,21 @@ TARGET_OBS=
all_targets=
HAVE_NATIVE_GCORE_TARGET=
+# File formats that will be enabled based on the selected
+# target(s). These are chosen because they are required to
+# compile one or more of the selected targets.
+target_formats=
+
+# If all targets were requested, this is all formats that should
+# accompany them. These are just the ones required for compilation
+# to succeed, not the formats suggested based on targets.
+all_target_formats="coff xcoff"
+
for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
do
if test "$targ_alias" = "all"; then
all_targets=true
+ target_formats=$all_target_formats
else
# Canonicalize the secondary target names.
result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -1952,32 +1973,87 @@ fi
# Note that WIN32APILIBS is set by GDB_AC_COMMON.
WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
+# Object files to be used when building with support for all file formats.
+# This should not have elf or macho, as support for those formats depends
+# on BFD enabling them as well.
+all_binary_file_srcs="\$(dbx_SRCS) \$(mips_SRCS) \$(coff_SRCS) \$(xcoff_SRCS)"
+
+bfd_supports_elf=no
# Add ELF support to GDB, but only if BFD includes ELF support.
-GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_elf,
+GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_bfd_elf,
[bfd_get_elf_phdr_upper_bound (NULL)], elf-bfd.h)
-if test "$gdb_cv_var_elf" = yes; then
- CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o \
- gcore-elf.o elf-none-tdep.o"
+if test "$gdb_cv_var_bfd_elf" = yes; then
+ CONFIG_OBS="$CONFIG_OBS gcore-elf.o elf-none-tdep.o"
AC_DEFINE(HAVE_ELF, 1,
[Define if ELF support should be included.])
# -ldl is provided by bfd/Makefile.am (LIBDL) <PLUGINS>.
if test "$plugins" = "yes"; then
AC_SEARCH_LIBS(dlopen, dl)
fi
+ bfd_supports_elf=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(elf_SRCS)"
fi
# Add macho support to GDB, but only if BFD includes it.
-GDB_AC_CHECK_BFD([for Mach-O support in BFD], gdb_cv_var_macho,
+bfd_supports_macho=no
+GDB_AC_CHECK_BFD([for Mach-O support in BFD], gdb_cv_var_bfd_macho,
[bfd_mach_o_lookup_command (NULL, 0, NULL)], mach-o.h)
-if test "$gdb_cv_var_macho" = yes; then
- CONFIG_OBS="$CONFIG_OBS machoread.o"
+if test "$gdb_cv_var_bfd_macho" = yes; then
+ bfd_supports_macho=yes
+ all_binary_file_srcs="$all_binary_file_srcs \$(macho_SRCS)"
+fi
+
+FORMAT_SRCS=
+
+if test "$enable_binary_file_formats" != "all"; then
+ # Formats that are required by some requested target(s).
+ # Warn users that they are added, so no one is surprised.
+ for req in $target_formats; do
+ case ,$enable_binary_file_formats, in
+ *,$req,*)
+ # Do nothing.
+ ;;
+ *)
+ AC_MSG_WARN("$req is required to support one or more requested targets. Adding it")
+ enable_binary_file_formats="${enable_binary_file_formats},$req"
+ ;;
+ esac
+ done
+
+ AC_DEFINE_UNQUOTED(SUPPORTED_BINARY_FILE_FORMATS, "$enable_binary_file_formats",
+ Which binary file formats were requested at configure time. )
fi
+enable_binary_file_formats=$(echo $enable_binary_file_formats | sed 's/,/ /g')
+
+# Go through all requested and required binary file formats to compile
+# GDB, and double check that we can compile them.
+for format in $enable_binary_file_formats
+do
+ if test "$format" = "elf" && test "$bfd_supports_elf" != "yes"; then
+ AC_MSG_ERROR("elf support was requested, but BFD does not support it.");
+ elif test "$format" = "macho" && test "$bfd_supports_macho" != "yes"; then
+ AC_MSG_ERROR("Mach-O support was requested, but BFD does not support it.");
+ fi
+
+ if test "$format" = "all"; then
+ FORMAT_SRCS="$all_binary_file_srcs"
+ # We don't break here in case the user requested Mach-O or ELF, but
+ # BFD is not configured to support it. If we were to break, we would
+ # silently drop the requested support instead of erroring out.
+ else
+ fmt=$(echo "$format _SRCS" | sed 's/ //')
+ FORMAT_SRCS="$FORMAT_SRCS \$($fmt)"
+ fi
+done
+
+AC_SUBST(FORMAT_SRCS)
+
# Add any host-specific objects to GDB.
CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
# If building on ELF, look for lzma support for embedded compressed debug info.
-if test "$gdb_cv_var_elf" = yes; then
+if test "$gdb_cv_var_bfd_elf" = yes; then
AC_ARG_WITH(lzma,
AS_HELP_STRING([--with-lzma], [support lzma compression (auto/yes/no)]),
[], [with_lzma=auto])
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 255c77e..332f5b7 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -505,7 +505,7 @@ powerpc-*-openbsd*)
;;
powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*)
# Target: PowerPC running AIX
- gdb_target_obs="rs6000-tdep.o rs6000-aix-tdep.o xcoffread.o \
+ gdb_target_obs="rs6000-tdep.o rs6000-aix-tdep.o \
ppc-sysv-tdep.o solib-aix.o \
ravenscar-thread.o ppc-ravenscar-thread.o"
;;
@@ -522,8 +522,8 @@ powerpc*-*-linux*)
powerpc-*-lynx*178)
# Target: PowerPC running Lynx178.
gdb_target_obs="rs6000-tdep.o rs6000-lynx178-tdep.o \
- xcoffread.o ppc-sysv-tdep.o \
- ravenscar-thread.o ppc-ravenscar-thread.o"
+ ppc-sysv-tdep.o ravenscar-thread.o \
+ ppc-ravenscar-thread.o"
;;
powerpc*-*-*)
# Target: PowerPC running eabi
@@ -835,3 +835,17 @@ for t in x ${gdb_target_obs}; do
gdb_have_gcore=true
fi
done
+
+# Decide which file formats are absolutely required based on
+# the requested targets. Warn later that they are added, in
+# case the user didn't manually request them, or all readers.
+# It's fine to add the same format multiple times since the
+# loop that reads the options to FORMAT_OBS will ensure that
+# they are only added once.
+for i in $gdb_target_obs; do
+ case "${i}" in
+ *"windows-tdep.o" ) target_formats="${target_formats} coff";;
+ "rs6000-aix-tdep.o" ) target_formats="${target_formats} xcoff";;
+ "rs6000-lynx178-tdep.o" ) target_formats="${target_formats} xcoff";;
+ esac
+done
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2bbaf14..d4a5a63 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -41277,6 +41277,14 @@ Configure @value{GDBN} for cross-debugging programs running on the
specified list of targets. The special value @samp{all} configures
@value{GDBN} for debugging programs running on any target it supports.
+@item --enable-binary-file-formats=@r{[}@var{format}@r{]}@dots{}
+@itemx --enable-binary-file-formats=all
+Configure @value{GDBN} to support certain binary file formats. If a
+format is the main (or only) file format for a given target, the
+configure script may add support to it anyway, and warn the user.
+If not given, all file formats that @value{GDBN} supports are compiled
+in.
+
@item --with-gdb-datadir=@var{path}
Set the @value{GDBN}-specific data directory. @value{GDBN} will look
here for certain supporting files or scripts. This defaults to the
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 97677c0..ddf4935 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -768,12 +768,12 @@ build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd,
return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info);
}
-/* This does all the work for dwarf2_read_debug_names, but putting it
- into a separate function makes some cleanup a bit simpler. */
+/* See read-debug-names.h. */
-static bool
-do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
+bool
+dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
{
+ scoped_remove_all_units remove_all_units (*per_objfile->per_bfd);
mapped_debug_names_reader map;
mapped_debug_names_reader dwz_map;
struct objfile *objfile = per_objfile->objfile;
@@ -850,17 +850,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
(per_objfile, std::move (map)));
auto idx = std::make_unique<debug_names_index> (std::move (cidn));
per_bfd->start_reading (std::move (idx));
+ remove_all_units.disable ();
return true;
}
-
-/* See read-debug-names.h. */
-
-bool
-dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
-{
- bool result = do_dwarf2_read_debug_names (per_objfile);
- if (!result)
- per_objfile->per_bfd->all_units.clear ();
- return result;
-}
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index 76317fe..fc7b654 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -1419,7 +1419,7 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
iter += 4;
- if (lo > hi)
+ if (lo >= hi)
{
complaint (_(".gdb_index address table has invalid range (%s - %s)"),
hex_string (lo), hex_string (hi));
@@ -1489,6 +1489,7 @@ dwarf2_read_gdb_index
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+ scoped_remove_all_units remove_all_units (*per_bfd);
gdb::array_view<const gdb_byte> main_index_contents
= get_gdb_index_contents (objfile, per_bfd);
@@ -1544,10 +1545,7 @@ dwarf2_read_gdb_index
an index. */
if (per_bfd->infos.size () > 1
|| per_bfd->types.size () > 1)
- {
- per_bfd->all_units.clear ();
- return false;
- }
+ return false;
dwarf2_section_info *section
= (per_bfd->types.size () == 1
@@ -1566,6 +1564,7 @@ dwarf2_read_gdb_index
set_main_name_from_gdb_index (per_objfile, map.get ());
per_bfd->index_table = std::move (map);
+ remove_all_units.disable ();
return true;
}
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index ec8d376..7bd0850 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -3679,6 +3679,10 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
void
finalize_all_units (dwarf2_per_bfd *per_bfd)
{
+ /* Sanity check. */
+ gdb_assert (per_bfd->all_units.size ()
+ == per_bfd->num_comp_units + per_bfd->num_type_units);
+
/* Ensure that the all_units vector is in the expected order for
dwarf2_find_containing_unit to be able to perform a binary search. */
std::sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
@@ -3694,6 +3698,7 @@ void
create_all_units (dwarf2_per_objfile *per_objfile)
{
gdb_assert (per_objfile->per_bfd->all_units.empty ());
+ scoped_remove_all_units remove_all_units (*per_objfile->per_bfd);
signatured_type_set sig_types;
@@ -3714,8 +3719,6 @@ create_all_units (dwarf2_per_objfile *per_objfile)
if (!dwz->types.empty ())
{
- per_objfile->per_bfd->all_units.clear ();
-
/* See enhancement PR symtab/30838. */
error (_(DWARF_ERROR_PREFIX
".debug_types section not supported in dwz file"));
@@ -3725,6 +3728,7 @@ create_all_units (dwarf2_per_objfile *per_objfile)
per_objfile->per_bfd->signatured_types = std::move (sig_types);
finalize_all_units (per_objfile->per_bfd);
+ remove_all_units.disable ();
}
/* Return the initial uleb128 in the die at INFO_PTR. */
@@ -4504,9 +4508,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
else
{
struct type *disr_type = nullptr;
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- disr_type = type->field (i).type ();
+ disr_type = field.type ();
if (disr_type->code () != TYPE_CODE_STRUCT)
{
@@ -4545,7 +4549,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
field *new_fields
= (struct field *) TYPE_ZALLOC (type, ((type->num_fields () + 1)
* sizeof (struct field)));
- memcpy (new_fields + 1, type->fields (),
+ memcpy (new_fields + 1, type->fields ().data (),
type->num_fields () * sizeof (struct field));
type->set_fields (new_fields);
type->set_num_fields (type->num_fields () + 1);
@@ -4559,13 +4563,12 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
variant name. For convenience we build a map here. */
struct type *enum_type = disr_field->type ();
gdb::unordered_map<std::string_view, ULONGEST> discriminant_map;
- for (int i = 0; i < enum_type->num_fields (); ++i)
+ for (const auto &field : enum_type->fields ())
{
- if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
+ if (field.loc_kind () == FIELD_LOC_KIND_ENUMVAL)
{
- const char *name
- = rust_last_path_segment (enum_type->field (i).name ());
- discriminant_map[name] = enum_type->field (i).loc_enumval ();
+ const char *name = rust_last_path_segment (field.name ());
+ discriminant_map[name] = field.loc_enumval ();
}
}
@@ -4601,7 +4604,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
if (sub_type->num_fields () > 0)
{
sub_type->set_num_fields (sub_type->num_fields () - 1);
- sub_type->set_fields (sub_type->fields () + 1);
+ sub_type->set_fields (sub_type->fields ().data () + 1);
}
type->field (i).set_name (variant_name);
sub_type->set_name
@@ -10629,7 +10632,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
smash_to_method_type (fnp->type, type,
this_type->target_type (),
this_type->fields (),
- this_type->num_fields (),
this_type->has_varargs ());
/* Handle static member functions.
@@ -10851,8 +10853,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
self_type = pfn_type->field (0).type ()->target_type ();
new_type = type_allocator (type).new_type ();
smash_to_method_type (new_type, self_type, pfn_type->target_type (),
- pfn_type->fields (), pfn_type->num_fields (),
- pfn_type->has_varargs ());
+ pfn_type->fields (), pfn_type->has_varargs ());
smash_to_methodptr_type (type, new_type);
}
@@ -12773,8 +12774,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
= type_allocator (cu->per_objfile->objfile, cu->lang ()).new_type ();
smash_to_method_type (new_type, domain, to_type->target_type (),
- to_type->fields (), to_type->num_fields (),
- to_type->has_varargs ());
+ to_type->fields (), to_type->has_varargs ());
type = lookup_methodptr_type (new_type);
}
else
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 4e3f8d7..74ec420 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -673,6 +673,36 @@ public:
std::string captured_debug_dir;
};
+/* Scoped object to remove all units from PER_BFD and clear other associated
+ fields in case of failure. */
+
+struct scoped_remove_all_units
+{
+ explicit scoped_remove_all_units (dwarf2_per_bfd &per_bfd)
+ : m_per_bfd (&per_bfd)
+ {}
+
+ DISABLE_COPY_AND_ASSIGN (scoped_remove_all_units);
+
+ ~scoped_remove_all_units ()
+ {
+ if (m_per_bfd == nullptr)
+ return;
+
+ m_per_bfd->all_units.clear ();
+ m_per_bfd->num_comp_units = 0;
+ m_per_bfd->num_type_units = 0;
+ }
+
+ /* Disable this object. Call this to keep the units of M_PER_BFD on the
+ success path. */
+ void disable () { m_per_bfd = nullptr; }
+
+private:
+ /* This is nullptr if the object is disabled. */
+ dwarf2_per_bfd *m_per_bfd;
+};
+
/* An iterator for all_units that is based on index. This
approach makes it possible to iterate over all_units safely,
when some caller in the loop may add new units. */
diff --git a/gdb/eval.c b/gdb/eval.c
index 539b700..6227a26 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -492,7 +492,7 @@ fake_method::fake_method (type_instance_flags flags,
fake_method::~fake_method ()
{
- xfree (m_type.fields ());
+ xfree (m_type.fields ().data ());
}
namespace expr
diff --git a/gdb/event-top.c b/gdb/event-top.c
index f96982a..3138e8c 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -1180,6 +1180,9 @@ quit (void)
throw_forced_quit ("SIGTERM");
}
+ /* Pressing ^C cancels i-search. Tell readline that a ^C happened. */
+ rl_callback_sigcleanup ();
+
#ifdef __MSDOS__
/* No steenking SIGINT will ever be coming our way when the
program is resumed. Don't lie. */
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
index 7d0cdc0..e96d27c 100644
--- a/gdb/f-typeprint.c
+++ b/gdb/f-typeprint.c
@@ -299,8 +299,6 @@ void
f_language::f_type_print_base (struct type *type, struct ui_file *stream,
int show, int level) const
{
- int index;
-
QUIT;
stream->wrap_here (4);
@@ -423,14 +421,13 @@ f_language::f_type_print_base (struct type *type, struct ui_file *stream,
if (show > 0)
{
gdb_puts ("\n", stream);
- for (index = 0; index < type->num_fields (); index++)
+ for (const auto &field : type->fields ())
{
- f_type_print_base (type->field (index).type (), stream,
- show - 1, level + 4);
+ f_type_print_base (field.type (), stream, show - 1, level + 4);
gdb_puts (" :: ", stream);
- fputs_styled (type->field (index).name (),
+ fputs_styled (field.name (),
variable_name_style.style (), stream);
- f_type_print_varspec_suffix (type->field (index).type (),
+ f_type_print_varspec_suffix (field.type (),
stream, show - 1, 0, 0, 0, false);
gdb_puts ("\n", stream);
}
diff --git a/gdb/frame.c b/gdb/frame.c
index fc4cbca..50223f4 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2663,15 +2663,14 @@ get_prev_frame (const frame_info_ptr &this_frame)
{
FRAME_SCOPED_DEBUG_ENTER_EXIT;
- CORE_ADDR frame_pc;
- int frame_pc_p;
+ std::optional<CORE_ADDR> frame_pc;
/* There is always a frame. If this assertion fails, suspect that
something should be calling get_selected_frame() or
get_current_frame(). */
gdb_assert (this_frame != NULL);
- frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
+ frame_pc = get_frame_pc_if_available (this_frame);
/* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
sense to stop unwinding at a dummy frame. One place where a dummy
@@ -2686,7 +2685,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
&& !user_set_backtrace_options.backtrace_past_main
- && frame_pc_p
+ && frame_pc.has_value ()
&& inside_main_func (this_frame))
/* Don't unwind past main(). Note, this is done _before_ the
frame has been marked as previously unwound. That way if the
@@ -2733,7 +2732,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
&& !user_set_backtrace_options.backtrace_past_entry
- && frame_pc_p
+ && frame_pc.has_value ()
&& inside_entry_func (this_frame))
{
frame_debug_got_null_frame (this_frame, "inside entry func");
@@ -2747,7 +2746,7 @@ get_prev_frame (const frame_info_ptr &this_frame)
&& (get_frame_type (this_frame) == NORMAL_FRAME
|| get_frame_type (this_frame) == INLINE_FRAME)
&& get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME
- && frame_pc_p && frame_pc == 0)
+ && frame_pc.has_value () && *frame_pc == 0)
{
frame_debug_got_null_frame (this_frame, "zero PC");
return NULL;
@@ -2763,25 +2762,24 @@ get_frame_pc (const frame_info_ptr &frame)
return frame_unwind_pc (frame_info_ptr (frame->next));
}
-bool
-get_frame_pc_if_available (const frame_info_ptr &frame, CORE_ADDR *pc)
+std::optional<CORE_ADDR>
+get_frame_pc_if_available (const frame_info_ptr &frame)
{
+ std::optional<CORE_ADDR> pc;
gdb_assert (frame->next != NULL);
try
{
- *pc = frame_unwind_pc (frame_info_ptr (frame->next));
+ pc = frame_unwind_pc (frame_info_ptr (frame->next));
}
catch (const gdb_exception_error &ex)
{
- if (ex.error == NOT_AVAILABLE_ERROR)
- return false;
- else
+ if (ex.error != NOT_AVAILABLE_ERROR)
throw;
}
- return true;
+ return pc;
}
/* Return an address that falls within THIS_FRAME's code block. */
@@ -2870,7 +2868,7 @@ find_frame_sal (const frame_info_ptr &frame)
{
frame_info_ptr next_frame;
int notcurrent;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
if (frame_inlined_callees (frame) > 0)
{
@@ -2914,11 +2912,11 @@ find_frame_sal (const frame_info_ptr &frame)
PC and such a PC indicates the current (rather than next)
instruction/line, consequently, for such cases, want to get the
line containing fi->pc. */
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
return {};
- notcurrent = (pc != get_frame_address_in_block (frame));
- return find_pc_line (pc, notcurrent);
+ notcurrent = (*pc != get_frame_address_in_block (frame));
+ return find_pc_line (*pc, notcurrent);
}
/* Per "frame.h", return the ``address'' of the frame. Code should
diff --git a/gdb/frame.h b/gdb/frame.h
index b240662..99a7983 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -504,7 +504,8 @@ extern CORE_ADDR get_frame_pc (const frame_info_ptr &);
/* Same as get_frame_pc, but return a boolean indication of whether
the PC is actually available, instead of throwing an error. */
-extern bool get_frame_pc_if_available (const frame_info_ptr &frame, CORE_ADDR *pc);
+extern std::optional<CORE_ADDR> get_frame_pc_if_available
+ (const frame_info_ptr &frame);
/* An address (not necessarily aligned to an instruction boundary)
that falls within THIS frame's code block.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 14a903b..24e6d0b 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1080,10 +1080,10 @@ get_discrete_low_bound (struct type *type)
entries. */
LONGEST low = type->field (0).loc_enumval ();
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () < low)
- low = type->field (i).loc_enumval ();
+ if (field.loc_enumval () < low)
+ low = field.loc_enumval ();
}
return low;
@@ -1147,10 +1147,10 @@ get_discrete_high_bound (struct type *type)
entries. */
LONGEST high = type->field (0).loc_enumval ();
- for (int i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- if (type->field (i).loc_enumval () > high)
- high = type->field (i).loc_enumval ();
+ if (field.loc_enumval () > high)
+ high = field.loc_enumval ();
}
return high;
@@ -1602,15 +1602,15 @@ smash_to_methodptr_type (struct type *type, struct type *to_type)
void
smash_to_method_type (struct type *type, struct type *self_type,
- struct type *to_type, struct field *args,
- int nargs, int varargs)
+ struct type *to_type, gdb::array_view<struct field> args,
+ int varargs)
{
smash_type (type);
type->set_code (TYPE_CODE_METHOD);
type->set_target_type (to_type);
set_type_self_type (type, self_type);
- type->set_fields (args);
- type->set_num_fields (nargs);
+ type->set_fields (args.data ());
+ type->set_num_fields (args.size ());
if (varargs)
type->set_has_varargs (true);
@@ -2494,23 +2494,22 @@ resolve_dynamic_union (struct type *type,
const frame_info_ptr &frame)
{
struct type *resolved_type;
- int i;
unsigned int max_len = 0;
gdb_assert (type->code () == TYPE_CODE_UNION);
resolved_type = copy_type (type);
resolved_type->copy_fields (type);
- for (i = 0; i < resolved_type->num_fields (); ++i)
+ for (auto &field : resolved_type->fields ())
{
struct type *t;
- if (type->field (i).is_static ())
+ if (field.is_static ())
continue;
- t = resolve_dynamic_type_internal (resolved_type->field (i).type (),
- addr_stack, frame, false);
- resolved_type->field (i).set_type (t);
+ t = resolve_dynamic_type_internal (field.type (), addr_stack,
+ frame, false);
+ field.set_type (t);
struct type *real_type = check_typedef (t);
if (real_type->length () > max_len)
@@ -2791,7 +2790,6 @@ resolve_dynamic_struct (struct type *type,
const frame_info_ptr &frame)
{
struct type *resolved_type;
- int i;
unsigned resolved_type_bit_length = 0;
gdb_assert (type->code () == TYPE_CODE_STRUCT);
@@ -2812,22 +2810,21 @@ resolve_dynamic_struct (struct type *type,
resolved_type->copy_fields (type);
}
- for (i = 0; i < resolved_type->num_fields (); ++i)
+ for (auto &field : resolved_type->fields ())
{
unsigned new_bit_length;
- if (resolved_type->field (i).is_static ())
+ if (field.is_static ())
continue;
- resolve_dynamic_field (resolved_type->field (i), addr_stack, frame);
+ resolve_dynamic_field (field, addr_stack, frame);
- new_bit_length = resolved_type->field (i).loc_bitpos ();
- if (resolved_type->field (i).bitsize () != 0)
- new_bit_length += resolved_type->field (i).bitsize ();
+ new_bit_length = field.loc_bitpos ();
+ if (field.bitsize () != 0)
+ new_bit_length += field.bitsize ();
else
{
- struct type *real_type
- = check_typedef (resolved_type->field (i).type ());
+ struct type *real_type = check_typedef (field.type ());
new_bit_length += (real_type->length () * TARGET_CHAR_BIT);
}
@@ -3394,7 +3391,8 @@ check_stub_method (struct type *type, int method_id, int signature_id)
/* MTYPE may currently be a function (TYPE_CODE_FUNC).
We want a method (TYPE_CODE_METHOD). */
smash_to_method_type (mtype, type, mtype->target_type (),
- argtypes, argcount, p[-2] == '.');
+ gdb::make_array_view (argtypes, argcount),
+ p[-2] == '.');
mtype->set_is_stub (false);
TYPE_FN_FIELD_STUB (f, signature_id) = 0;
}
@@ -3698,12 +3696,12 @@ type_align (struct type *type)
case TYPE_CODE_UNION:
{
int number_of_non_static_fields = 0;
- for (unsigned i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (!type->field (i).is_static ())
+ if (!field.is_static ())
{
number_of_non_static_fields++;
- ULONGEST f_align = type_align (type->field (i).type ());
+ ULONGEST f_align = type_align (field.type ());
if (f_align == 0)
{
/* Don't pretend we know something we don't. */
@@ -5038,19 +5036,14 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value)
situation. */
static void
-print_args (struct field *args, int nargs, int spaces)
+print_args (gdb::array_view<struct field> args, int spaces)
{
- if (args != NULL)
+ for (int i = 0; i < args.size (); i++)
{
- int i;
-
- for (i = 0; i < nargs; i++)
- {
- gdb_printf
- ("%*s[%d] name '%s'\n", spaces, "", i,
- args[i].name () != NULL ? args[i].name () : "<NULL>");
- recursive_dump_type (args[i].type (), spaces + 2);
- }
+ gdb_printf
+ ("%*s[%d] name '%s'\n", spaces, "", i,
+ args[i].name () != NULL ? args[i].name () : "<NULL>");
+ recursive_dump_type (args[i].type (), spaces + 2);
}
}
@@ -5091,9 +5084,8 @@ dump_fn_fieldlists (struct type *type, int spaces)
gdb_printf
("%*sargs %s\n", spaces + 8, "",
- host_address_to_string (TYPE_FN_FIELD_ARGS (f, overload_idx)));
+ host_address_to_string (TYPE_FN_FIELD_ARGS (f, overload_idx).data ()));
print_args (TYPE_FN_FIELD_ARGS (f, overload_idx),
- TYPE_FN_FIELD_TYPE (f, overload_idx)->num_fields (),
spaces + 8 + 2);
gdb_printf
("%*sfcontext %s\n", spaces + 8, "",
@@ -5375,7 +5367,7 @@ recursive_dump_type (struct type *type, int spaces)
}
gdb_printf ("\n");
}
- gdb_printf ("%s\n", host_address_to_string (type->fields ()));
+ gdb_printf ("%s\n", host_address_to_string (type->fields ().data ()));
for (idx = 0; idx < type->num_fields (); idx++)
{
field &fld = type->field (idx);
@@ -5756,7 +5748,7 @@ append_composite_type_field_raw (struct type *t, const char *name,
struct field *f;
t->set_num_fields (t->num_fields () + 1);
- t->set_fields (XRESIZEVEC (struct field, t->fields (),
+ t->set_fields (XRESIZEVEC (struct field, t->fields ().data (),
t->num_fields ()));
f = &t->field (t->num_fields () - 1);
memset (f, 0, sizeof f[0]);
@@ -5907,7 +5899,7 @@ type::alloc_fields (unsigned int nfields, bool init)
return;
}
- size_t size = nfields * sizeof (*this->fields ());
+ size_t size = nfields * sizeof (struct field);
struct field *fields
= (struct field *) (init
? TYPE_ZALLOC (this, size)
@@ -5926,8 +5918,8 @@ type::copy_fields (struct type *src)
if (nfields == 0)
return;
- size_t size = nfields * sizeof (*this->fields ());
- memcpy (this->fields (), src->fields (), size);
+ size_t size = nfields * sizeof (struct field);
+ memcpy (this->fields ().data (), src->fields ().data (), size);
}
/* See gdbtypes.h. */
@@ -5940,8 +5932,8 @@ type::copy_fields (std::vector<struct field> &src)
if (nfields == 0)
return;
- size_t size = nfields * sizeof (*this->fields ());
- memcpy (this->fields (), src.data (), size);
+ size_t size = nfields * sizeof (struct field);
+ memcpy (this->fields ().data (), src.data (), size);
}
/* See gdbtypes.h. */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 9e2efe9..75c77b3 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1080,12 +1080,6 @@ struct type
this->main_type->m_nfields = num_fields;
}
- /* Get the fields array of this type. */
- struct field *fields () const
- {
- return this->main_type->flds_bnds.fields;
- }
-
/* Get the field at index IDX. */
struct field &field (int idx) const
{
@@ -1093,6 +1087,13 @@ struct type
return this->fields ()[idx];
}
+ /* Return an array view of the fields. */
+ gdb::array_view<struct field> fields () const
+ {
+ return gdb::make_array_view (this->main_type->flds_bnds.fields,
+ num_fields ());
+ }
+
/* Set the fields array of this type. */
void set_fields (struct field *fields)
{
@@ -2470,8 +2471,9 @@ extern struct type *lookup_memberptr_type (struct type *, struct type *);
extern struct type *lookup_methodptr_type (struct type *);
extern void smash_to_method_type (struct type *type, struct type *self_type,
- struct type *to_type, struct field *args,
- int nargs, int varargs);
+ struct type *to_type,
+ gdb::array_view<struct field> args,
+ int varargs);
extern void smash_to_memberptr_type (struct type *, struct type *,
struct type *);
diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
index 5114579..13676ce 100644
--- a/gdb/guile/scm-type.c
+++ b/gdb/guile/scm-type.c
@@ -510,7 +510,7 @@ tyscm_field_smob_to_field (field_smob *f_smob)
struct type *type = tyscm_field_smob_containing_type (f_smob);
/* This should be non-NULL by construction. */
- gdb_assert (type->fields () != NULL);
+ gdb_assert (type->fields ().data () != nullptr);
return &type->field (f_smob->field_num);
}
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index f97c98e..21a5a28 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8977,41 +8977,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS;
tdep->register_names = i386_register_names;
- /* No upper YMM registers. */
- tdep->ymmh_register_names = NULL;
- tdep->ymm0h_regnum = -1;
-
- /* No upper ZMM registers. */
- tdep->zmmh_register_names = NULL;
- tdep->zmm0h_regnum = -1;
-
- /* No high XMM registers. */
- tdep->xmm_avx512_register_names = NULL;
- tdep->xmm16_regnum = -1;
-
- /* No upper YMM16-31 registers. */
- tdep->ymm16h_register_names = NULL;
- tdep->ymm16h_regnum = -1;
-
tdep->num_byte_regs = 8;
tdep->num_word_regs = 8;
tdep->num_dword_regs = 0;
tdep->num_mmx_regs = 8;
tdep->num_ymm_regs = 0;
- /* No AVX512 registers. */
- tdep->k0_regnum = -1;
- tdep->num_zmm_regs = 0;
- tdep->num_ymm_avx512_regs = 0;
- tdep->num_xmm_avx512_regs = 0;
-
- /* No PKEYS registers */
- tdep->pkru_regnum = -1;
- tdep->num_pkeys_regs = 0;
-
- /* No segment base registers. */
- tdep->fsbase_regnum = -1;
-
tdesc_arch_data_up tdesc_data = tdesc_data_alloc ();
set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index e849b33..e4895b1 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -69,56 +69,57 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
size_t sizeof_fpregset = 0;
/* Register number for %st(0). The register numbers for the other
- registers follow from this one. Set this to -1 to indicate the
- absence of an FPU. */
- int st0_regnum = 0;
+ registers follow from this one. Set this to a value >= 0 if FPU is
+ present. */
+ int st0_regnum = -1;
/* Number of MMX registers. */
int num_mmx_regs = 0;
- /* Register number for %mm0. Set this to -1 to indicate the absence
- of MMX support. */
- int mm0_regnum = 0;
+ /* Register number for %mm0. Set this to a value >= 0 if MMX is
+ supported. */
+ int mm0_regnum = -1;
/* Number of pseudo YMM registers. */
int num_ymm_regs = 0;
- /* Register number for %ymm0. Set this to -1 to indicate the absence
- of pseudo YMM register support. */
- int ymm0_regnum = 0;
+ /* Register number for %ymm0. Set this to a value >= 0 if pseudo YMM
+ registers are supported. */
+ int ymm0_regnum = -1;
/* Number of AVX512 OpMask registers (K-registers) */
int num_k_regs = 0;
- /* Register number for %k0. Set this to -1 to indicate the absence
- of AVX512 OpMask register support. */
- int k0_regnum = 0;
+ /* Register number for %k0. Set this to a value >= 0 if AVX512 OpMask
+ is supported. */
+ int k0_regnum = -1;
/* Number of pseudo ZMM registers ($zmm0-$zmm31). */
int num_zmm_regs = 0;
- /* Register number for %zmm0. Set this to -1 to indicate the absence
- of pseudo ZMM register support. */
- int zmm0_regnum = 0;
+ /* Register number for %zmm0. Set this to a value >= 0 if pseudo ZMM
+ registers are supported. */
+ int zmm0_regnum = -1;
/* Number of byte registers. */
int num_byte_regs = 0;
- /* Register pseudo number for %al. */
- int al_regnum = 0;
+ /* Register pseudo number for %al. If supported, set this to a
+ value >= 0. */
+ int al_regnum = -1;
/* Number of pseudo word registers. */
int num_word_regs = 0;
- /* Register number for %ax. */
- int ax_regnum = 0;
+ /* Register number for %ax. If supported, set this to a value >= 0. */
+ int ax_regnum = -1;
/* Number of pseudo dword registers. */
int num_dword_regs = 0;
- /* Register number for %eax. Set this to -1 to indicate the absence
- of pseudo dword register support. */
- int eax_regnum = 0;
+ /* Register number for %eax. Set this to a value >= 0 if pseudo dword
+ registers are supported. */
+ int eax_regnum = -1;
/* Number of core registers. */
int num_core_regs = 0;
@@ -129,14 +130,16 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Number of SSE registers added in AVX512. */
int num_xmm_avx512_regs = 0;
- /* Register number of XMM16, the first XMM register added in AVX512. */
- int xmm16_regnum = 0;
+ /* Register number of XMM16, the first XMM register added in AVX512.
+ Set this to a value >= 0 if XMM registers are supported. */
+ int xmm16_regnum = -1;
/* Number of YMM registers added in AVX512. */
int num_ymm_avx512_regs = 0;
- /* Register number of YMM16, the first YMM register added in AVX512. */
- int ymm16_regnum = 0;
+ /* Register number of YMM16, the first YMM register added in AVX512.
+ Set this to a value >= 0 if YMM registers are supported. */
+ int ymm16_regnum = -1;
/* Bits of the extended control register 0 (the XFEATURE_ENABLED_MASK
register), excluding the x87 bit, which are supported by this GDB. */
@@ -152,23 +155,23 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Register names. */
const char * const *register_names = nullptr;
- /* Register number for %ymm0h. Set this to -1 to indicate the absence
- of upper YMM register support. */
- int ymm0h_regnum = 0;
+ /* Register number for %ymm0h. Set this to a value >= 0 if they are
+ supported. */
+ int ymm0h_regnum = -1;
/* Upper YMM register names. Only used for tdesc_numbered_register. */
const char * const *ymmh_register_names = nullptr;
- /* Register number for %ymm16h. Set this to -1 to indicate the absence
- of support for YMM16-31. */
- int ymm16h_regnum = 0;
+ /* Register number for %ymm16h. Set this to a value >= 0 if they are
+ supported. */
+ int ymm16h_regnum = -1;
/* YMM16-31 register names. Only used for tdesc_numbered_register. */
const char * const *ymm16h_register_names = nullptr;
- /* Register number for %zmm0h. Set this to -1 to indicate the absence
- of ZMM_HI256 register support. */
- int zmm0h_regnum = 0;
+ /* Register number for %zmm0h. Set this to a value >= 0 if ZMM_HI256
+ registers are supported. */
+ int zmm0h_regnum = -1;
/* OpMask register names. */
const char * const *k_register_names = nullptr;
@@ -185,15 +188,16 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base
/* Number of PKEYS registers. */
int num_pkeys_regs = 0;
- /* Register number for PKRU register. */
- int pkru_regnum = 0;
+ /* Register number for PKRU register. If supported, set this to a value
+ >= 0. */
+ int pkru_regnum = -1;
/* PKEYS register names. */
const char * const *pkeys_register_names = nullptr;
- /* Register number for %fsbase. Set this to -1 to indicate the
- absence of segment base registers. */
- int fsbase_regnum = 0;
+ /* Register number for %fsbase. If supported, set this to a value
+ >= 0. */
+ int fsbase_regnum = -1;
/* Target description. */
const struct target_desc *tdesc = nullptr;
diff --git a/gdb/macroscope.c b/gdb/macroscope.c
index 7aa0784..a8b78c9 100644
--- a/gdb/macroscope.c
+++ b/gdb/macroscope.c
@@ -97,12 +97,12 @@ default_macro_scope ()
{
struct symtab_and_line sal;
frame_info_ptr frame;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
/* If there's a selected frame, use its PC. */
frame = deprecated_safe_get_selected_frame ();
- if (frame && get_frame_pc_if_available (frame, &pc))
- sal = find_pc_line (pc, 0);
+ if (frame && (pc = get_frame_pc_if_available (frame)))
+ sal = find_pc_line (*pc, 0);
/* Fall back to the current listing position. */
else
diff --git a/gdb/main.c b/gdb/main.c
index bb8ddc3..8c5ef99 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -1330,10 +1330,8 @@ captured_main_1 (struct captured_main_args *context)
}
static void
-captured_main (void *data)
+captured_main (captured_main_args *context)
{
- struct captured_main_args *context = (struct captured_main_args *) data;
-
captured_main_1 (context);
/* NOTE: cagney/1999-11-07: There is probably no reason for not
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 5bb15c2..b9302c5 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -1034,7 +1034,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
t->set_code (type_code);
t->set_length (sh->value);
t->alloc_fields (nfields);
- f = t->fields();
+ f = t->fields ().data ();
if (type_code == TYPE_CODE_ENUM)
{
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
index 6d8dce8..8c0854b 100644
--- a/gdb/nat/aarch64-hw-point.c
+++ b/gdb/nat/aarch64-hw-point.c
@@ -710,10 +710,8 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
itself. For instance, the access size of an stp instruction is 16.
So, if we use stp to store to address p, and set a watchpoint on
address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
- for this situation introduces the possibility of false positives,
- so we only do this for hw_write watchpoints. */
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
+ RK3399 SOC). But it also can be p (observed on M1 SOC). */
+ const CORE_ADDR max_access_size = 16;
const CORE_ADDR addr_watch_base = addr_watch_aligned -
(max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
if (!(addr_trap >= addr_watch_base
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index cae5aa6..f872f73 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -2060,10 +2060,12 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
}
/* Small character arrays are returned, right justified, in r3. */
- if (valtype->code () == TYPE_CODE_ARRAY
+ if (tdep->elf_abi == POWERPC_ELF_V1
+ && valtype->code () == TYPE_CODE_ARRAY
&& !valtype->is_vector ()
&& valtype->length () <= 8
- && valtype->target_type ()->code () == TYPE_CODE_INT
+ && (valtype->target_type ()->code () == TYPE_CODE_INT
+ || valtype->target_type ()->code () == TYPE_CODE_CHAR)
&& valtype->target_type ()->length () == 1)
{
int regnum = tdep->ppc_gp0_regnum + 3;
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 19fbc20..c6d7075 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -753,10 +753,10 @@ pc_prefix (CORE_ADDR addr)
if (has_stack_frames ())
{
frame_info_ptr frame;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
frame = get_selected_frame (NULL);
- if (get_frame_pc_if_available (frame, &pc) && pc == addr)
+ if ((pc = get_frame_pc_if_available (frame)) && *pc == addr)
return "=> ";
}
return " ";
@@ -1290,7 +1290,9 @@ should_validate_memtags (gdbarch *gdbarch, struct value *value)
return false;
/* We do. Check whether it includes any tags. */
- return target_is_address_tagged (gdbarch, value_as_address (value));
+ struct type *val_type = value->type ();
+ const gdb_byte *data = value->contents ().data ();
+ return target_is_address_tagged (gdbarch, unpack_pointer (val_type, data));
}
/* Helper for parsing arguments for print_command_1. */
diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py
index 8a13c51..1b54fe7 100644
--- a/gdb/python/lib/gdb/dap/varref.py
+++ b/gdb/python/lib/gdb/dap/varref.py
@@ -146,6 +146,10 @@ class BaseReference(ABC):
if self._children is None:
self._children = [None] * self.child_count()
for idx in range(start, start + count):
+ if idx >= len(self._children):
+ raise DAPException(
+ f"requested child {idx} outside range of variable {self._ref}"
+ )
if self._children[idx] is None:
(name, value) = self.fetch_one_child(idx)
name = self._compute_name(name)
diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index cba27d2..cda033f 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -415,11 +415,17 @@ def make_visualizer(value):
result = NoOpArrayPrinter(ty, value)
elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
result = NoOpStructPrinter(ty, value)
- elif ty.code in (
- gdb.TYPE_CODE_PTR,
- gdb.TYPE_CODE_REF,
- gdb.TYPE_CODE_RVALUE_REF,
+ elif (
+ ty.code
+ in (
+ gdb.TYPE_CODE_PTR,
+ gdb.TYPE_CODE_REF,
+ gdb.TYPE_CODE_RVALUE_REF,
+ )
+ and ty.target().code != gdb.TYPE_CODE_VOID
):
+ # Note we avoid "void *" here because those pointers can't
+ # be dereferenced without a cast.
result = NoOpPointerReferencePrinter(value)
else:
result = NoOpScalarPrinter(value)
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 0ea629f..70e1684 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -175,7 +175,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
struct frame_id frame_id;
PyObject *internal = NULL;
int internal_bp = 0;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
&frame_obj, &internal))
@@ -249,9 +249,9 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
try
{
- if (get_frame_pc_if_available (frame, &pc))
+ if ((pc = get_frame_pc_if_available (frame)))
{
- struct symbol *function = find_pc_function (pc);
+ struct symbol *function = find_pc_function (*pc);
if (function != nullptr)
{
struct type *ret_type =
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index c546aa7..10ae636 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1312,10 +1312,9 @@ static PyObject *
typy_has_key (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
- const char *field;
- int i;
+ const char *field_name;
- if (!PyArg_ParseTuple (args, "s", &field))
+ if (!PyArg_ParseTuple (args, "s", &field_name))
return NULL;
/* We want just fields of this type, not of base types, so instead of
@@ -1326,11 +1325,11 @@ typy_has_key (PyObject *self, PyObject *args)
if (type == NULL)
return NULL;
- for (i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- const char *t_field_name = type->field (i).name ();
+ const char *t_field_name = field.name ();
- if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
+ if (t_field_name && (strcmp_iw (t_field_name, field_name) == 0))
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 3957413..3605552 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -126,15 +126,15 @@ rust_underscore_fields (struct type *type)
if (type->code () != TYPE_CODE_STRUCT)
return false;
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (!type->field (i).is_static ())
+ if (!field.is_static ())
{
char buf[20];
xsnprintf (buf, sizeof (buf), "%d", field_number);
- const char *field_name = type->field (i).name ();
+ const char *field_name = field.name ();
if (startswith (field_name, "__"))
field_name += 2;
if (strcmp (buf, field_name) != 0)
@@ -376,11 +376,11 @@ rust_array_like_element_type (struct type *type)
{
/* Caller must check this. */
gdb_assert (rust_slice_type_p (type));
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- if (strcmp (type->field (i).name (), "data_ptr") == 0)
+ if (strcmp (field.name (), "data_ptr") == 0)
{
- struct type *base_type = type->field (i).type ()->target_type ();
+ struct type *base_type = field.type ()->target_type ();
if (rewrite_slice_type (base_type, nullptr, 0, nullptr))
return nullptr;
return base_type;
@@ -1017,9 +1017,9 @@ rust_internal_print_type (struct type *type, const char *varstring,
}
gdb_puts ("{\n", stream);
- for (int i = 0; i < type->num_fields (); ++i)
+ for (const auto &field : type->fields ())
{
- const char *name = type->field (i).name ();
+ const char *name = field.name ();
QUIT;
diff --git a/gdb/source.c b/gdb/source.c
index 0fd370b..8cb5c36 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1312,14 +1312,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
int nlines = stopline - line;
struct ui_out *uiout = current_uiout;
- /* Regardless of whether we can open the file, set current_source_symtab. */
+ /* Regardless of whether we can open the file, we'll want to set
+ current_source_symtab, but not if throw an error, or return without
+ printing any source lines. */
current_source_location *loc
= get_source_location (current_program_space);
- loc->set (s, line);
- first_line_listed = line;
- last_line_listed = line;
-
/* If printing of source lines is disabled, just print file and line
number. */
if (uiout->test_flags (ui_source_list) && source_open)
@@ -1380,6 +1378,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->text ("\n");
}
+ loc->set (s, line);
+ first_line_listed = line;
+ last_line_listed = line;
+
return;
}
@@ -1399,12 +1401,9 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
}
const char *iter = lines.c_str ();
- int new_lineno = loc->line ();
- while (nlines-- > 0 && *iter != '\0')
+ int new_lineno = line;
+ for (; nlines-- > 0 && *iter != '\0'; ++new_lineno)
{
- char buf[20];
-
- last_line_listed = loc->line ();
if (flags & PRINT_SOURCE_LINES_FILENAME)
{
uiout->message ("%ps",
@@ -1415,7 +1414,6 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->message ("%ps\t", styled_string (line_number_style.style (),
pulongest (new_lineno)));
- ++new_lineno;
while (*iter != '\0')
{
@@ -1457,6 +1455,8 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
}
else if (*iter > 0 && *iter < 040)
{
+ char buf[20];
+
xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100);
uiout->text (buf);
++iter;
@@ -1470,7 +1470,11 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
uiout->text ("\n");
}
- loc->set (loc->symtab (), new_lineno);
+ /* As NEW_LINENO was incremented after displaying the last source line,
+ the last line shown was the one before NEW_LINENO. */
+ first_line_listed = line;
+ last_line_listed = new_lineno - 1;
+ loc->set (s, new_lineno);
}
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index 6ee61e0..74d0175 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -4431,8 +4431,9 @@ again:
if (args == NULL)
return error_type (pp, objfile);
type = dbx_alloc_type (typenums, objfile);
- smash_to_method_type (type, domain, return_type, args,
- nargs, varargs);
+ smash_to_method_type (type, domain, return_type,
+ gdb::make_array_view (args, nargs),
+ varargs);
}
break;
diff --git a/gdb/stack.c b/gdb/stack.c
index e633566..e3fa1f4 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1165,10 +1165,10 @@ do_print_frame_info (struct ui_out *uiout, const frame_print_options &fp_opts,
if (set_current_sal)
{
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
- if (get_frame_pc_if_available (frame, &pc))
- last_displayed_symtab_info.set (sal.pspace, pc, sal.symtab, sal.line);
+ if ((pc = get_frame_pc_if_available (frame)))
+ last_displayed_symtab_info.set (sal.pspace, *pc, sal.symtab, sal.line);
else
last_displayed_symtab_info.invalidate ();
}
@@ -1325,16 +1325,15 @@ print_frame (struct ui_out *uiout,
enum language funlang = language_unknown;
struct value_print_options opts;
struct symbol *func;
- CORE_ADDR pc = 0;
- int pc_p;
+ std::optional <CORE_ADDR> pc;
- pc_p = get_frame_pc_if_available (frame, &pc);
+ pc = get_frame_pc_if_available (frame);
gdb::unique_xmalloc_ptr<char> funname
= find_frame_funname (frame, &funlang, &func);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- gdbarch, pc);
+ gdbarch, pc.value_or (0));
{
ui_out_emit_tuple tuple_emitter (uiout, "frame");
@@ -1352,8 +1351,8 @@ print_frame (struct ui_out *uiout,
|| print_what == LOC_AND_ADDRESS)
{
annotate_frame_address ();
- if (pc_p)
- print_pc (uiout, gdbarch, frame, pc);
+ if (pc.has_value ())
+ print_pc (uiout, gdbarch, frame, *pc);
else
uiout->field_string ("addr", "<unavailable>",
metadata_style.style ());
@@ -1422,7 +1421,7 @@ print_frame (struct ui_out *uiout,
}
if (print_what != SHORT_LOCATION
- && pc_p && (funname == NULL || sal.symtab == NULL))
+ && pc.has_value () && (funname == NULL || sal.symtab == NULL))
{
const char *lib
= solib_name_from_address (get_frame_program_space (frame),
@@ -1481,8 +1480,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
enum language funlang = language_unknown;
const char *pc_regname;
struct gdbarch *gdbarch;
- CORE_ADDR frame_pc;
- int frame_pc_p;
+ std::optional<CORE_ADDR> frame_pc;
/* Initialize it to avoid "may be used uninitialized" warning. */
CORE_ADDR caller_pc = 0;
int caller_pc_p = 0;
@@ -1503,7 +1501,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
get_frame_pc(). */
pc_regname = "pc";
- frame_pc_p = get_frame_pc_if_available (fi, &frame_pc);
+ frame_pc = get_frame_pc_if_available (fi);
func = get_frame_function (fi);
symtab_and_line sal = find_frame_sal (fi);
s = sal.symtab;
@@ -1525,9 +1523,9 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
funname = func_only.get ();
}
}
- else if (frame_pc_p)
+ else if (frame_pc.has_value ())
{
- bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (frame_pc);
+ bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (*frame_pc);
if (msymbol.minsym != NULL)
{
funname = msymbol.minsym->print_name ();
@@ -1548,7 +1546,7 @@ info_frame_command_core (const frame_info_ptr &fi, bool selected_frame_p)
gdb_puts (paddress (gdbarch, get_frame_base (fi)));
gdb_printf (":\n");
gdb_printf (" %s = ", pc_regname);
- if (frame_pc_p)
+ if (frame_pc.has_value ())
gdb_puts (paddress (gdbarch, get_frame_pc (fi)));
else
fputs_styled ("<unavailable>", metadata_style.style (), gdb_stdout);
@@ -2337,9 +2335,9 @@ print_frame_local_vars (const frame_info_ptr &frame,
{
struct print_variable_and_value_data cb_data;
const struct block *block;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
{
if (!quiet)
gdb_printf (stream,
@@ -2499,11 +2497,11 @@ print_frame_arg_vars (const frame_info_ptr &frame,
{
struct print_variable_and_value_data cb_data;
struct symbol *func;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
std::optional<compiled_regex> preg;
std::optional<compiled_regex> treg;
- if (!get_frame_pc_if_available (frame, &pc))
+ if (!(pc = get_frame_pc_if_available (frame)))
{
if (!quiet)
gdb_printf (stream,
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array.exp b/gdb/testsuite/gdb.ada/return-small-char-array.exp
new file mode 100644
index 0000000..75c781e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array.exp
@@ -0,0 +1,40 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# 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/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile proc
+
+if { [gdb_compile_ada $srcfile $binfile executable debug] != "" } {
+ return -1
+}
+
+clean_restart $testfile
+
+set bp_location [gdb_get_line_number "STOP" $testdir/proc.adb]
+runto "proc.adb:$bp_location"
+
+gdb_test "print Value.Name(My_Value)" \
+ { = "abcd"}
+
+# Step into the function.
+gdb_test "step 2" \
+ "return Of_Value;"
+
+# and finish.
+gdb_test "finish" \
+ { = "abcd"}
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb b/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb
new file mode 100644
index 0000000..b18d9fe
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/proc.adb
@@ -0,0 +1,22 @@
+-- Copyright 2025 Free Software Foundation, Inc.
+--
+-- 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/>.
+
+with Value;
+procedure Proc is
+ My_Value : Value.T := "abcd";
+begin
+ null; -- STOP
+ My_Value := Value.Name(My_Value);
+end;
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/value.adb b/gdb/testsuite/gdb.ada/return-small-char-array/value.adb
new file mode 100644
index 0000000..2dd9faa
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/value.adb
@@ -0,0 +1,21 @@
+-- Copyright 2025 Free Software Foundation, Inc.
+--
+-- 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/>.
+
+package body Value is
+ function Name (Of_Value : T) return T is
+ begin
+ return Of_Value;
+ end Name;
+end Value;
diff --git a/gdb/testsuite/gdb.ada/return-small-char-array/value.ads b/gdb/testsuite/gdb.ada/return-small-char-array/value.ads
new file mode 100644
index 0000000..16b171e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/return-small-char-array/value.ads
@@ -0,0 +1,20 @@
+-- Copyright 2025 Free Software Foundation, Inc.
+--
+-- 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/>.
+
+package Value is
+ type T is new String (1 .. 4);
+
+ function Name (Of_Value : T) return T;
+end;
diff --git a/gdb/testsuite/gdb.base/color-prompt.exp b/gdb/testsuite/gdb.base/color-prompt.exp
new file mode 100644
index 0000000..c037185
--- /dev/null
+++ b/gdb/testsuite/gdb.base/color-prompt.exp
@@ -0,0 +1,29 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Check using a prompt with color in CLI.
+
+# Using tuiterm requires setting TERM on host.
+require {!is_remote host}
+
+# We use a tuiterm, which allows us to determine cursor position.
+tuiterm_env
+Term::clean_restart 8 80
+
+# We start with an empty screen, to generate a visible prompt.
+Term::gen_prompt
+
+set tui 0
+source $srcdir/$subdir/../gdb.tui/color-prompt.exp.tcl
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index 01e3cc1..d857165 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -759,7 +759,6 @@ set show_conv_list \
{$_probe_arg10 = <error: No frame selected>} \
{$_probe_arg11 = <error: No frame selected>} \
{$_cimag = <internal function _cimag>} \
- {$_colorsupport = "monochrome"} \
{$_creal = <internal function _creal>} \
{$_isvoid = <internal function _isvoid>} \
{$_shell = <internal function _shell>} \
@@ -767,8 +766,6 @@ set show_conv_list \
{$_gdb_maint_setting = <internal function _gdb_maint_setting>} \
{$_gdb_setting_str = <internal function _gdb_setting_str>} \
{$_gdb_setting = <internal function _gdb_setting>} \
- {$_gdb_major = 17} \
- {$_gdb_minor = 1} \
{$_shell_exitsignal = void} \
{$_shell_exitcode = 0} \
{$_active_linker_namespaces = 1} \
@@ -788,10 +785,52 @@ if [allow_python_tests] {
{$_any_caller_matches = <internal function _any_caller_matches>} \
}
}
-gdb_test_list_exact "show convenience" "show convenience" \
- "\[^\r\n\]+\[\r\n\]+" \
- "\[^\r\n\]+" \
- $show_conv_list
+
+set lines [gdb_get_lines_no_pass "show convenience"]
+set matches 0
+set all_found 1
+foreach s $show_conv_list {
+ if { ![regexp (^|\r\n)[string_to_regexp $s](\r\n|$) $lines] } {
+ verbose -log "didn't match: '$s'"
+ set all_found 0
+ break
+ }
+ incr matches
+}
+
+set re_var [string_to_regexp {$_colorsupport}]
+if { [is_remote host] } {
+ set re_val {[^\r\n]+}
+} else {
+ set re_val [string_to_regexp {"monochrome"}]
+}
+if { [regexp "$re_var = $re_val" $lines] } {
+ incr matches
+} else {
+ set all_found 0
+}
+
+set re_vars \
+ [list \
+ [string_to_regexp {$_gdb_major}] \
+ [string_to_regexp {$_gdb_minor}]]
+foreach re_var $re_vars {
+ if { [regexp "$re_var = $decimal" $lines] } {
+ incr matches
+ } else {
+ set all_found 0
+ }
+}
+
+if { [regexp [string_to_regexp {$_tlb = void}] $lines] } {
+ incr matches
+} else {
+ # Convenience variable _tlb is added only if support for windows targets
+ # is enabled. Don't complain if it's missing.
+}
+
+gdb_assert { $all_found && $matches == [count_newlines $lines] } \
+ "show convenience"
#test show directories
gdb_test "show directories" "Source directories searched: .cdir\[:;\].cwd"
diff --git a/gdb/testsuite/gdb.base/dlmopen.exp b/gdb/testsuite/gdb.base/dlmopen.exp
index da17002..e7bf6f3 100644
--- a/gdb/testsuite/gdb.base/dlmopen.exp
+++ b/gdb/testsuite/gdb.base/dlmopen.exp
@@ -358,15 +358,19 @@ proc_with_prefix test_solib_unmap_events { } {
# dynamic linker as pending when some instances of the library were
# unloaded, despite there really only being one copy of the dynamic
# linker actually loaded into the inferior's address space.
- gdb_test_multiple "info breakpoints $bpnum" "check b/p status" {
- -re -wrap "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+\\*$::hex\\s*\r\n\\s+stop only if \\(0\\)" {
- fail $gdb_test_name
- }
-
- -re -wrap "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s*\[^\r\n\]+\r\n\\s+stop only if \\(0\\)" {
- pass $gdb_test_name
- }
- }
+ set hs {[^\r\n]}
+ set re_pass \
+ [multi_line \
+ "" \
+ [join \
+ [list \
+ "$bpnum" "breakpoint" "keep" "y" "$::hex$hs+"] \
+ {\s+}] \
+ [string cat \
+ {\s+} \
+ [string_to_regexp "stop only if (0)"] \
+ ([string_to_regexp " (target evals)"])?]]
+ gdb_test "info breakpoints $bpnum" $re_pass "check b/p status"
# With all the dlclose calls now complete, we should be back to a
# single copy of the dynamic linker.
diff --git a/gdb/testsuite/gdb.base/exprs.exp b/gdb/testsuite/gdb.base/exprs.exp
index f703c18..81f6f19 100644
--- a/gdb/testsuite/gdb.base/exprs.exp
+++ b/gdb/testsuite/gdb.base/exprs.exp
@@ -285,11 +285,14 @@ gdb_test "print v_short + " \
gdb_test "print v_short =}{= 3" \
"A syntax error in expression, near `\\}\\{= 3'\\."
+set hs {[^\r\n]}
+set re_debug [string cat $hs* {[Ss]hift} $hs*]
+
gdb_test_no_output "set debug parse 1"
set saw_start 0
set saw_val 0
gdb_test_multiple "print 23" "print with debugging" -lbl {
- -re "\r\nStarting parse(?=\r\n)" {
+ -re "\r\n${re_debug}(?=\r\n)" {
set saw_start 1
exp_continue
}
diff --git a/gdb/testsuite/gdb.base/readline-ask.exp b/gdb/testsuite/gdb.base/readline-ask.exp
index 3f98e13..2948970 100644
--- a/gdb/testsuite/gdb.base/readline-ask.exp
+++ b/gdb/testsuite/gdb.base/readline-ask.exp
@@ -13,6 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+require {!is_remote host}
+
standard_testfile .c
set inputrc ${srcdir}/${subdir}/${testfile}.inputrc
diff --git a/gdb/testsuite/gdb.base/readline.exp b/gdb/testsuite/gdb.base/readline.exp
index 198d686..9b87790 100644
--- a/gdb/testsuite/gdb.base/readline.exp
+++ b/gdb/testsuite/gdb.base/readline.exp
@@ -21,6 +21,8 @@
# Tests for readline operations.
#
+require {!is_remote host}
+
# This function is used to test operate-and-get-next.
# NAME is the name of the test.
# ARGS is a list of alternating commands and expected results.
diff --git a/gdb/testsuite/gdb.base/source-search.c b/gdb/testsuite/gdb.base/source-search.c
new file mode 100644
index 0000000..2320c5c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/source-search.c
@@ -0,0 +1,127 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 Free Software Foundation, Inc.
+
+ 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/>. */
+
+int
+main (void)
+{
+ /* Line 21 */
+ /* Line 22 */
+ /* Line 23 */
+ /* Line 24 */
+ /* Line 25 */
+ /* Line 26 */
+ /* Line 27 */
+ /* Line 28 */
+ /* Line 29 */
+ /* Line 30 */
+ /* Line 31 */
+ /* Line 32 */
+ /* Line 33 */
+ /* Line 34 */
+ /* Line 35 */
+ /* Line 36 */
+ /* Line 37 */
+ /* Line 38 */
+ /* Line 39 */
+ /* Line 40 */
+ /* Line 41 */
+ /* Line 42 */
+ /* Line 43 */
+ /* Line 44 */
+ /* Line 45 */
+ /* Line 46 */
+ /* Line 47 */
+ /* Line 48 */
+ /* Line 49 */
+ /* Line 50 */
+ /* Line 51 */
+ /* Line 52 */
+ /* Line 53 */
+ /* Line 54 */
+ /* Line 55 */
+ /* Line 56 */
+ /* Line 57 */
+ /* Line 58 */
+ /* Line 59 */
+ /* Line 60 */
+ /* Line 61 */
+ /* Line 62 */
+ /* Line 63 */
+ /* Line 64 */
+ /* Line 65 */
+ /* Line 66 */
+ /* Line 67 */
+ /* Line 68 */
+ /* Line 69 */
+ /* Line 70 */
+ /* Line 71 */
+ /* Line 72 */
+ /* Line 73 */
+ /* Line 74 */
+ /* Line 75 */
+ /* Line 76 */
+ /* Line 77 */
+ /* Line 78 */
+ /* Line 79 */
+ /* Line 80 */
+ /* Line 81 */
+ /* Line 82 */
+ /* Line 83 */
+ /* Line 84 */
+ /* Line 85 */
+ /* Line 86 */
+ /* Line 87 */
+ /* Line 88 */
+ /* Line 89 */
+ /* Line 90 */
+ /* Line 91 */
+ /* Line 92 */
+ /* Line 93 */
+ /* Line 94 */
+ /* Line 95 */
+ /* Line 96 */
+ /* Line 97 */
+ /* Line 98 */
+ /* Line 99 */
+ /* Line 100 */
+ /* Line 101 */
+ /* Line 102 */
+ /* Line 103 */
+ /* Line 104 */
+ /* Line 105 */
+ /* Line 106 */
+ /* Line 107 */
+ /* Line 108 */
+ /* Line 109 */
+ /* Line 110 */
+ /* Line 111 */
+ /* Line 112 */
+ /* Line 113 */
+ /* Line 114 */
+ /* Line 115 */
+ /* Line 116 */
+ /* Line 117 */
+ /* Line 118 */
+ /* Line 119 */
+ /* Line 120 */
+ /* Line 121 */
+ /* Line 122 */
+ /* Line 123 */
+ /* Line 124 */
+ /* Line 125 */
+ return 0;
+} /* Last line. */
diff --git a/gdb/testsuite/gdb.base/source-search.exp b/gdb/testsuite/gdb.base/source-search.exp
new file mode 100644
index 0000000..559c500
--- /dev/null
+++ b/gdb/testsuite/gdb.base/source-search.exp
@@ -0,0 +1,106 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# Test 'forward-search' and 'reverse-search' commands. This test
+# relies on some hard-coded line numbers relating to the source file.
+# We could switch to using gdb_get_line_number, but it doesn't feel
+# like that would add much value; just don't change the source file.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+ return
+}
+
+gdb_test "forward-search This testcase is part" \
+ "1\\s+/\\* This testcase is part of GDB, the GNU debugger\\." \
+ "search for first line of the file"
+
+gdb_test "forward-search This testcase is part" \
+ "Expression not found" \
+ "repeated search doesn't find the same first line"
+
+# The 'reverse-search' command starts searching from the line before
+# the last line displayed. So in this case, the reverse search starts
+# from line 0, i.e. nothing is searched.
+gdb_test "reverse-search This testcase is part" \
+ "Expression not found" \
+ "reverse search doesn't find the first line either"
+
+# List some source lines, and then perform some forward-searches. The
+# searches start from the first line after the last line displayed.
+gdb_test "list 20" ".*" \
+ "list source code ahead of a forward-search"
+gdb_test "forward-search Line 2" \
+ "25\\s+/\\* Line 25 \\*/" \
+ "first forward-search after a list"
+gdb_test "forward-search Line 2" \
+ "26\\s+/\\* Line 26 \\*/" \
+ "second forward-search after a list"
+gdb_test "forward-search Line 2" \
+ "27\\s+/\\* Line 27 \\*/" \
+ "third forward-search after a list"
+
+# Now reverse-search from where we got too.
+gdb_test "reverse-search Line 2" \
+ "26\\s+/\\* Line 26 \\*/" \
+ "first reverse-search for 'Line 2'"
+gdb_test "reverse-search Line 2" \
+ "25\\s+/\\* Line 25 \\*/" \
+ "second reverse-search for 'Line 2'"
+gdb_test "reverse-search Line 2" \
+ "24\\s+/\\* Line 24 \\*/" \
+ "third reverse-search for 'Line 2'"
+
+# List some source lines, and then perform a reverse-search. The
+# search starts frm the first line before the last line displayed.
+gdb_test "list 20" ".*" \
+ "list source code ahead of a reverse-search"
+gdb_test "reverse-search Line 2" \
+ "23\\s+/\\* Line 23 \\*/" \
+ "reverse-search after a list"
+
+# List the last lines of the file, then reverse search for the last
+# line. As reverse-search starts on the line before the last line
+# displayed, this will fail to find the last line.
+gdb_test "list 127"
+gdb_test "reverse-search Last line" \
+ "Expression not found" \
+ "reverse search for the last line fails"
+
+# List some lines from the middle of the file. Then try an invalid
+# 'list' command. Finally, check searches pick up from the middle of
+# the file where the first 'list' successfully completed.
+foreach_with_prefix search_direction { forward reverse } {
+ foreach_with_prefix bad_list { out-of-range backwards } {
+ gdb_test "list 50"
+
+ if { $bad_list eq "out-of-range" } {
+ gdb_test "list 1000" \
+ "Line number 995 out of range; \[^\r\n\]+ has 127 lines\\."
+ } else {
+ gdb_test_no_output "list 60,50"
+ }
+
+ if { $search_direction eq "forward" } {
+ set line 55
+ } else {
+ set line 53
+ }
+
+ gdb_test "${search_direction}-search Line" \
+ "$line\\s+/\\* Line $line \\*/"
+ }
+}
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index a6c18d3..6b1b08e 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -13,6 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+require {!is_remote host}
+
load_lib gdb-python.exp
# Test CLI output styling.
diff --git a/gdb/testsuite/gdb.base/tls-common.exp.tcl b/gdb/testsuite/gdb.base/tls-common.exp.tcl
index 7aa7f46..fc212a9 100644
--- a/gdb/testsuite/gdb.base/tls-common.exp.tcl
+++ b/gdb/testsuite/gdb.base/tls-common.exp.tcl
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-2025 Free Software Foundation, Inc.
# 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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj-lib.c b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
index c69bab7..e82a064 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj-lib.c
+++ b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.c b/gdb/testsuite/gdb.base/tls-dlobj.c
index 322bdda..a93f4a7 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj.c
+++ b/gdb/testsuite/gdb.base/tls-dlobj.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.exp b/gdb/testsuite/gdb.base/tls-dlobj.exp
index 02f2ff8..32e869e 100644
--- a/gdb/testsuite/gdb.base/tls-dlobj.exp
+++ b/gdb/testsuite/gdb.base/tls-dlobj.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-2025 Free Software Foundation, Inc.
# 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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.c b/gdb/testsuite/gdb.base/tls-multiobj.c
index 10e67da..dd4aadb 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.exp b/gdb/testsuite/gdb.base/tls-multiobj.exp
index 97acb33..2a52610 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj.exp
+++ b/gdb/testsuite/gdb.base/tls-multiobj.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-2025 Free Software Foundation, Inc.
# 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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj1.c b/gdb/testsuite/gdb.base/tls-multiobj1.c
index 86e7222..6207173 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj1.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj1.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj2.c b/gdb/testsuite/gdb.base/tls-multiobj2.c
index cea0709..9ff8b67 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj2.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj2.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-multiobj3.c b/gdb/testsuite/gdb.base/tls-multiobj3.c
index bb0f239..3594eba0 100644
--- a/gdb/testsuite/gdb.base/tls-multiobj3.c
+++ b/gdb/testsuite/gdb.base/tls-multiobj3.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.c b/gdb/testsuite/gdb.base/tls-nothreads.c
index b3aaa33..cac20f8 100644
--- a/gdb/testsuite/gdb.base/tls-nothreads.c
+++ b/gdb/testsuite/gdb.base/tls-nothreads.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2024 Free Software Foundation, Inc.
+ Copyright 2024-2025 Free Software Foundation, Inc.
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
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.exp b/gdb/testsuite/gdb.base/tls-nothreads.exp
index 92a5cd9..105e686 100644
--- a/gdb/testsuite/gdb.base/tls-nothreads.exp
+++ b/gdb/testsuite/gdb.base/tls-nothreads.exp
@@ -1,4 +1,4 @@
-# Copyright 2024 Free Software Foundation, Inc.
+# Copyright 2024-2025 Free Software Foundation, Inc.
# 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
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
index d3c1349..ca2fa45 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <assert.h>
+static volatile int volatile_dummy;
+
static int again;
static volatile struct
@@ -53,6 +55,40 @@ write_size8twice (void)
data.u.size8twice[offset] = first;
data.u.size8twice[offset + 1] = second;
#endif
+
+ /* Setting a breakpoint on an instruction after an instruction triggering a
+ watchpoint makes it ambiguous which one will be reported.
+ Insert a dummy instruction in between to make sure the watchpoint gets
+ reported. */
+ volatile_dummy = 1;
+
+ return; /* write_size8twice_return */
+}
+
+static void
+read_size8twice (void)
+{
+ static uint64_t volatile first;
+ static uint64_t volatile second;
+
+#ifdef __aarch64__
+ volatile void *p = &data.u.size8twice[offset];
+ asm volatile ("ldp %0, %1, [%2]"
+ : "=r" (first), "=r" (second) /* output */
+ : "r" (p) /* input */
+ : /* clobber */);
+#else
+ first = data.u.size8twice[offset];
+ second = data.u.size8twice[offset + 1];
+#endif
+
+ /* Setting a breakpoint on an instruction after an instruction triggering a
+ watchpoint makes it ambiguous which one will be reported.
+ Insert a dummy instruction inbetween to make sure the watchpoint gets
+ reported. */
+ volatile_dummy = 1;
+
+ return; /* read_size8twice_return */
}
int
@@ -63,6 +99,7 @@ main (void)
assert (sizeof (data) == 8 + 3 * 8);
write_size8twice ();
+ read_size8twice ();
while (size)
{
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
index 9220402..85b1eb7 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
@@ -151,6 +151,63 @@ foreach_with_prefix wpcount {4 7} {
gdb_assert $got_hit $test
}
+proc size8twice { function cmd offset index } {
+ clean_restart $::testfile
+
+ if { ![runto $function] } {
+ return -1
+ }
+
+ # Set offset in the inferior.
+ gdb_test_no_output "set var offset = $offset"
+
+ # Set a breakpoint.
+ set bp_src_string "${function}_return"
+ set bp_loc [gdb_get_line_number $bp_src_string]
+ gdb_breakpoint $bp_loc \
+ "Breakpoint $::decimal at $::hex" "$bp_src_string"
+
+ # Set a hardware watchpoint.
+ set watch_index [expr $offset + $index]
+ set test "$cmd data.u.size8twice\[$watch_index\]"
+ set wpnum 0
+ gdb_test_multiple $test "" {
+ -re -wrap "Hardware (read )?watchpoint ($::decimal): .*" {
+ set wpnum $expect_out(2,string)
+ pass $gdb_test_name
+ }
+ -re -wrap "Watchpoint ($::decimal): .*" {
+ if {[istarget "arm*-*-*"]} {
+ untested $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+ }
+
+ if { ! $wpnum } {
+ # No hardware watchpoint, we're done.
+ return 0
+ }
+
+ # Try to trigger the hardware watchpoint.
+ set got_hit 0
+ gdb_test_multiple "continue" "" {
+ -re -wrap "\r\nCould not insert hardware watchpoint .*" {
+ }
+ -re -wrap "Hardware (read )?watchpoint $wpnum:.*(New value|Value) = .*" {
+ set got_hit 1
+ send_gdb "continue\n"
+ exp_continue
+ }
+ -re -wrap " $bp_src_string .*" {
+ }
+ }
+ gdb_assert { $got_hit }
+
+ return $got_hit
+}
+
# We've got an array with 3 8-byte elements. Do a store of 16 bytes,
# to:
# - elements 0 and 1 (offset == 0), and
@@ -158,49 +215,21 @@ foreach_with_prefix wpcount {4 7} {
# For each case, check setting a watchpoint at:
# - the first written element (index == 0), and
# - the second element (index == 1).
-foreach_with_prefix offset { 0 1 } {
- foreach_with_prefix index { 0 1 } {
-
- clean_restart $binfile
-
- if ![runto_main] {
- return -1
- }
-
- gdb_test_no_output "set var offset = $offset"
- gdb_breakpoint [gdb_get_line_number "final_return"] \
- "Breakpoint $decimal at $hex" "final_return"
- set watch_index [expr $offset + $index]
- set test "watch data.u.size8twice\[$watch_index\]"
- set wpnum 0
- gdb_test_multiple $test $test {
- -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
- set wpnum $expect_out(1,string)
- pass $gdb_test_name
- }
- -re "Watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
- if {[istarget "arm*-*-*"]} {
- untested $gdb_test_name
- } else {
- fail $gdb_test_name
- }
+foreach_with_prefix fun { write_size8twice read_size8twice } {
+ if { $fun == "write_size8twice" } {
+ set cmd "watch"
+ } else {
+ set cmd "rwatch"
+ }
+ foreach_with_prefix offset { 0 1 } {
+ foreach_with_prefix index { 0 1 } {
+ set res [size8twice $fun $cmd $offset $index]
+ if { $res != 1 } {
+ break
}
}
- if {$wpnum} {
- set test "continue"
- set got_hit 0
- gdb_test_multiple $test $test {
- -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
- }
- -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
- set got_hit 1
- send_gdb "continue\n"
- exp_continue
- }
- -re " final_return .*\r\n$gdb_prompt $" {
- }
- }
- gdb_assert $got_hit "size8twice write"
+ if { $res != 1 } {
+ break
}
}
}
diff --git a/gdb/testsuite/gdb.cp/method-ref-return.cc b/gdb/testsuite/gdb.cp/method-ref-return.cc
new file mode 100644
index 0000000..4169bfe
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/method-ref-return.cc
@@ -0,0 +1,42 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Test that we can access class method/data member via reference. */
+
+struct foo
+{
+ foo () : m_a (42) {}
+ int get_a () const { return m_a; }
+ int m_a;
+};
+
+struct bar
+{
+ bar () : m_foo () {}
+ const foo &get_foo () const { return m_foo; }
+ foo m_foo;
+};
+
+int
+main (int argc, char *argv[])
+{
+ bar b;
+ const foo &ref = b.get_foo ();
+ int ret = ref.m_a; // breakpoint here
+ ret += ref.get_a ();
+ return ret;
+} \ No newline at end of file
diff --git a/gdb/testsuite/gdb.cp/method-ref-return.exp b/gdb/testsuite/gdb.cp/method-ref-return.exp
new file mode 100644
index 0000000..1ac5ac9
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/method-ref-return.exp
@@ -0,0 +1,70 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Test calling methods and accessing members via reference.
+
+require allow_cplus_tests
+
+standard_testfile .cc
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+# Set a breakpoint after the bar object is created and the reference is obtained.
+gdb_breakpoint [gdb_get_line_number "breakpoint here"]
+gdb_continue_to_breakpoint "after reference assignment"
+
+# Test that we can call the method through reference and get the expected result.
+gdb_test_multiple "print b.get_foo()" "print method call returning reference" {
+ -re "\\$\[0-9\]+ = \\(const foo &\\) @$hex: \\{m_a = 42\\}\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "Could not validate memory tag: Value can't be converted to integer\\." {
+ fail "$gdb_test_name"
+ }
+}
+
+# Test accessing the member through the reference.
+gdb_test "print b.get_foo ().m_a" \
+ "\\$\[0-9\]+ = 42" \
+ "print member access through reference"
+
+# Test calling method on the referenced object.
+gdb_test "print b.get_foo ().get_a()" \
+ "\\$\[0-9\]+ = 42" \
+ "print method call on referenced object"
+
+# Test that the stored reference works correctly.
+gdb_test_multiple "print ref" "print stored reference" {
+ -re "\\$\[0-9\]+ = \\(const foo &\\) @$hex: \\{m_a = 42\\}\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "Could not validate memory tag: Value can't be converted to integer\\." {
+ fail "$gdb_test_name"
+ }
+}
+
+gdb_test "print ref.m_a" \
+ "\\$\[0-9\]+ = 42" \
+ "print member through stored reference"
+
+gdb_test "print ref.get_a()" \
+ "\\$\[0-9\]+ = 42" \
+ "print method call through stored reference" \ No newline at end of file
diff --git a/gdb/testsuite/gdb.dap/scopes.c b/gdb/testsuite/gdb.dap/scopes.c
index d8929f1..2a1d76c 100644
--- a/gdb/testsuite/gdb.dap/scopes.c
+++ b/gdb/testsuite/gdb.dap/scopes.c
@@ -27,6 +27,8 @@ int main ()
static int scalar = 23;
+ void *ptr = (void *) &scalar;
+
{
const char *inner = "inner block";
diff --git a/gdb/testsuite/gdb.dap/scopes.exp b/gdb/testsuite/gdb.dap/scopes.exp
index 59d344b..52efa68 100644
--- a/gdb/testsuite/gdb.dap/scopes.exp
+++ b/gdb/testsuite/gdb.dap/scopes.exp
@@ -70,7 +70,8 @@ lassign $scopes scope reg_scope
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
gdb_assert {[dict get $scope presentationHint] == "locals"} \
"locals presentation hint"
-gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"
+set count [dict get $scope namedVariables]
+gdb_assert {$count == 4} "four vars in scope"
gdb_assert {[dict get $reg_scope name] == "Registers"} \
"second scope is registers"
@@ -89,8 +90,8 @@ set refs1 [lindex [dap_check_request_and_response "fetch variables 0,1" \
set refs2 [lindex [dap_check_request_and_response "fetch variables 2" \
"variables" \
[format {o variablesReference [i %d] \
- start [i 2] count [i 1]} \
- $num]] \
+ start [i 2] count [i %d]} \
+ $num [expr {$count - 2}]]] \
0]
set vars [concat [dict get $refs1 body variables] \
@@ -115,6 +116,10 @@ foreach var $vars {
"scalar" {
gdb_assert {[dict get $var value] == 23} "check value of scalar"
}
+ "ptr" {
+ gdb_assert {[dict get $var memoryReference] != ""} \
+ "check memoryReference of ptr"
+ }
default {
fail "unknown variable $name"
}
@@ -128,11 +133,38 @@ set refs [lindex [dap_check_request_and_response "fetch contents of dei" \
set deivals [dict get $refs body variables]
gdb_assert {[llength $deivals] == 2} "dei has two members"
+# Request more children than exist. See PR dap/33228.
+set seq [dap_send_request variables \
+ [format {o variablesReference [i %d] count [i 100]} $dei_ref]]
+lassign [dap_read_response variables $seq] response ignore
+gdb_assert {[dict get $response success] == "false"} \
+ "variables with invalid count"
+
set num [dict get $reg_scope variablesReference]
-# The request succeeding is sufficient.
-set val [dap_check_request_and_response "fetch first register" \
+lassign [dap_check_request_and_response "fetch all registers" \
"variables" \
- [format {o variablesReference [i %d] count [i 1]} $num]]
+ [format {o variablesReference [i %d] count [i %d]} $num\
+ [dict get $reg_scope namedVariables]]] \
+ val events
+
+# If any register has children, try to fetch those as well. This is a
+# regression test for part of PR dap/33228.
+foreach var [dict get $val body variables] {
+ set regvar [dict get $var variablesReference]
+ if {$regvar > 0} {
+ # If variablesReference is non-zero, then there must be either
+ # named or indexed children.
+ if {[dict exists $var namedVariables]} {
+ set n [dict get $var namedVariables]
+ } else {
+ set n [dict get $var indexedVariables]
+ }
+
+ dap_check_request_and_response "fetch register children for $regvar" \
+ "variables" \
+ [format {o variablesReference [i %d] count [i %d]} $regvar $n]
+ }
+}
set num [dict get $scope variablesReference]
set refs [lindex [dap_check_request_and_response "set variable scalar" \
diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp
index 8126740..7f91278 100644
--- a/gdb/testsuite/gdb.gdb/python-helper.exp
+++ b/gdb/testsuite/gdb.gdb/python-helper.exp
@@ -291,4 +291,4 @@ proc test_python_helper {} {
}
# Use the self-test framework to run the test.
-do_self_tests captured_main test_python_helper
+do_self_tests main test_python_helper
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 1cf9265..3948fce 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -167,5 +167,5 @@ proc test_with_self { } {
save_vars { INTERNAL_GDBFLAGS } {
set INTERNAL_GDBFLAGS [string map {"-q" ""} $INTERNAL_GDBFLAGS]
- do_self_tests captured_main test_with_self
+ do_self_tests main test_with_self
}
diff --git a/gdb/testsuite/gdb.guile/scm-parameter.exp b/gdb/testsuite/gdb.guile/scm-parameter.exp
index e35428a..0ee11e6 100644
--- a/gdb/testsuite/gdb.guile/scm-parameter.exp
+++ b/gdb/testsuite/gdb.guile/scm-parameter.exp
@@ -565,47 +565,50 @@ rename scm_param_test_maybe_no_output ""
# Test a color parameter.
-with_ansi_styling_terminal {
- # This enables 256 colors support and disables colors approximation.
- setenv TERM xterm-256color
- setenv COLORTERM truecolor
-
- # Start with a fresh gdb.
- gdb_exit
- gdb_start
- gdb_reinitialize_dir $srcdir/$subdir
-
- gdb_install_guile_utils
- gdb_install_guile_module
-
- # We use "." here instead of ":" so that this works on win32 too.
- set escaped_directory [string_to_regexp "$srcdir/$subdir"]
-
- gdb_test_multiline "color gdb parameter" \
- "guile" "" \
- "(define test-color-param" "" \
- " (make-parameter \"print test-color-param\"" "" \
- " #:command-class COMMAND_DATA" "" \
- " #:parameter-type PARAM_COLOR" "" \
- " #:doc \"When set, test param does something useful. When disabled, does nothing.\"" "" \
- " #:show-doc \"Show the state of the test-color-param.\"" "" \
- " #:set-doc \"Set the state of the test-color-param.\"" "" \
- " #:show-func (lambda (self value)" "" \
- " (format #f \"The state of the test-color-param is ~a.\" value))" "" \
- " #:initial-value (make-color \"green\")))" "" \
- "(register-parameter! test-color-param)" "" \
- "end"
-
- with_test_prefix "test-color-param" {
- with_test_prefix "initial-value" {
- gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color green COLORSPACE_ANSI_8COLOR>" "color parameter value (green)"
- gdb_test "show print test-color-param" "The state of the test-color-param is green." "show initial value"
- gdb_test_no_output "set print test-color-param 255"
- }
- with_test_prefix "new-value" {
- gdb_test "show print test-color-param" "The state of the test-color-param is 255." "show new value"
- gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color 255 COLORSPACE_XTERM_256COLOR>" "color parameter value (255)"
- gdb_test "set print test-color-param 256" "integer 256 out of range.*" "set invalid color parameter"
+if { ![is_remote host] } {
+ with_ansi_styling_terminal {
+
+ # This enables 256 colors support and disables colors approximation.
+ setenv TERM xterm-256color
+ setenv COLORTERM truecolor
+
+ # Start with a fresh gdb.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+
+ gdb_install_guile_utils
+ gdb_install_guile_module
+
+ # We use "." here instead of ":" so that this works on win32 too.
+ set escaped_directory [string_to_regexp "$srcdir/$subdir"]
+
+ gdb_test_multiline "color gdb parameter" \
+ "guile" "" \
+ "(define test-color-param" "" \
+ " (make-parameter \"print test-color-param\"" "" \
+ " #:command-class COMMAND_DATA" "" \
+ " #:parameter-type PARAM_COLOR" "" \
+ " #:doc \"When set, test param does something useful. When disabled, does nothing.\"" "" \
+ " #:show-doc \"Show the state of the test-color-param.\"" "" \
+ " #:set-doc \"Set the state of the test-color-param.\"" "" \
+ " #:show-func (lambda (self value)" "" \
+ " (format #f \"The state of the test-color-param is ~a.\" value))" "" \
+ " #:initial-value (make-color \"green\")))" "" \
+ "(register-parameter! test-color-param)" "" \
+ "end"
+
+ with_test_prefix "test-color-param" {
+ with_test_prefix "initial-value" {
+ gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color green COLORSPACE_ANSI_8COLOR>" "color parameter value (green)"
+ gdb_test "show print test-color-param" "The state of the test-color-param is green." "show initial value"
+ gdb_test_no_output "set print test-color-param 255"
+ }
+ with_test_prefix "new-value" {
+ gdb_test "show print test-color-param" "The state of the test-color-param is 255." "show new value"
+ gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color 255 COLORSPACE_XTERM_256COLOR>" "color parameter value (255)"
+ gdb_test "set print test-color-param 256" "integer 256 out of range.*" "set invalid color parameter"
+ }
}
}
}
diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp
index 214c570..e676925 100644
--- a/gdb/testsuite/gdb.python/py-parameter.exp
+++ b/gdb/testsuite/gdb.python/py-parameter.exp
@@ -45,6 +45,9 @@ proc_with_prefix test_directories { } {
}
proc_with_prefix test_data_directory { } {
+ # Proc assumes local host.
+ require {!is_remote host}
+
clean_restart
# Check we can correctly read the data-directory parameter. First,
@@ -187,6 +190,8 @@ proc_with_prefix test_enum_parameter { } {
# Test an color parameter.
proc_with_prefix test_color_parameter { } {
+ require {!is_remote host}
+
global env
with_ansi_styling_terminal {
# This enables 256 colors support and disables colors approximation.
diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 35c99bd..8ecc91a 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -112,5 +112,9 @@ set re_noattr "\[^<\]"
set status_window_line 15
set status [Term::get_line_with_attrs $status_window_line]
-gdb_assert { [regexp "^<reverse:1>$re_noattr*<reverse:0>$" $status] == 1} \
+verbose -log "status line: '$status'"
+
+# The status line uses standout, which may translate to different attributes
+# depending on the terminal settings. Just check for at least one attribute.
+gdb_assert { [regexp "^<.*>(exec|extended-r)" $status] == 1 } \
"status window: reverse"
diff --git a/gdb/testsuite/gdb.tui/color-prompt.exp b/gdb/testsuite/gdb.tui/color-prompt.exp
index a95b24a..af6e467 100644
--- a/gdb/testsuite/gdb.tui/color-prompt.exp
+++ b/gdb/testsuite/gdb.tui/color-prompt.exp
@@ -15,18 +15,16 @@
# Check using a prompt with color in TUI.
+require allow_tui_tests
+
tuiterm_env
Term::clean_restart 24 80
-# Set colored prompt.
if {![Term::enter_tui]} {
unsupported "TUI not supported"
return
}
-Term::command "set prompt \\033\[31m(gdb) \\033\[0m"
-
-set line [Term::get_line_with_attrs $Term::_cur_row]
-gdb_assert { [regexp "^<fg:red>$gdb_prompt <fg:default> *$" $line] } \
- "prompt with color"
+set tui 1
+source $srcdir/$subdir/color-prompt.exp.tcl
diff --git a/gdb/testsuite/gdb.tui/color-prompt.exp.tcl b/gdb/testsuite/gdb.tui/color-prompt.exp.tcl
new file mode 100644
index 0000000..e6f4d3b
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/color-prompt.exp.tcl
@@ -0,0 +1,80 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Check using a prompt with color in TUI ($tui == 0) or CLI ($tui == 0).
+
+set csi [string cat {\033} "\["]
+set rl_prompt_start_ignore {\001}
+set rl_prompt_end_ignore {\002}
+
+foreach_with_prefix rl_prompt_start_end_ignore { 0 1 } {
+ set color_on [string cat $csi 31m]
+ set color_off [string cat $csi 0m]
+
+ if { $rl_prompt_start_end_ignore } {
+ set color_on \
+ [string cat \
+ $rl_prompt_start_ignore \
+ $color_on \
+ $rl_prompt_end_ignore]
+ set color_off \
+ [string cat \
+ $rl_prompt_start_ignore \
+ $color_off \
+ $rl_prompt_end_ignore]
+ }
+
+ # Set prompt with color.
+ set prompt "${color_on}(gdb) $color_off"
+ Term::command "set prompt $prompt"
+
+ # Check the color.
+ set line [Term::get_line_with_attrs $Term::_cur_row]
+ gdb_assert { [regexp "^<fg:red>$gdb_prompt <fg:default> *$" $line] } \
+ "prompt with color"
+
+ # Type a string.
+ set cmd "some long command"
+ send_gdb $cmd
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"] 23
+
+ # Send ^A, aka C-a, trigger beginning-of-line.
+ send_gdb "\001"
+ if { $tui || $rl_prompt_start_end_ignore } {
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"] 6
+ } else {
+ # Without the markers, readline may get the cursor position wrong, so
+ # match less strict.
+ Term::wait_for_line ^[string_to_regexp "(gdb) $cmd"]
+ }
+ Term::dump_screen
+
+ # Type something else to flush out the effect of the ^A.
+ set prefix "A"
+ send_gdb $prefix
+ if { $tui || $rl_prompt_start_end_ignore } {
+ Term::wait_for_line ^[string_to_regexp "(gdb) $prefix$cmd"] 7
+ } else {
+ # Without the markers, readline may get the cursor position wrong, so
+ # match less strict.
+ Term::wait_for_line [string_to_regexp "$prefix"]
+ }
+
+ # Abort command line editing, and regenerate prompt.
+ send_gdb "\003"
+
+ # Reset prompt to default prompt.
+ Term::command "set prompt (gdb) "
+}
diff --git a/gdb/testsuite/gdb.tui/gdb.tcl b/gdb/testsuite/gdb.tui/gdb.tcl
new file mode 100755
index 0000000..ca207ed
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/gdb.tcl
@@ -0,0 +1,20 @@
+#!/usr/bin/env tclsh
+
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+puts "foo\033(%5"
+
+gets stdin
diff --git a/gdb/testsuite/gdb.tui/main-2.exp b/gdb/testsuite/gdb.tui/main-2.exp
index 71ad03b..14a7cb1 100644
--- a/gdb/testsuite/gdb.tui/main-2.exp
+++ b/gdb/testsuite/gdb.tui/main-2.exp
@@ -41,7 +41,7 @@ if {![Term::enter_tui]} {
set line " return 0;"
set nr [gdb_get_line_number $line]
-set screen_line [Term::get_string_with_attrs 6 1 79]
+set screen_line [Term::get_string_with_attrs 6 11 79]
verbose -log "screen line 6: '$screen_line'"
-gdb_assert { [regexp "$nr <reverse:1>$line<reverse:0>" $screen_line] } \
+gdb_assert { [regexp "<reverse:1>$line<reverse:0>" $screen_line] } \
"highlighted line in middle of source window"
diff --git a/gdb/testsuite/gdb.tui/main.exp b/gdb/testsuite/gdb.tui/main.exp
index d6960c7..e49da35 100644
--- a/gdb/testsuite/gdb.tui/main.exp
+++ b/gdb/testsuite/gdb.tui/main.exp
@@ -43,7 +43,10 @@ if {![Term::enter_tui]} {
}
send_gdb "file [standard_output_file $testfile]\n"
-gdb_assert { [Term::wait_for "Reading symbols from"] } "file command"
+# Matching the output is difficult because it may or may not wrap. Simply
+# match the resulting prompt.
+gdb_assert { [Term::wait_for ""] } "file command"
+
Term::check_contents "show main after file" \
[string_to_regexp "|___[format %06d $nr]_$line"]
diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp
index f517997..914e10c 100644
--- a/gdb/testsuite/gdb.tui/new-layout.exp
+++ b/gdb/testsuite/gdb.tui/new-layout.exp
@@ -150,4 +150,7 @@ Term::check_box "before cmd_only: src box in src layout" 0 0 80 15
Term::command "layout cmd_only"
Term::command "layout src"
+
+# Flush out and check the resulting src box.
+Term::command "print 1"
Term::check_box "after cmd_only: src box in src layout" 0 0 80 15
diff --git a/gdb/testsuite/gdb.tui/pr30056.exp b/gdb/testsuite/gdb.tui/pr30056.exp
index 3403033..dd3b25c 100644
--- a/gdb/testsuite/gdb.tui/pr30056.exp
+++ b/gdb/testsuite/gdb.tui/pr30056.exp
@@ -72,9 +72,8 @@ save_vars { env(LC_ALL) } {
# Send ^C to clear the command line.
send_gdb "\003"
} else {
- # Sending ^C currently doesn't abort the i-search. PR cli/30498 is
- # open about this.
- kfail cli/30498 $test
+ # Sending ^C currently doesn't abort the i-search.
+ fail $test
# At this point we don't have a responsive prompt. Send ^G to abort
# the i-search.
diff --git a/gdb/testsuite/gdb.tui/source-search.c b/gdb/testsuite/gdb.tui/source-search.c
new file mode 100644
index 0000000..2320c5c
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/source-search.c
@@ -0,0 +1,127 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 Free Software Foundation, Inc.
+
+ 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/>. */
+
+int
+main (void)
+{
+ /* Line 21 */
+ /* Line 22 */
+ /* Line 23 */
+ /* Line 24 */
+ /* Line 25 */
+ /* Line 26 */
+ /* Line 27 */
+ /* Line 28 */
+ /* Line 29 */
+ /* Line 30 */
+ /* Line 31 */
+ /* Line 32 */
+ /* Line 33 */
+ /* Line 34 */
+ /* Line 35 */
+ /* Line 36 */
+ /* Line 37 */
+ /* Line 38 */
+ /* Line 39 */
+ /* Line 40 */
+ /* Line 41 */
+ /* Line 42 */
+ /* Line 43 */
+ /* Line 44 */
+ /* Line 45 */
+ /* Line 46 */
+ /* Line 47 */
+ /* Line 48 */
+ /* Line 49 */
+ /* Line 50 */
+ /* Line 51 */
+ /* Line 52 */
+ /* Line 53 */
+ /* Line 54 */
+ /* Line 55 */
+ /* Line 56 */
+ /* Line 57 */
+ /* Line 58 */
+ /* Line 59 */
+ /* Line 60 */
+ /* Line 61 */
+ /* Line 62 */
+ /* Line 63 */
+ /* Line 64 */
+ /* Line 65 */
+ /* Line 66 */
+ /* Line 67 */
+ /* Line 68 */
+ /* Line 69 */
+ /* Line 70 */
+ /* Line 71 */
+ /* Line 72 */
+ /* Line 73 */
+ /* Line 74 */
+ /* Line 75 */
+ /* Line 76 */
+ /* Line 77 */
+ /* Line 78 */
+ /* Line 79 */
+ /* Line 80 */
+ /* Line 81 */
+ /* Line 82 */
+ /* Line 83 */
+ /* Line 84 */
+ /* Line 85 */
+ /* Line 86 */
+ /* Line 87 */
+ /* Line 88 */
+ /* Line 89 */
+ /* Line 90 */
+ /* Line 91 */
+ /* Line 92 */
+ /* Line 93 */
+ /* Line 94 */
+ /* Line 95 */
+ /* Line 96 */
+ /* Line 97 */
+ /* Line 98 */
+ /* Line 99 */
+ /* Line 100 */
+ /* Line 101 */
+ /* Line 102 */
+ /* Line 103 */
+ /* Line 104 */
+ /* Line 105 */
+ /* Line 106 */
+ /* Line 107 */
+ /* Line 108 */
+ /* Line 109 */
+ /* Line 110 */
+ /* Line 111 */
+ /* Line 112 */
+ /* Line 113 */
+ /* Line 114 */
+ /* Line 115 */
+ /* Line 116 */
+ /* Line 117 */
+ /* Line 118 */
+ /* Line 119 */
+ /* Line 120 */
+ /* Line 121 */
+ /* Line 122 */
+ /* Line 123 */
+ /* Line 124 */
+ /* Line 125 */
+ return 0;
+} /* Last line. */
diff --git a/gdb/testsuite/gdb.tui/source-search.exp b/gdb/testsuite/gdb.tui/source-search.exp
new file mode 100644
index 0000000..6865db4
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/source-search.exp
@@ -0,0 +1,71 @@
+# Copyright 2025 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Test forward-search and reverse-search within the TUI src window.
+
+tuiterm_env
+
+standard_testfile .c
+
+if {[build_executable "failed to build" ${testfile} ${srcfile}] == -1} {
+ return
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+ unsupported "TUI not supported"
+ return
+}
+
+proc check_src_window { testname first_line } {
+ set last_line [expr $first_line + 12]
+ Term::check_box_contents $testname 0 0 80 15 \
+ "^\\s+${first_line}\\s+.*\\s+${last_line}\\s+/\\* Line ${last_line} \\*/\\s+$"
+
+}
+
+set first_line 15
+
+# Check that the window contents are as expected.
+check_src_window "initial src contents" $first_line
+
+# Search forward. Searches are from the last line displayed, so this
+# will move the next source line onto the screen each time.
+for { set i 1 } { $i < 4 } { incr i } {
+ incr first_line
+ Term::command "forward-search Line"
+ check_src_window "src windows after forward-search $i" $first_line
+}
+
+# Reverse search. Like forward-search, but move backward through the
+# source.
+for { set i 1 } { $i < 3 } { incr i } {
+ incr first_line -1
+ Term::command "reverse-search Line"
+ check_src_window "src windows after reverse-search $i" $first_line
+}
+
+# Until there are no matching lines left.
+Term::command "reverse-search Line"
+gdb_assert {[regexp -- "^Expression not found\\s+$" [Term::get_line 22]]} \
+ "check start of source was reached"
+
+Term::command "forward-search Last line"
+Term::check_box_contents "forward-search to end of file" 0 0 80 15 \
+ "^\\s+122\\s+.*/\\* Last line\\. \\*/\\s+$"
+
+Term::command "reverse-search This testcase is part"
+Term::check_box_contents "reverse-search to start of file" 0 0 80 15 \
+ "^\\s+1\\s+.*\\s+13\\s+GNU General Public License for more details\\.\\s+$"
diff --git a/gdb/testsuite/gdb.tui/tui-disasm-styling.exp b/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
index 513d787..43b8ecf 100644
--- a/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
+++ b/gdb/testsuite/gdb.tui/tui-disasm-styling.exp
@@ -43,6 +43,9 @@ if {![Term::enter_tui]} {
return
}
+# Proc enter_tui switches off styling, re-enable it.
+Term::command "set style enabled on"
+
Term::command "layout asm"
Term::check_box "asm box" 0 0 80 15
diff --git a/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp b/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
index 51623e8..47482a2 100644
--- a/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
+++ b/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.exp
@@ -20,9 +20,13 @@ tuiterm_env
standard_testfile tui-layout-asm-short-prog.S
-if {[build_executable "failed to prepare" ${testfile} ${srcfile} \
- {debug additional_flags=-nostdlib \
- additional_flags=-nostartfiles}] == -1} {
+set opts {}
+lappend opts debug
+lappend opts additional_flags=-static
+lappend opts additional_flags=-nostdlib
+lappend opts additional_flags=-nostartfiles
+
+if { [build_executable "failed to prepare" $testfile $srcfile $opts] == -1 } {
return -1
}
diff --git a/gdb/testsuite/gdb.tui/tui-mode-switch.exp b/gdb/testsuite/gdb.tui/tui-mode-switch.exp
new file mode 100644
index 0000000..c605962
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/tui-mode-switch.exp
@@ -0,0 +1,57 @@
+require allow_tui_tests
+
+tuiterm_env
+
+if { [ishost *-*-*bsd*] } {
+ # We need support for alternate screen, and xterm doesn't have it.
+ set term xterm-clear
+} else {
+ set term xterm
+}
+
+Term::with_term $term {
+ Term::clean_restart 12 40
+}
+
+if {![Term::prepare_for_tui]} {
+ unsupported "TUI not supported"
+ return 0
+}
+
+# Generate prompt.
+Term::gen_prompt
+
+# Move to last line.
+for { set i 1 } { $i <= 11 } { incr i } {
+ send_gdb "\n"
+ Term::wait_for ""
+}
+
+# Type "foo".
+send_gdb "foo"
+set line { 0 11 40 1 }
+gdb_assert { [Term::wait_for_region_contents {*}$line "^$gdb_prompt foo"] } \
+ "type foo"
+
+# Enter TUI.
+send_gdb "\030\001"
+gdb_assert { [Term::wait_for ""] } "enter TUI"
+
+# Exit TUI.
+send_gdb "\030\001"
+gdb_assert { [Term::wait_for ""] } "exit TUI"
+
+# Type b.
+send_gdb "b"
+gdb_assert { [Term::wait_for_region_contents {*}$line "^$gdb_prompt b"] } \
+ "type b"
+
+# Check that we don't see "boo".
+gdb_assert { ![Term::check_region_contents_p {*}$line "^$gdb_prompt boo"] } \
+ "no boo"
+Term::dump_screen
+
+# We need an empty prompt here, to deal with the "monitor exit" that
+# native-extended-gdbserver will send. Send a backspace.
+send_gdb "\010"
+Term::wait_for ""
diff --git a/gdb/testsuite/gdb.tui/tuiterm-2.exp b/gdb/testsuite/gdb.tui/tuiterm-2.exp
index 5992271..a451834 100644
--- a/gdb/testsuite/gdb.tui/tuiterm-2.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm-2.exp
@@ -106,6 +106,76 @@ with_override Term::accept_gdb_output test_accept_gdb_output {
}
gdb_assert { [Term::wait_for ""] }
}
+
+ with_test_prefix "Term::wait_for 2" {
+ Term::_setup 4 20
+ set send_cnt 0
+ set expect_send {}
+ set action_cnt 0
+ set actions {
+ {
+ Term::_move_cursor 0 0
+
+ Term::_insert "${::border}(gdb) "
+ set pos $Term::_cur_col
+
+ Term::_insert "foo"
+
+ Term::_move_cursor 19 0
+ Term::_insert "$::border"
+
+ Term::_move_cursor $pos 0
+ }
+ {
+ Term::_move_cursor 0 1
+
+ Term::_insert "${::border}(gdb) "
+ set pos $Term::_cur_col
+
+ Term::_move_cursor 19 1
+ Term::_insert "$::border"
+
+ Term::_move_cursor $pos 1
+ }
+ }
+
+ # Wait for a prompt.
+ gdb_assert { [Term::wait_for ""] }
+
+ # The first action sets the cursor after the prompt on the
+ # first line. The second action sets the cursor after the
+ # prompt on the second line. Check that wait_for returns
+ # after the second action, not the first.
+ gdb_assert { $Term::_cur_row == 1 }
+ }
}
}
}
+
+with_test_prefix "Unrecognized escape sequence" {
+ spawn $srcdir/$subdir/gdb.tcl
+ switch_gdb_spawn_id $spawn_id
+
+ Term::_setup 4 20
+
+ save_vars timeout {
+ set timeout 1
+
+ set line { 0 0 20 1 }
+
+ # Parse "foo".
+ gdb_assert { [Term::wait_for_region_contents \
+ {*}$line \
+ [string_to_regexp "foo"]] } \
+ "foo"
+
+ # Parse "\033(%5".
+ gdb_assert { ![Term::accept_gdb_output 0] } \
+ "fail to parse escape sequence"
+ gdb_assert { [Term::wait_for_region_contents \
+ {*}$line \
+ [string_to_regexp "^\[(%5"]] } \
+ "echoed escape sequence"
+ }
+ Term::dump_screen
+}
diff --git a/gdb/testsuite/gdb.tui/tuiterm.exp b/gdb/testsuite/gdb.tui/tuiterm.exp
index 6cd65f3..ed9478a 100644
--- a/gdb/testsuite/gdb.tui/tuiterm.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm.exp
@@ -653,13 +653,21 @@ proc test_cursor_backward_tabulation { } {
}
proc test_repeat { } {
- Term::_move_cursor 2 1
- set Term::_last_char X
+ Term::_move_cursor 0 1
+
+ Term::_insert "xxX"
+ gdb_assert { $Term::_last_char == "X" }
+ check "insert" {
+ "abcdefgh"
+ "xxXlmnop"
+ "qrstuvwx"
+ "yz01234 "
+ } 3 1
- Term::_csi_b 3
+ Term::_csi_b 2
check "repeat" {
"abcdefgh"
- "ijXXXnop"
+ "xxXXXnop"
"qrstuvwx"
"yz01234 "
} 5 1
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
index e037664..97be023 100644
--- a/gdb/testsuite/lib/selftest-support.exp
+++ b/gdb/testsuite/lib/selftest-support.exp
@@ -72,21 +72,39 @@ proc selftest_setup { executable function } {
# run yourself
set description "run until breakpoint at $function"
+ set re_hs {[^\r\n]+}
+ set re_args [string cat \
+ [string_to_regexp "("] \
+ $re_hs \
+ [string_to_regexp ")"]]
+ set re_pass \
+ [multi_line \
+ "Starting program: $re_hs" \
+ ".*" \
+ [string cat "Breakpoint $::decimal, $function $re_args at" \
+ " ${re_hs}gdb.c:$re_hs"] \
+ ".*"]
+ set re_xfail \
+ [multi_line \
+ "Starting program: $re_hs" \
+ ".*" \
+ "Breakpoint $::decimal, $function $re_args$re_hs" \
+ ".*"]
gdb_test_multiple "run $INTERNAL_GDBFLAGS" "$description" {
- -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).* at .*main.c:.*$gdb_prompt $" {
- pass "$description"
- }
- -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).*$gdb_prompt $" {
- xfail "$description (line numbers scrambled?)"
- }
- -re "vfork: No more processes.*$gdb_prompt $" {
- fail "$description (out of virtual memory)"
- return -1
- }
- -re ".*$gdb_prompt $" {
- fail "$description"
- return -1
- }
+ -re -wrap $re_pass {
+ pass $description
+ }
+ -re -wrap $re_xfail {
+ xfail "$description (line numbers scrambled?)"
+ }
+ -re -wrap "vfork: No more processes.*" {
+ fail "$description (out of virtual memory)"
+ return -1
+ }
+ -re -wrap "" {
+ fail $description
+ return -1
+ }
}
return 0
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index b83b8af..e1af223 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -33,1331 +33,1690 @@ namespace eval Term {
variable _resize_count
- proc _log { what } {
- verbose "+++ $what"
- }
+ variable _TERM
+ set _TERM ""
- # Call BODY, then log WHAT along with the original and new cursor position.
- proc _log_cur { what body } {
- variable _cur_row
- variable _cur_col
+ variable _alternate
+ variable _alternate_setup
+ set _alternate 0
+ set _alternate_setup 0
+}
- set orig_cur_row $_cur_row
- set orig_cur_col $_cur_col
+proc Term::_log { what } {
+ verbose "+++ $what"
+}
- set code [catch {uplevel $body} result]
+# Call BODY, then log WHAT along with the original and new cursor position.
+proc Term::_log_cur { what body } {
+ variable _cur_row
+ variable _cur_col
- _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+ set orig_cur_row $_cur_row
+ set orig_cur_col $_cur_col
- if { $code == 1 } {
- global errorInfo errorCode
- return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
- } else {
- return -code $code $result
- }
- }
+ set code [catch {uplevel $body} result]
- # If ARG is empty, return DEF: otherwise ARG. This is useful for
- # defaulting arguments in CSIs.
- proc _default {arg def} {
- if {$arg == ""} {
- return $def
- }
- return $arg
+ _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+
+ if { $code == 1 } {
+ global errorInfo errorCode
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+ } else {
+ return -code $code $result
}
+}
- # Erase in the line Y from SX to just before EX.
- proc _clear_in_line {sx ex y} {
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- while {$sx < $ex} {
- set _chars($sx,$y) [list " " $lattr]
- incr sx
- }
+# If ARG is empty, return DEF: otherwise ARG. This is useful for
+# defaulting arguments in CSIs.
+proc Term::_default {arg def} {
+ if {$arg == ""} {
+ return $def
}
+ return $arg
+}
- # Erase the lines from SY to just before EY.
- proc _clear_lines {sy ey} {
- variable _cols
- while {$sy < $ey} {
- _clear_in_line 0 $_cols $sy
- incr sy
- }
+# Erase in the line Y from SX to just before EX.
+proc Term::_clear_in_line {sx ex y} {
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ while {$sx < $ex} {
+ set _chars($sx,$y) [list " " $lattr]
+ incr sx
}
+}
- # Beep.
- proc _ctl_0x07 {} {
+# Erase the lines from SY to just before EY.
+proc Term::_clear_lines {sy ey} {
+ variable _cols
+ while {$sy < $ey} {
+ _clear_in_line 0 $_cols $sy
+ incr sy
}
+}
+
+# Beep.
+proc Term::_ctl_0x07 {} {
+}
+
+# Return 1 if tuiterm has the bw/auto_left_margin enabled.
+proc Term::_have_bw {} {
+ return [expr \
+ [string equal $Term::_TERM "ansiw"] \
+ || [string equal $Term::_TERM "ansis"]]
+}
- # Return 1 if tuiterm has the bw/auto_left_margin enabled.
- proc _have_bw {} {
- return [string equal $Term::_TERM "ansiw"]
+# Backspace.
+proc Term::_ctl_0x08 { {bw -1} } {
+ if { $bw == -1 } {
+ set bw [_have_bw]
}
+ _log_cur "Backspace, bw == $bw" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- # Backspace.
- proc _ctl_0x08 { {bw -1} } {
- if { $bw == -1 } {
- set bw [_have_bw]
+ if { $_cur_col > 0 } {
+ # No wrapping needed.
+ incr _cur_col -1
+ return
}
- _log_cur "Backspace, bw == $bw" {
- variable _cur_col
- variable _cur_row
- variable _cols
- if { $_cur_col > 0 } {
- # No wrapping needed.
- incr _cur_col -1
- return
- }
+ if { ! $bw } {
+ # Wrapping not enabled.
+ return
+ }
- if { ! $bw } {
- # Wrapping not enabled.
- return
- }
+ if { $_cur_row == 0 } {
+ # Can't wrap.
+ return
+ }
+
+ # Wrap to previous line.
+ set _cur_col [expr $_cols - 1]
+ incr _cur_row -1
+ }
+}
+
+# Linefeed.
+proc Term::_ctl_0x0a {} {
+ _log_cur "Line feed" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- if { $_cur_row == 0 } {
- # Can't wrap.
- return
+ incr _cur_row 1
+ while {$_cur_row >= $_rows} {
+ # Scroll the display contents. We scroll one line at
+ # a time here; as _cur_row was only increased by one,
+ # a single line scroll should be enough to put the
+ # cursor back on the screen. But we wrap the
+ # scrolling inside a while loop just to be on the safe
+ # side.
+ for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
+ set next_y [expr $y + 1]
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
+ }
}
- # Wrap to previous line.
- set _cur_col [expr $_cols - 1]
incr _cur_row -1
}
}
+}
- # Linefeed.
- proc _ctl_0x0a {} {
- _log_cur "Line feed" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
-
- incr _cur_row 1
- while {$_cur_row >= $_rows} {
- # Scroll the display contents. We scroll one line at
- # a time here; as _cur_row was only increased by one,
- # a single line scroll should be enough to put the
- # cursor back on the screen. But we wrap the
- # scrolling inside a while loop just to be on the safe
- # side.
- for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
- set next_y [expr $y + 1]
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- }
+# Carriage return.
+proc Term::_ctl_0x0d {} {
+ _log_cur "Carriage return" {
+ variable _cur_col
- incr _cur_row -1
- }
- }
+ set _cur_col 0
}
+}
- # Carriage return.
- proc _ctl_0x0d {} {
- _log_cur "Carriage return" {
- variable _cur_col
+# Designate G0 Character Set, USASCII (ESC ( B)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = B)
+proc Term::_esc_0x28_B {} {
+ _log "ignored: G0: USASCII"
+}
- set _cur_col 0
- }
- }
+# Designate G0 Character Set, DEC Special Character and Line Drawing Set (ESC ( 0)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = 0)
+proc Term::_esc_0x28_0 {} {
+ _log "ignored: G0: DEC Special Character and Line Drawing Set"
+}
+
+# DECKPAM (Application Keypad, ESC =)
+#
+# https://vt100.net/docs/vt510-rm/DECKPAM.html
+proc Term::_esc_0x3d {} {
+ _log "ignored: Application Keypad"
+}
- # Insert Character.
- #
- # https://vt100.net/docs/vt510-rm/ICH.html
- proc _csi_@ {args} {
- set n [_default [lindex $args 0] 1]
+# DECKPNM (Normal Keypad, ESC >)
+#
+# https://vt100.net/docs/vt510-rm/DECKPNM.html
+proc Term::_esc_0x3e {} {
+ _log "ignored: Normal Keypad"
+}
- _log_cur "Insert Character ($n)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _chars
+# Insert Character.
+#
+# https://vt100.net/docs/vt510-rm/ICH.html
+proc Term::_csi_@ {args} {
+ set n [_default [lindex $args 0] 1]
- # Move characters right of the cursor right by N positions,
- # starting with the rightmost one.
- for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
- set out_col [expr $in_col + $n]
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- }
+ _log_cur "Insert Character ($n)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _chars
- # Write N blank spaces starting from the cursor.
- _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
+ # Move characters right of the cursor right by N positions,
+ # starting with the rightmost one.
+ for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
+ set out_col [expr $in_col + $n]
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
}
- }
- # Horizontal Position Absolute.
- #
- # https://vt100.net/docs/vt510-rm/HPA.html
- proc _csi_` {args} {
- # Same as Cursor Horizontal Absolute.
- return [Term::_csi_G {*}$args]
+ # Write N blank spaces starting from the cursor.
+ _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
}
+}
+
+# Horizontal Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/HPA.html
+proc Term::_csi_` {args} {
+ # Same as Cursor Horizontal Absolute.
+ return [Term::_csi_G {*}$args]
+}
- # Cursor Up.
- #
- # https://vt100.net/docs/vt510-rm/CUU.html
- proc _csi_A {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Up.
+#
+# https://vt100.net/docs/vt510-rm/CUU.html
+proc Term::_csi_A {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Up ($arg)" {
- variable _cur_row
+ _log_cur "Cursor Up ($arg)" {
+ variable _cur_row
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Down.
- #
- # https://vt100.net/docs/vt510-rm/CUD.html
- proc _csi_B {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Down.
+#
+# https://vt100.net/docs/vt510-rm/CUD.html
+proc Term::_csi_B {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Down ($arg)" {
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Down ($arg)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Forward.
- #
- # https://vt100.net/docs/vt510-rm/CUF.html
- proc _csi_C {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Forward.
+#
+# https://vt100.net/docs/vt510-rm/CUF.html
+proc Term::_csi_C {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Forward ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Forward ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
- }
+ set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
}
+}
- # Cursor Backward.
- #
- # https://vt100.net/docs/vt510-rm/CUB.html
- proc _csi_D {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Backward.
+#
+# https://vt100.net/docs/vt510-rm/CUB.html
+proc Term::_csi_D {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward ($arg)" {
- variable _cur_col
+ _log_cur "Cursor Backward ($arg)" {
+ variable _cur_col
- set _cur_col [expr {max ($_cur_col - $arg, 0)}]
- }
+ set _cur_col [expr {max ($_cur_col - $arg, 0)}]
}
+}
- # Cursor Next Line.
- #
- # https://vt100.net/docs/vt510-rm/CNL.html
- proc _csi_E {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Next Line.
+#
+# https://vt100.net/docs/vt510-rm/CNL.html
+proc Term::_csi_E {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Next Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Next Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Previous Line.
- #
- # https://vt100.net/docs/vt510-rm/CPL.html
- proc _csi_F {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Previous Line.
+#
+# https://vt100.net/docs/vt510-rm/CPL.html
+proc Term::_csi_F {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Previous Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Previous Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Horizontal Absolute.
- #
- # https://vt100.net/docs/vt510-rm/CHA.html
- proc _csi_G {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Horizontal Absolute.
+#
+# https://vt100.net/docs/vt510-rm/CHA.html
+proc Term::_csi_G {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Absolute ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Absolute ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($arg, $_cols)} - 1]
- }
+ set _cur_col [expr {min ($arg, $_cols)} - 1]
}
+}
- # Cursor Position.
- #
- # https://vt100.net/docs/vt510-rm/CUP.html
- proc _csi_H {args} {
- set row [_default [lindex $args 0] 1]
- set col [_default [lindex $args 1] 1]
+# Cursor Position.
+#
+# https://vt100.net/docs/vt510-rm/CUP.html
+proc Term::_csi_H {args} {
+ set row [_default [lindex $args 0] 1]
+ set col [_default [lindex $args 1] 1]
- _log_cur "Cursor Position ($row, $col)" {
- variable _cur_col
- variable _cur_row
+ _log_cur "Cursor Position ($row, $col)" {
+ variable _cur_col
+ variable _cur_row
- set _cur_row [expr {$row - 1}]
- set _cur_col [expr {$col - 1}]
- }
+ set _cur_row [expr {$row - 1}]
+ set _cur_col [expr {$col - 1}]
}
+}
- # Cursor Horizontal Forward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CHT.html
- proc _csi_I {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Horizontal Forward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CHT.html
+proc Term::_csi_I {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
+ variable _cur_col
+ variable _cols
- incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
- if {$_cur_col >= $_cols} {
- set _cur_col [expr {$_cols - 1}]
- }
+ incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
+ if {$_cur_col >= $_cols} {
+ set _cur_col [expr {$_cols - 1}]
}
}
+}
- # Erase in Display.
- #
- # https://vt100.net/docs/vt510-rm/ED.html
- proc _csi_J {args} {
- set arg [_default [lindex $args 0] 0]
-
- _log_cur "Erase in Display ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
-
- if {$arg == 0} {
- # Cursor (inclusive) to end of display.
- _clear_in_line $_cur_col $_cols $_cur_row
- _clear_lines [expr {$_cur_row + 1}] $_rows
- } elseif {$arg == 1} {
- # Beginning of display to cursor (inclusive).
- _clear_lines 0 $_cur_row
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire display.
- _clear_lines 0 $_rows
- }
+# Erase in Display.
+#
+# https://vt100.net/docs/vt510-rm/ED.html
+proc Term::_csi_J {args} {
+ set arg [_default [lindex $args 0] 0]
+
+ _log_cur "Erase in Display ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of display.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ _clear_lines [expr {$_cur_row + 1}] $_rows
+ } elseif {$arg == 1} {
+ # Beginning of display to cursor (inclusive).
+ _clear_lines 0 $_cur_row
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire display.
+ _clear_lines 0 $_rows
}
}
+}
- # Erase in Line.
- #
- # https://vt100.net/docs/vt510-rm/EL.html
- proc _csi_K {args} {
- set arg [_default [lindex $args 0] 0]
+# Erase in Line.
+#
+# https://vt100.net/docs/vt510-rm/EL.html
+proc Term::_csi_K {args} {
+ set arg [_default [lindex $args 0] 0]
- _log_cur "Erase in Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _cols
+ _log_cur "Erase in Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- if {$arg == 0} {
- # Cursor (inclusive) to end of line.
- _clear_in_line $_cur_col $_cols $_cur_row
- } elseif {$arg == 1} {
- # Beginning of line to cursor (inclusive).
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire line.
- _clear_in_line 0 $_cols $_cur_row
- }
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of line.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ } elseif {$arg == 1} {
+ # Beginning of line to cursor (inclusive).
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire line.
+ _clear_in_line 0 $_cols $_cur_row
}
}
+}
- # Insert Line
- #
- # https://vt100.net/docs/vt510-rm/IL.html
- proc _csi_L {args} {
- set arg [_default [lindex $args 0] 1]
+# Insert Line
+#
+# https://vt100.net/docs/vt510-rm/IL.html
+proc Term::_csi_L {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Insert Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Insert Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y [expr $_rows - 2]
- set next_y [expr $y + $arg]
- while {$y >= $_cur_row} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$next_y) $_chars($x,$y)
- }
- incr y -1
- incr next_y -1
+ set y [expr $_rows - 2]
+ set next_y [expr $y + $arg]
+ while {$y >= $_cur_row} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$next_y) $_chars($x,$y)
}
-
- _clear_lines $_cur_row [expr $_cur_row + $arg]
+ incr y -1
+ incr next_y -1
}
+
+ _clear_lines $_cur_row [expr $_cur_row + $arg]
}
+}
- # Delete line.
- #
- # https://vt100.net/docs/vt510-rm/DL.html
- proc _csi_M {args} {
- set count [_default [lindex $args 0] 1]
+# Delete line.
+#
+# https://vt100.net/docs/vt510-rm/DL.html
+proc Term::_csi_M {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Delete line ($count)" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Delete line ($count)" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y $_cur_row
- set next_y [expr {$y + $count}]
- while {$next_y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- incr y
- incr next_y
+ set y $_cur_row
+ set next_y [expr {$y + $count}]
+ while {$next_y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
}
- _clear_lines $y $_rows
+ incr y
+ incr next_y
}
+ _clear_lines $y $_rows
}
+}
- # Delete Character.
- #
- # https://vt100.net/docs/vt510-rm/DCH.html
- proc _csi_P {args} {
- set count [_default [lindex $args 0] 1]
-
- _log_cur "Delete character ($count)" {
- variable _cur_row
- variable _cur_col
- variable _chars
- variable _cols
+# Delete Character.
+#
+# https://vt100.net/docs/vt510-rm/DCH.html
+proc Term::_csi_P {args} {
+ set count [_default [lindex $args 0] 1]
- # Move all characters right of the cursor N positions left.
- set out_col [expr $_cur_col]
- set in_col [expr $_cur_col + $count]
+ _log_cur "Delete character ($count)" {
+ variable _cur_row
+ variable _cur_col
+ variable _chars
+ variable _cols
- while {$in_col < $_cols} {
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- incr in_col
- incr out_col
- }
+ # Move all characters right of the cursor N positions left.
+ set out_col [expr $_cur_col]
+ set in_col [expr $_cur_col + $count]
- # Clear the rest of the line.
- _clear_in_line $out_col $_cols $_cur_row
+ while {$in_col < $_cols} {
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
+ incr in_col
+ incr out_col
}
+
+ # Clear the rest of the line.
+ _clear_in_line $out_col $_cols $_cur_row
}
+}
- # Pan Down
- #
- # https://vt100.net/docs/vt510-rm/SU.html
- proc _csi_S {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Down
+#
+# https://vt100.net/docs/vt510-rm/SU.html
+proc Term::_csi_S {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Down ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Down ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set dy 0
- set y $count
+ set dy 0
+ set y $count
- while {$y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y 1
- incr dy 1
+ while {$y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines $dy $_rows
+ incr y 1
+ incr dy 1
}
+
+ _clear_lines $dy $_rows
}
+}
- # Pan Up
- #
- # https://vt100.net/docs/vt510-rm/SD.html
- proc _csi_T {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Up
+#
+# https://vt100.net/docs/vt510-rm/SD.html
+proc Term::_csi_T {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Up ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Up ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set y [expr $_rows - $count]
- set dy $_rows
+ set y [expr $_rows - $count]
+ set dy $_rows
- while {$dy >= $count} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y -1
- incr dy -1
+ while {$dy >= $count} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines 0 $count
+ incr y -1
+ incr dy -1
}
+
+ _clear_lines 0 $count
}
+}
- # Erase chars.
- #
- # https://vt100.net/docs/vt510-rm/ECH.html
- proc _csi_X {args} {
- set n [_default [lindex $args 0] 1]
+# Erase chars.
+#
+# https://vt100.net/docs/vt510-rm/ECH.html
+proc Term::_csi_X {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Erase chars ($n)" {
- # Erase characters but don't move cursor.
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _chars
+ _log_cur "Erase chars ($n)" {
+ # Erase characters but don't move cursor.
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _chars
- set lattr [array get _attrs]
- set x $_cur_col
- for {set i 0} {$i < $n} {incr i} {
- set _chars($x,$_cur_row) [list " " $lattr]
- incr x
- }
+ set lattr [array get _attrs]
+ set x $_cur_col
+ for {set i 0} {$i < $n} {incr i} {
+ set _chars($x,$_cur_row) [list " " $lattr]
+ incr x
}
}
+}
- # Cursor Backward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CBT.html
- proc _csi_Z {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Backward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CBT.html
+proc Term::_csi_Z {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward Tabulation ($n)" {
- variable _cur_col
+ _log_cur "Cursor Backward Tabulation ($n)" {
+ variable _cur_col
- set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
- }
+ set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
}
+}
- # Repeat.
- #
- # https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
- proc _csi_b {args} {
- set n [_default [lindex $args 0] 1]
+# Repeat.
+#
+# https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
+proc Term::_csi_b {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Repeat ($n)" {
- variable _last_char
+ _log_cur "Repeat ($n)" {
+ variable _last_char
- _insert [string repeat $_last_char $n]
- }
+ _insert [string repeat $_last_char $n]
}
+}
- # Vertical Line Position Absolute.
- #
- # https://vt100.net/docs/vt510-rm/VPA.html
- proc _csi_d {args} {
- set row [_default [lindex $args 0] 1]
+# Vertical Line Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/VPA.html
+proc Term::_csi_d {args} {
+ set row [_default [lindex $args 0] 1]
- _log_cur "Vertical Line Position Absolute ($row)" {
- variable _cur_row
- variable _rows
+ _log_cur "Vertical Line Position Absolute ($row)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr min ($row - 1, $_rows - 1)]
- }
+ set _cur_row [expr min ($row - 1, $_rows - 1)]
}
+}
- # Reset the attributes in attributes array UPVAR_NAME to the default values.
- proc _reset_attrs { upvar_name } {
- upvar $upvar_name var
- array set var {
- intensity normal
- fg default
- bg default
- underline 0
- reverse 0
- invisible 0
- blinking 0
+# Set Mode (SM, CSI h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Insert Mode (IRM)
+ _log "ignored: insert mode"
+ }
+ default {
+ error unsupported
+ }
}
}
+}
- # Translate the color numbers as used in proc _csi_m to a name.
- proc _color_attr { n } {
- switch -exact -- $n {
- 0 {
- return black
+# Reset Mode (RM, CSI l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Replace Mode (IRM)
+ _log "ignored: replace mode"
+ }
+ default {
+ error unsupported
}
+ }
+ }
+}
+
+# Set Scrolling Region (DECSTBM, CSI Ps ; Ps r)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_r { top bottom } {
+ _log "ignored: set scrolling region"
+}
+
+# Window manipulation (XTWINOPS, CSI Ps ; Ps ; Ps t)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_t { arg1 arg2 arg3 } {
+ if { $arg1 == 22 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Save xterm icon and window title on stack"
+ return
+ }
+
+ if { $arg1 == 23 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Restore xterm icon and window title from stack"
+ return
+ }
+
+ error unsupported
+}
+
+# DECSET (CSI ? h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
1 {
- return red
+ _log "ignored: Application Cursor Keys"
}
- 2 {
- return green
+ 7 {
+ _log "ignored: autowrap mode"
}
- 3 {
- return yellow
+ 1000 {
+ _log "ignored: Send Mouse X & Y on button press and release"
}
- 4 {
- return blue
+ 1006 {
+ _log "ignored: Enable SGR Mouse Mode"
}
- 5 {
- return magenta
+ 1049 {
+ _log "switch to alternate screen"
+ _set_alternate 1
}
- 6 {
- return cyan
+ default {
+ error unsupported
+ }
+ }
+ }
+}
+
+# DECRST (CSI ? l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 1 {
+ _log "ignored: Normal Cursor Keys"
}
7 {
- return white
+ _log "ignored: no autowrap mode"
+ }
+ 1000 {
+ _log "ignored: Don't send Mouse X & Y on button press and release"
+ }
+ 1006 {
+ _log "ignored: Disable SGR Mouse Mode"
+ }
+ 1049 {
+ _log "switch from alternate screen"
+ _set_alternate 0
+ }
+ default {
+ error "unsupported"
}
- default { error "unsupported color number: $n" }
}
}
+}
- # Select Graphic Rendition.
- #
- # https://vt100.net/docs/vt510-rm/SGR.html
- proc _csi_m {args} {
- if { [llength $args] == 0 } {
- # Apply default.
- set args [list 0]
+# Reset the attributes in attributes array UPVAR_NAME to the default values.
+proc Term::_reset_attrs { upvar_name } {
+ upvar $upvar_name var
+ array set var {
+ intensity normal
+ fg default
+ bg default
+ underline 0
+ reverse 0
+ invisible 0
+ blinking 0
+ }
+}
+
+# Translate the color numbers as used in proc _csi_m to a name.
+proc Term::_color_attr { n } {
+ switch -exact -- $n {
+ 0 {
+ return black
+ }
+ 1 {
+ return red
+ }
+ 2 {
+ return green
}
+ 3 {
+ return yellow
+ }
+ 4 {
+ return blue
+ }
+ 5 {
+ return magenta
+ }
+ 6 {
+ return cyan
+ }
+ 7 {
+ return white
+ }
+ default { error "unsupported color number: $n" }
+ }
+}
- _log_cur "Select Graphic Rendition ([join $args {, }])" {
- variable _attrs
+# Select Graphic Rendition.
+#
+# https://vt100.net/docs/vt510-rm/SGR.html
+proc Term::_csi_m {args} {
+ if { [llength $args] == 0 } {
+ # Apply default.
+ set args [list 0]
+ }
- foreach item $args {
- switch -exact -- $item {
- "" - 0 {
- _reset_attrs _attrs
- }
- 1 {
- set _attrs(intensity) bold
- }
- 2 {
- set _attrs(intensity) dim
- }
- 4 {
- set _attrs(underline) 1
- }
- 5 {
- set _attrs(blinking) 1
- }
- 7 {
- set _attrs(reverse) 1
- }
- 8 {
- set _attrs(invisible) 1
- }
- 22 {
- set _attrs(intensity) normal
- }
- 24 {
- set _attrs(underline) 0
- }
- 25 {
- set _attrs(blinking) 0
- }
- 27 {
- set _attrs(reverse) 0
- }
- 28 {
- set _attrs(invisible) 0
- }
- 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
- set _attrs(fg) [_color_attr [expr $item - 30]]
- }
- 39 {
- set _attrs(fg) default
- }
- 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
- set _attrs(bg) [_color_attr [expr $item - 40]]
- }
- 49 {
- set _attrs(bg) default
- }
+ _log_cur "Select Graphic Rendition ([join $args {, }])" {
+ variable _attrs
+
+ foreach item $args {
+ switch -exact -- $item {
+ "" - 0 {
+ _reset_attrs _attrs
+ }
+ 1 {
+ set _attrs(intensity) bold
+ }
+ 2 {
+ set _attrs(intensity) dim
+ }
+ 4 {
+ set _attrs(underline) 1
+ }
+ 5 {
+ set _attrs(blinking) 1
+ }
+ 7 {
+ set _attrs(reverse) 1
+ }
+ 8 {
+ set _attrs(invisible) 1
+ }
+ 22 {
+ set _attrs(intensity) normal
+ }
+ 24 {
+ set _attrs(underline) 0
+ }
+ 25 {
+ set _attrs(blinking) 0
+ }
+ 27 {
+ set _attrs(reverse) 0
+ }
+ 28 {
+ set _attrs(invisible) 0
+ }
+ 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
+ set _attrs(fg) [_color_attr [expr $item - 30]]
+ }
+ 39 {
+ set _attrs(fg) default
+ }
+ 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
+ set _attrs(bg) [_color_attr [expr $item - 40]]
+ }
+ 49 {
+ set _attrs(bg) default
}
}
}
}
+}
+
+# Request Terminal Parameters (DECREQTPARM)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+# https://vt100.net/docs/vt100-ug/chapter3.html
+proc Term::_csi_x {} {
+ # Ignore.
+}
+
+# Insert string at the cursor location.
+proc Term::_insert {str} {
+ _log_cur "Inserted string '$str'" {
+ _log "Inserting string '$str'"
- # Insert string at the cursor location.
- proc _insert {str} {
- _log_cur "Inserted string '$str'" {
- _log "Inserting string '$str'"
-
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- foreach char [split $str {}] {
- _log_cur " Inserted char '$char'" {
- set _chars($_cur_col,$_cur_row) [list $char $lattr]
- incr _cur_col
- if {$_cur_col >= $_cols} {
- set _cur_col 0
- incr _cur_row
- if {$_cur_row >= $_rows} {
- error "FIXME scroll"
- }
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ foreach char [split $str {}] {
+ _log_cur " Inserted char '$char'" {
+ set _chars($_cur_col,$_cur_row) [list $char $lattr]
+ incr _cur_col
+ if {$_cur_col >= $_cols} {
+ set _cur_col 0
+ incr _cur_row
+ if {$_cur_row >= $_rows} {
+ error "FIXME scroll"
}
}
}
}
+
+ variable _last_char
+ set _last_char [string index $str end]
}
+}
- # Move the cursor to the (0-based) COL and ROW positions.
- proc _move_cursor { col row } {
- variable _cols
- variable _rows
- variable _cur_col
- variable _cur_row
+# Move the cursor to the (0-based) COL and ROW positions.
+proc Term::_move_cursor { col row } {
+ variable _cols
+ variable _rows
+ variable _cur_col
+ variable _cur_row
- if { $col < 0 || $col >= $_cols } {
- error "_move_cursor: invalid col value: $col"
- }
+ if { $col < 0 || $col >= $_cols } {
+ error "_move_cursor: invalid col value: $col"
+ }
- if { $row < 0 || $row >= $_rows } {
- error "_move_cursor: invalid row value: $row"
- }
+ if { $row < 0 || $row >= $_rows } {
+ error "_move_cursor: invalid row value: $row"
+ }
- set _cur_col $col
- set _cur_row $row
- }
+ set _cur_col $col
+ set _cur_row $row
+}
- # Initialize.
- proc _setup {rows cols} {
- global stty_init
- set stty_init "rows $rows columns $cols"
+# Enable or disable alternate screen.
+proc Term::_set_alternate { enable } {
+ variable _alternate
+ if { $enable == $_alternate } {
+ return
+ }
+ set _alternate $enable
- variable _rows
- variable _cols
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _resize_count
+ variable _attrs
+ variable _chars
+ variable _cur_col
+ variable _cur_row
- set _rows $rows
- set _cols $cols
- set _cur_col 0
- set _cur_row 0
- set _resize_count 0
- _reset_attrs _attrs
-
- _clear_lines 0 $_rows
- }
-
- # Accept some output from gdb and update the screen.
- # Return 1 if successful, or 0 if a timeout occurred.
- proc accept_gdb_output { } {
- global expect_out
- gdb_expect {
- -re "^\[\x07\x08\x0a\x0d\]" {
- scan $expect_out(0,string) %c val
- set hexval [format "%02x" $val]
- _log "wait_for: _ctl_0x${hexval}"
- _ctl_0x${hexval}
- }
- -re "^\x1b(\[0-9a-zA-Z\])" {
- _log "wait_for: unsupported escape"
- error "unsupported escape"
- }
- -re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@`\])" {
- set cmd $expect_out(2,string)
- set params [split $expect_out(1,string) ";"]
- _log "wait_for: _csi_$cmd <<<$expect_out(1,string)>>>"
- eval _csi_$cmd $params
- }
- -re "^\[^\x07\x08\x0a\x0d\x1b\]+" {
- _insert $expect_out(0,string)
- variable _last_char
- set _last_char [string index $expect_out(0,string) end]
- }
+ variable _save_attrs
+ variable _save_chars
+ variable _save_cur_col
+ variable _save_cur_row
- timeout {
- # Assume a timeout means we somehow missed the
- # expected result, and carry on.
- warning "timeout in accept_gdb_output"
- dump_screen
- return 0
- }
- }
+ variable _alternate_setup
- return 1
+ if { $_alternate_setup } {
+ set tmp $_save_chars
+ }
+ set _save_chars [array get _chars]
+ if { $_alternate_setup } {
+ array set _chars $tmp
}
- # Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
- proc debug_tui_matching { arg } {
- set debug 0
- if { [info exists ::DEBUG_TUI_MATCHING] } {
- set debug $::DEBUG_TUI_MATCHING
- }
+ if { $_alternate_setup } {
+ set tmp $_save_attrs
+ }
+ set _save_attrs [array get _attrs]
+ if { $_alternate_setup } {
+ array set _attrs $tmp
+ }
- if { ! $debug } {
- return
- }
+ if { $_alternate_setup } {
+ set tmp $_save_cur_col
+ }
+ set _save_cur_col $_cur_col
+ if { $_alternate_setup } {
+ set _cur_col $tmp
+ }
- verbose -log "$arg"
+ if { $_alternate_setup } {
+ set tmp $_save_cur_row
+ }
+ set _save_cur_row $_cur_row
+ if { $_alternate_setup } {
+ set _cur_row $tmp
}
- # Accept some output from gdb and update the screen. WAIT_FOR is
- # a regexp matching the line to wait for. Return 0 on timeout, 1
- # on success.
- proc wait_for {wait_for} {
- global gdb_prompt
- variable _cur_col
- variable _cur_row
+ if { ! $_alternate_setup } {
+ variable _rows
+ variable _cols
+ _setup $_rows $_cols
+ set _alternate_setup 1
+ }
+}
- set fn "wait_for"
+# Initialize.
+proc Term::_setup {rows cols} {
+ global stty_init
+ set stty_init "rows $rows columns $cols"
- set prompt_wait_for "(^|\\|)$gdb_prompt \$"
- if { $wait_for == "" } {
- set wait_for $prompt_wait_for
- }
+ variable _rows
+ variable _cols
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _resize_count
- debug_tui_matching "$fn: regexp: '$wait_for'"
+ set _rows $rows
+ set _cols $cols
+ set _cur_col 0
+ set _cur_row 0
+ set _resize_count 0
+ _reset_attrs _attrs
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ _clear_lines 0 $_rows
+}
- # If the cursor appears just after the prompt, return. It
- # isn't reliable to check this only after an insertion,
- # because curses may make "unusual" redrawing decisions.
- if {$wait_for == "$prompt_wait_for"} {
- set prev [get_line $_cur_row $_cur_col]
- } else {
- set prev [get_line $_cur_row]
- }
- if {[regexp -- $wait_for $prev]} {
- debug_tui_matching "$fn: match: '$prev'"
- if {$wait_for == "$prompt_wait_for"} {
- break
- }
- set wait_for $prompt_wait_for
- debug_tui_matching "$fn: regexp prompt: '$wait_for'"
- } else {
- debug_tui_matching "$fn: mismatch: '$prev'"
- }
+# Accept some output from gdb and update the screen.
+# Return 1 if successful, or 0 if a timeout occurred.
+proc Term::accept_gdb_output { {warn 1} } {
+ global expect_out
+
+ set ctls "\x07\x08\x0a\x0d"
+ set esc "\x1b"
+ set re_ctls "\[$ctls\]"
+ set re_others "\[^$esc$ctls\]"
+ set have_esc 0
+ gdb_expect {
+ -re ^$re_ctls {
+ scan $expect_out(0,string) %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _ctl_0x${hexval}"
+ _ctl_0x${hexval}
+ }
+ -re "^$esc" {
+ _log "wait_for: ESC"
+ set have_esc 1
+ }
+ -re "^$re_others+" {
+ _insert $expect_out(0,string)
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ warning "timeout in accept_gdb_output"
+ dump_screen
+ return 0
}
+ }
+ if { !$have_esc } {
return 1
}
- # Accept some output from gdb and update the screen. Wait for the screen
- # region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
- # success.
- proc wait_for_region_contents {x y width height regexp} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set re_csi [string_to_regexp "\["]
+ set have_csi 0
+ gdb_expect {
+ -re "^(\[0-9a-zA-Z\])" {
+ _log "wait_for: unsupported escape"
+ error "unsupported escape"
+ }
+ -re "^(\[\\(\])(\[a-zA-Z\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ set cmd $expect_out(2,string)
+ eval _esc_0x${hexval}_$cmd
+ }
+ -re "^(\[=>\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ _esc_0x$hexval
+ }
+ -re "^$re_csi" {
+ _log "wait_for: CSI"
+ set have_csi 1
+ }
- if { [check_region_contents_p $x $y $width $height $regexp] } {
- break
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following ESC"
+ dump_screen
}
+ _insert "^\["
+ return 0
}
+ }
+ if { !$have_csi } {
return 1
}
- # Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
- # BODY.
- proc with_tuiterm {rows cols body} {
- global env stty_init
- variable _TERM
- save_vars {env(TERM) env(NO_COLOR) stty_init} {
- if { [ishost *-*-*bsd*] } {
- setenv TERM ansiw
- } else {
- setenv TERM ansi
+ set re_csi_prefix {[?]}
+ set re_csi_args {[0-9;]}
+ set re_csi_cmd {[a-zA-Z@`]}
+ gdb_expect {
+ -re "^($re_csi_cmd)" {
+ set cmd $expect_out(1,string)
+ _log "wait_for: _csi_$cmd"
+ eval _csi_$cmd
+ }
+ -re "^($re_csi_args*)($re_csi_cmd)" {
+ set params [split $expect_out(1,string) ";"]
+ set cmd $expect_out(2,string)
+ _log "wait_for: _csi_$cmd <<<$params>>>"
+ eval _csi_$cmd $params
+ }
+ -re "^($re_csi_prefix?)($re_csi_args*)($re_csi_cmd)" {
+ set prefix $expect_out(1,string)
+ set params [split $expect_out(2,string) ";"]
+ set cmd $expect_out(3,string)
+ scan $prefix %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _csi_0x${hexval}_$cmd <<<$expect_out(1,string)>>>"
+ eval _csi_0x${hexval}_$cmd $params
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following CSI"
+ dump_screen
}
- # Save active TERM variable.
- set Term::_TERM $env(TERM)
+ _insert "^\[\["
+ return 0
+ }
+ }
- setenv NO_COLOR ""
- _setup $rows $cols
+ return 1
+}
- uplevel $body
- }
+# Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
+proc Term::debug_tui_matching { arg } {
+ set debug 0
+ if { [info exists ::DEBUG_TUI_MATCHING] } {
+ set debug $::DEBUG_TUI_MATCHING
}
- # Like ::clean_restart, but ensures that gdb starts in an
- # environment where the TUI can work. ROWS and COLS are the size
- # of the terminal. EXECUTABLE, if given, is passed to
- # clean_restart.
- proc clean_restart {rows cols {executable {}}} {
- with_tuiterm $rows $cols {
- save_vars { ::GDBFLAGS } {
- # Make GDB not print the directory names. Use this setting to
- # remove the differences in test runs due to varying directory
- # names.
- append ::GDBFLAGS " -ex \"set filename-display basename\""
+ if { ! $debug } {
+ return
+ }
- if {$executable == ""} {
- ::clean_restart
- } else {
- ::clean_restart $executable
- }
- }
+ verbose -log "$arg"
+}
- ::gdb_test_no_output "set pagination off"
- }
+# Accept some output from gdb and update the screen. WAIT_FOR is
+# a regexp matching the line to wait for. Return 0 on timeout, 1
+# on success.
+proc Term::wait_for {wait_for} {
+ global gdb_prompt
+ variable _cur_col
+ variable _cur_row
+
+ set fn "wait_for"
+
+ set prompt_wait_for "(^|\\|)$gdb_prompt \$"
+ if { $wait_for == "" } {
+ set wait_for $prompt_wait_for
}
- # Generate prompt on TUIterm.
- proc gen_prompt {} {
- # Generate a prompt.
- send_gdb "echo\n"
+ debug_tui_matching "$fn: regexp: '$wait_for'"
+
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
+ }
+
+ # If the cursor appears just after the prompt, return. It
+ # isn't reliable to check this only after an insertion,
+ # because curses may make "unusual" redrawing decisions.
+ if {$wait_for == "$prompt_wait_for"} {
+ set prev [get_line $_cur_row $_cur_col]
+ } else {
+ set prev [get_line $_cur_row]
+ }
+
+ if { ![regexp -- $wait_for $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
+ }
- # Drain the output before the prompt.
- gdb_expect {
- -re "echo\r\n" {
+ if {$wait_for == "$prompt_wait_for"} {
+ # We've detected that the cursor is just after the prompt.
+ # Now check that there's nothing else on the line.
+ set prev [get_line $_cur_row]
+ if { ![regexp -- "(^|\\|)$gdb_prompt +($|\\||\\+)" $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
}
}
- # Interpret prompt using TUIterm.
- wait_for ""
- }
+ debug_tui_matching "$fn: match: '$prev'"
- # Setup ready for starting the tui, but don't actually start it.
- # Returns 1 on success, 0 if TUI tests should be skipped.
- proc prepare_for_tui {} {
- if { [is_remote host] } {
- # In clean_restart, we're using "setenv TERM ansi", which has
- # effect on build. If we have [is_remote host] == 0, so
- # build == host, then it also has effect on host. But for
- # [is_remote host] == 1, it has no effect on host.
- return 0
+ if {$wait_for == "$prompt_wait_for"} {
+ # Matched the prompt, we're done.
+ break
}
- if {![allow_tui_tests]} {
+ # Now try to match the prompt.
+ set wait_for $prompt_wait_for
+ debug_tui_matching "$fn: regexp prompt: '$wait_for'"
+ }
+
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the screen
+# region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
+# success.
+proc Term::wait_for_region_contents {x y width height regexp} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- gdb_test_no_output "set tui border-kind ascii"
- gdb_test_no_output "maint set tui-resize-message on"
- return 1
+ if { [check_region_contents_p $x $y $width $height $regexp] } {
+ break
+ }
}
- # Start the TUI. Returns 1 on success, 0 if TUI tests should be
- # skipped.
- proc enter_tui {} {
- if {![prepare_for_tui]} {
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the current
+# screen line to match REGEXP and cursor position POS, unless POS is empty.
+# Return 0 on timeout, 1 on success.
+proc Term::wait_for_line { regexp {pos ""} } {
+ variable _cur_row
+ variable _cur_col
+ variable _cols
+
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- command_no_prompt_prefix "tui enable"
- return 1
- }
+ if { ![check_region_contents_p 0 $_cur_row $_cols 1 $regexp] } {
+ continue
+ }
- # Send the command CMD to gdb, then wait for a gdb prompt to be
- # seen in the TUI. CMD should not end with a newline -- that will
- # be supplied by this function.
- proc command {cmd} {
- global gdb_prompt
- send_gdb "$cmd\n"
- set str [string_to_regexp $cmd]
- set str "(^|\\|)$gdb_prompt $str"
- wait_for $str
- }
-
- # As proc command, but don't wait for an initial prompt. This is used for
- # initial terminal commands, where there's no prompt yet.
- proc command_no_prompt_prefix {cmd} {
- gen_prompt
- command $cmd
- }
-
- # Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
- # Return a string annotating the changed attributes.
- proc apply_attrs { upvar_name attrs } {
- set res ""
- upvar $upvar_name var
- foreach { attr val } $attrs {
- if { $var($attr) != $val } {
- append res "<$attr:$val>"
- set var($attr) $val
- }
+ if { $pos == "" || $_cur_col == $pos } {
+ break
}
+ }
+
+ return 1
+}
+
+# In BODY, when using Term::with_tuiterm, use TERM instead of the default.
- return $res
+proc Term::with_term { term body } {
+ save_vars { Term::_TERM } {
+ set Term::_TERM $term
+ uplevel $body
}
+}
- # Return the text of screen line N. Lines are 0-based. Start at column
- # X. If C is non-empty, stop before column C. Columns are also
- # zero-based. If ATTRS, annotate with attributes.
- proc get_string {n x c {attrs 0}} {
- variable _rows
- # This can happen during resizing, if the cursor seems to
- # temporarily be off-screen.
- if {$n >= $_rows} {
- return ""
+# Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
+# BODY.
+proc Term::with_tuiterm {rows cols body} {
+ global env stty_init
+ variable _TERM
+ save_vars {env(TERM) env(NO_COLOR) stty_init} {
+ if { $Term::_TERM != "" } {
+ setenv TERM $Term::_TERM
+ } elseif { [ishost *-*-*bsd*] } {
+ setenv TERM ansiw
+ } else {
+ setenv TERM ansi
}
+ # Save active TERM variable.
+ set Term::_TERM $env(TERM)
- set result ""
- variable _cols
- variable _chars
- set c [_default $c $_cols]
- if { $attrs } {
- _reset_attrs line_attrs
- }
- while {$x < $c} {
- if { $attrs } {
- set char_attrs [lindex $_chars($x,$n) 1]
- append result [apply_attrs line_attrs $char_attrs]
+ setenv NO_COLOR ""
+ _setup $rows $cols
+
+ uplevel $body
+ }
+}
+
+# Like ::clean_restart, but ensures that gdb starts in an
+# environment where the TUI can work. ROWS and COLS are the size
+# of the terminal. EXECUTABLE, if given, is passed to
+# clean_restart.
+proc Term::clean_restart {rows cols {executable {}}} {
+ with_tuiterm $rows $cols {
+ save_vars { ::GDBFLAGS } {
+ # Make GDB not print the directory names. Use this setting to
+ # remove the differences in test runs due to varying directory
+ # names.
+ append ::GDBFLAGS " -ex \"set filename-display basename\""
+
+ if {$executable == ""} {
+ ::clean_restart
+ } else {
+ ::clean_restart $executable
}
- append result [lindex $_chars($x,$n) 0]
- incr x
}
- if { $attrs } {
- _reset_attrs zero_attrs
- set char_attrs [array get zero_attrs]
- append result [apply_attrs line_attrs $char_attrs]
- }
- return $result
- }
- # Return the text of screen line N. Lines are 0-based. Start at column
- # X. If C is non-empty, stop before column C. Columns are also
- # zero-based. Annotate with attributes.
- proc get_string_with_attrs { n x c } {
- return [get_string $n $x $c 1]
+ ::gdb_test_no_output "set pagination off"
}
+}
- # Return the text of screen line N. Lines are 0-based. If C is
- # non-empty, stop before column C. Columns are also zero-based. If
- # ATTRS, annotate with attributes.
- proc get_line_1 {n c attrs} {
- return [get_string $n 0 $c $attrs]
+# Generate prompt on TUIterm.
+proc Term::gen_prompt {} {
+ # Generate a prompt.
+ send_gdb "echo\n"
+
+ # Drain the output before the prompt.
+ gdb_expect {
+ -re "echo\r\n" {
+ }
}
- # Return the text of screen line N, without attributes. Lines are
- # 0-based. If C is given, stop before column C. Columns are also
- # zero-based.
- proc get_line {n {c ""} } {
- return [get_line_1 $n $c 0]
+ # Interpret prompt using TUIterm.
+ wait_for ""
+}
+
+# Setup ready for starting the tui, but don't actually start it.
+# Returns 1 on success, 0 if TUI tests should be skipped.
+proc Term::prepare_for_tui {} {
+ if { [is_remote host] } {
+ # In clean_restart, we're using "setenv TERM ansi", which has
+ # effect on build. If we have [is_remote host] == 0, so
+ # build == host, then it also has effect on host. But for
+ # [is_remote host] == 1, it has no effect on host.
+ return 0
}
- # As get_line, but annotate with attributes.
- proc get_line_with_attrs {n {c ""}} {
- return [get_line_1 $n $c 1]
+ if {![allow_tui_tests]} {
+ return 0
}
- # Get just the character at (X, Y).
- proc get_char {x y} {
- variable _chars
- return [lindex $_chars($x,$y) 0]
+ gdb_test_no_output "set tui border-kind ascii"
+ gdb_test_no_output "maint set tui-resize-message on"
+ # When matching GDB output using Term::wait_for, the number of
+ # matching attempts in wait_for can be influenced by CLI styling.
+ # Disable it by default to avoid this.
+ gdb_test_no_output "set style enabled off"
+ return 1
+}
+
+# Start the TUI. Returns 1 on success, 0 if TUI tests should be
+# skipped.
+proc Term::enter_tui {} {
+ if {![prepare_for_tui]} {
+ return 0
}
- # Get the entire screen as a string.
- proc get_all_lines {} {
- variable _rows
- variable _cols
- variable _chars
+ command_no_prompt_prefix "tui enable"
+ return 1
+}
- set result ""
- for {set y 0} {$y < $_rows} {incr y} {
- for {set x 0} {$x < $_cols} {incr x} {
- append result [lindex $_chars($x,$y) 0]
- }
- append result "\n"
+# Send the command CMD to gdb, then wait for a gdb prompt to be
+# seen in the TUI. CMD should not end with a newline -- that will
+# be supplied by this function.
+proc Term::command {cmd} {
+ global gdb_prompt
+ send_gdb "$cmd\n"
+ set str [string_to_regexp $cmd]
+ set str "(^|\\|)$gdb_prompt $str"
+ wait_for $str
+}
+
+# As proc command, but don't wait for an initial prompt. This is used for
+# initial terminal commands, where there's no prompt yet.
+proc Term::command_no_prompt_prefix {cmd} {
+ gen_prompt
+ command $cmd
+}
+
+# Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
+# Return a string annotating the changed attributes.
+proc Term::apply_attrs { upvar_name attrs } {
+ set res ""
+ upvar $upvar_name var
+ foreach { attr val } $attrs {
+ if { $var($attr) != $val } {
+ append res "<$attr:$val>"
+ set var($attr) $val
}
+ }
- return $result
+ return $res
+}
+
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. If ATTRS, annotate with attributes.
+proc Term::get_string {n x c {attrs 0}} {
+ variable _rows
+ # This can happen during resizing, if the cursor seems to
+ # temporarily be off-screen.
+ if {$n >= $_rows} {
+ return ""
}
- # Get the text just before the cursor.
- proc get_current_line {} {
- variable _cur_col
- variable _cur_row
- return [get_line $_cur_row $_cur_col]
+ set result ""
+ variable _cols
+ variable _chars
+ set c [_default $c $_cols]
+ if { $attrs } {
+ _reset_attrs line_attrs
+ }
+ while {$x < $c} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($x,$n) 1]
+ append result [apply_attrs line_attrs $char_attrs]
+ }
+ append result [lindex $_chars($x,$n) 0]
+ incr x
}
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs line_attrs $char_attrs]
+ }
+ return $result
+}
- # Helper function for check_box. Returns empty string if the box
- # is found, description of why not otherwise.
- proc _check_box {x y width height} {
- set x2 [expr {$x + $width - 1}]
- set y2 [expr {$y + $height - 1}]
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. Annotate with attributes.
+proc Term::get_string_with_attrs { n x c } {
+ return [get_string $n $x $c 1]
+}
- verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+# Return the text of screen line N. Lines are 0-based. If C is
+# non-empty, stop before column C. Columns are also zero-based. If
+# ATTRS, annotate with attributes.
+proc Term::get_line_1 {n c attrs} {
+ return [get_string $n 0 $c $attrs]
+}
- set c [get_char $x $y]
- if {$c != "+"} {
- return "ul corner is $c, not +"
- }
+# Return the text of screen line N, without attributes. Lines are
+# 0-based. If C is given, stop before column C. Columns are also
+# zero-based.
+proc Term::get_line {n {c ""} } {
+ return [get_line_1 $n $c 0]
+}
- set c [get_char $x $y2]
- if {$c != "+"} {
- return "ll corner is $c, not +"
- }
+# As get_line, but annotate with attributes.
+proc Term::get_line_with_attrs {n {c ""}} {
+ return [get_line_1 $n $c 1]
+}
- set c [get_char $x2 $y]
- if {$c != "+"} {
- return "ur corner is $c, not +"
- }
+# Get just the character at (X, Y).
+proc Term::get_char {x y} {
+ variable _chars
+ return [lindex $_chars($x,$y) 0]
+}
- set c [get_char $x2 $y2]
- if {$c != "+"} {
- return "lr corner is $c, not +"
- }
+# Get the entire screen as a string.
+proc Term::get_all_lines {} {
+ variable _rows
+ variable _cols
+ variable _chars
- # Note we do not check the full horizonal borders of the box.
- # The top will contain a title, and the bottom may as well, if
- # it is overlapped by some other border. However, at most a
- # title should appear as '+-VERY LONG TITLE-+', so we can
- # check for the '+-' on the left, and '-+' on the right.
- set c [get_char [expr {$x + 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
+ set result ""
+ for {set y 0} {$y < $_rows} {incr y} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ append result [lindex $_chars($x,$y) 0]
}
+ append result "\n"
+ }
- set c [get_char [expr {$x2 - 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
- }
+ return $result
+}
- # Now check the vertical borders.
- for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
- set c [get_char $x $i]
- if {$c != "|"} {
- return "left side $i is $c, not |"
- }
+# Get the text just before the cursor.
+proc Term::get_current_line {} {
+ variable _cur_col
+ variable _cur_row
+ return [get_line $_cur_row $_cur_col]
+}
- set c [get_char $x2 $i]
- if {$c != "|"} {
- return "right side $i is $c, not |"
- }
- }
+# Helper function for check_box. Returns empty string if the box
+# is found, description of why not otherwise.
+proc Term::_check_box {x y width height} {
+ set x2 [expr {$x + $width - 1}]
+ set y2 [expr {$y + $height - 1}]
- return ""
+ verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+
+ set c [get_char $x $y]
+ if {$c != "+"} {
+ return "ul corner is $c, not +"
}
- # Check for a box at the given coordinates.
- proc check_box {test_name x y width height} {
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- } else {
- fail "$test_name ($why)"
- }
+ set c [get_char $x $y2]
+ if {$c != "+"} {
+ return "ll corner is $c, not +"
}
- # Wait until a box appears at the given coordinates.
- proc wait_for_box {test_name x y width height} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set c [get_char $x2 $y]
+ if {$c != "+"} {
+ return "ur corner is $c, not +"
+ }
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- break
- }
- }
+ set c [get_char $x2 $y2]
+ if {$c != "+"} {
+ return "lr corner is $c, not +"
}
- # Check whether the text contents of the terminal match the
- # regular expression. Note that text styling is not considered.
- proc check_contents {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {[regexp -- $regexp $contents]} $test_name
+ # Note we do not check the full horizonal borders of the box.
+ # The top will contain a title, and the bottom may as well, if
+ # it is overlapped by some other border. However, at most a
+ # title should appear as '+-VERY LONG TITLE-+', so we can
+ # check for the '+-' on the left, and '-+' on the right.
+ set c [get_char [expr {$x + 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # As check_contents, but check that the text contents of the terminal does
- # not match the regular expression.
- proc check_contents_not {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {![regexp -- $regexp $contents]} $test_name
+ set c [get_char [expr {$x2 - 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # Get the region of the screen described by X, Y, WIDTH, and
- # HEIGHT, and separate the lines using SEP. If ATTRS is true then
- # include attribute information in the output.
- proc get_region { x y width height sep { attrs false } } {
- variable _chars
+ # Now check the vertical borders.
+ for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
+ set c [get_char $x $i]
+ if {$c != "|"} {
+ return "left side $i is $c, not |"
+ }
- if { $attrs } {
- _reset_attrs region_attrs
+ set c [get_char $x2 $i]
+ if {$c != "|"} {
+ return "right side $i is $c, not |"
}
+ }
- # Grab the contents of the box, join each line together
- # using $sep.
- set result ""
- for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} {
- if {$yy > $y} {
- # Add the end of line sequence only if this isn't the
- # first line.
- append result $sep
- }
- for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} {
- if { $attrs } {
- set char_attrs [lindex $_chars($xx,$yy) 1]
- append result [apply_attrs region_attrs $char_attrs]
- }
+ return ""
+}
- append result [get_char $xx $yy]
- }
+# Check for a box at the given coordinates.
+proc Term::check_box {test_name x y width height} {
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ } else {
+ fail "$test_name ($why)"
+ }
+}
+
+# Wait until a box appears at the given coordinates.
+proc Term::wait_for_box {test_name x y width height} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
}
- if { $attrs } {
- _reset_attrs zero_attrs
- set char_attrs [array get zero_attrs]
- append result [apply_attrs region_attrs $char_attrs]
+
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ break
}
- return $result
}
+}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. This is like check_contents except
- # only part of the screen is checked. This can be used to check
- # the contents within a box (though check_box_contents is a better
- # choice for boxes with a border). Return 1 if check succeeded.
- proc check_region_contents_p { x y width height regexp } {
- variable _chars
- dump_box $x $y $width $height
+# Check whether the text contents of the terminal match the
+# regular expression. Note that text styling is not considered.
+proc Term::check_contents {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {[regexp -- $regexp $contents]} $test_name
+}
- # Now grab the contents of the box, join each line together
- # with a '\r\n' sequence and match against REGEXP.
- set result [get_region $x $y $width $height "\r\n"]
- return [regexp -- $regexp $result]
- }
+# As check_contents, but check that the text contents of the terminal does
+# not match the regular expression.
+proc Term::check_contents_not {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {![regexp -- $regexp $contents]} $test_name
+}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. As check_region_contents_p, but produce
- # a pass/fail message.
- proc check_region_contents { test_name x y width height regexp } {
- set ok [check_region_contents_p $x $y $width $height $regexp]
- gdb_assert {$ok} $test_name
- }
+# Get the region of the screen described by X, Y, WIDTH, and
+# HEIGHT, and separate the lines using SEP. If ATTRS is true then
+# include attribute information in the output.
+proc Term::get_region { x y width height sep { attrs false } } {
+ variable _chars
- # Check the contents of a box on the screen. This is a little
- # like check_contents, but doesn't check the whole screen
- # contents, only the contents of a single box. This procedure
- # includes (effectively) a call to check_box to ensure there is a
- # box where expected, if there is then the contents of the box are
- # matched against REGEXP.
- proc check_box_contents {test_name x y width height regexp} {
- variable _chars
+ if { $attrs } {
+ _reset_attrs region_attrs
+ }
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why != ""} {
- fail "$test_name (box check: $why)"
- return
+ # Grab the contents of the box, join each line together
+ # using $sep.
+ set result ""
+ for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} {
+ if {$yy > $y} {
+ # Add the end of line sequence only if this isn't the
+ # first line.
+ append result $sep
}
+ for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($xx,$yy) 1]
+ append result [apply_attrs region_attrs $char_attrs]
+ }
- check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
- [expr {$width - 2}] [expr {$height - 2}] $regexp
+ append result [get_char $xx $yy]
+ }
+ }
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs region_attrs $char_attrs]
}
+ return $result
+}
- # A debugging function to dump the current screen, with line
- # numbers. If ATTRS, annotate with attributes.
- proc dump_screen { {attrs 0} } {
- variable _rows
- variable _cols
- variable _cur_row
- variable _cur_col
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. This is like check_contents except
+# only part of the screen is checked. This can be used to check
+# the contents within a box (though check_box_contents is a better
+# choice for boxes with a border). Return 1 if check succeeded.
+proc Term::check_region_contents_p { x y width height regexp } {
+ variable _chars
+ dump_box $x $y $width $height
- verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+ # Now grab the contents of the box, join each line together
+ # with a '\r\n' sequence and match against REGEXP.
+ set result [get_region $x $y $width $height "\r\n"]
+ return [regexp -- $regexp $result]
+}
- for {set y 0} {$y < $_rows} {incr y} {
- set fmt [format %5d $y]
- verbose -log "$fmt [get_line_1 $y {} $attrs]"
- }
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. As check_region_contents_p, but produce
+# a pass/fail message.
+proc Term::check_region_contents { test_name x y width height regexp } {
+ set ok [check_region_contents_p $x $y $width $height $regexp]
+ gdb_assert {$ok} $test_name
+}
+
+# Check the contents of a box on the screen. This is a little
+# like check_contents, but doesn't check the whole screen
+# contents, only the contents of a single box. This procedure
+# includes (effectively) a call to check_box to ensure there is a
+# box where expected, if there is then the contents of the box are
+# matched against REGEXP.
+proc Term::check_box_contents {test_name x y width height regexp} {
+ variable _chars
+
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why != ""} {
+ fail "$test_name (box check: $why)"
+ return
}
- # As dump_screen, but with attributes annotation.
- proc dump_screen_with_attrs {} {
- return [dump_screen 1]
+ check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
+ [expr {$width - 2}] [expr {$height - 2}] $regexp
+}
+
+# A debugging function to dump the current screen, with line
+# numbers. If ATTRS, annotate with attributes.
+proc Term::dump_screen { {attrs 0} } {
+ variable _rows
+ variable _cols
+ variable _cur_row
+ variable _cur_col
+
+ verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+
+ for {set y 0} {$y < $_rows} {incr y} {
+ set fmt [format %5d $y]
+ verbose -log "$fmt [get_line_1 $y {} $attrs]"
}
+}
- # A debugging function to dump a box from the current screen, with line
- # numbers.
- proc dump_box { x y width height } {
- verbose -log "Box Dump ($width x $height) @ ($x, $y):"
- set region [get_region $x $y $width $height "\n"]
- set lines [split $region "\n"]
- set nr $y
- foreach line $lines {
- set fmt [format %5d $nr]
- verbose -log "$fmt $line"
- incr nr
- }
+# As dump_screen, but with attributes annotation.
+proc Term::dump_screen_with_attrs {} {
+ return [dump_screen 1]
+}
+
+# A debugging function to dump a box from the current screen, with line
+# numbers.
+proc Term::dump_box { x y width height } {
+ verbose -log "Box Dump ($width x $height) @ ($x, $y):"
+ set region [get_region $x $y $width $height "\n"]
+ set lines [split $region "\n"]
+ set nr $y
+ foreach line $lines {
+ set fmt [format %5d $nr]
+ verbose -log "$fmt $line"
+ incr nr
}
+}
- # Resize the terminal.
- proc _do_resize {rows cols} {
- variable _chars
- variable _rows
- variable _cols
+# Resize the terminal.
+proc Term::_do_resize {rows cols} {
+ variable _chars
+ variable _rows
+ variable _cols
- set old_rows [expr {min ($_rows, $rows)}]
- set old_cols [expr {min ($_cols, $cols)}]
+ set old_rows [expr {min ($_rows, $rows)}]
+ set old_cols [expr {min ($_cols, $cols)}]
- # Copy locally.
- array set local_chars [array get _chars]
- unset _chars
+ # Copy locally.
+ array set local_chars [array get _chars]
+ unset _chars
- set _rows $rows
- set _cols $cols
- _clear_lines 0 $_rows
+ set _rows $rows
+ set _cols $cols
+ _clear_lines 0 $_rows
- for {set x 0} {$x < $old_cols} {incr x} {
- for {set y 0} {$y < $old_rows} {incr y} {
- set _chars($x,$y) $local_chars($x,$y)
- }
+ for {set x 0} {$x < $old_cols} {incr x} {
+ for {set y 0} {$y < $old_rows} {incr y} {
+ set _chars($x,$y) $local_chars($x,$y)
}
}
+}
- proc resize {rows cols {wait_for_msg 1}} {
- variable _rows
- variable _cols
- variable _resize_count
+proc Term::resize {rows cols {wait_for_msg 1}} {
+ variable _rows
+ variable _cols
+ variable _resize_count
- # expect handles each argument to stty separately. This means
- # that gdb will see SIGWINCH twice. Rather than rely on this
- # behavior (which, after all, could be changed), we make it
- # explicit here. This also simplifies waiting for the redraw.
- _do_resize $rows $_cols
- stty rows $_rows < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- _do_resize $_rows $cols
- stty columns $_cols < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- }
+ # expect handles each argument to stty separately. This means
+ # that gdb will see SIGWINCH twice. Rather than rely on this
+ # behavior (which, after all, could be changed), we make it
+ # explicit here. This also simplifies waiting for the redraw.
+ _do_resize $rows $_cols
+ stty rows $_rows < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
+ _do_resize $_rows $cols
+ stty columns $_cols < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
}
diff --git a/gdb/top.c b/gdb/top.c
index b097683..b34f291 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1312,7 +1312,7 @@ print_gdb_version (struct ui_file *stream, bool interactive)
/* Second line is a copyright notice. */
gdb_printf (stream,
- "Copyright (C) 2024 Free Software Foundation, Inc.\n");
+ "Copyright (C) 2025 Free Software Foundation, Inc.\n");
/* Following the copyright is a brief statement that the program is
free software, that users are free to copy and change it on
@@ -1596,6 +1596,11 @@ This GDB was configured as follows:\n\
--with-system-gdbinit-dir=%s%s\n\
"), SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE ? " (relocatable)" : "");
+#ifdef SUPPORTED_BINARY_FILE_FORMATS
+ gdb_printf (stream, _("\
+ --enable-binary-file-formats=%s\n"), SUPPORTED_BINARY_FILE_FORMATS);
+#endif
+
/* We assume "relocatable" will be printed at least once, thus we always
print this text. It's a reasonably safe assumption for now. */
gdb_printf (stream, _("\n\
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index c0f1eae..89f7414 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -208,16 +208,16 @@ set_tracepoint_num (int num)
static void
set_traceframe_context (const frame_info_ptr &trace_frame)
{
- CORE_ADDR trace_pc;
+ std::optional<CORE_ADDR> trace_pc;
struct symbol *traceframe_fun;
symtab_and_line traceframe_sal;
/* Save as globals for internal use. */
if (trace_frame != NULL
- && get_frame_pc_if_available (trace_frame, &trace_pc))
+ && (trace_pc = get_frame_pc_if_available (trace_frame)))
{
- traceframe_sal = find_pc_line (trace_pc, 0);
- traceframe_fun = find_pc_function (trace_pc);
+ traceframe_sal = find_pc_line (*trace_pc, 0);
+ traceframe_fun = find_pc_function (*trace_pc);
/* Save linenumber as "$trace_line", a debugger variable visible to
users. */
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 627f71c..07453b4 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -100,6 +100,9 @@ tui_disassemble (struct gdbarch *gdbarch,
{
bool term_out = disassembler_styling && gdb_stdout->can_emit_style_escape ();
string_file gdb_dis_out (term_out);
+ struct ui_file *stream = (addr_size == nullptr
+ ? (decltype (stream))&null_stream
+ : (decltype (stream))&gdb_dis_out);
/* Must start with an empty list. */
asm_lines.clear ();
@@ -108,11 +111,13 @@ tui_disassemble (struct gdbarch *gdbarch,
for (int i = 0; i < count; ++i)
{
tui_asm_line tal;
- CORE_ADDR orig_pc = pc;
+
+ /* Save the instruction address. */
+ tal.addr = pc;
try
{
- pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
+ pc += gdb_print_insn (gdbarch, pc, stream, NULL);
}
catch (const gdb_exception_error &except)
{
@@ -124,25 +129,24 @@ tui_disassemble (struct gdbarch *gdbarch,
return pc;
}
+ /* If that's all we need, continue. */
+ if (addr_size == nullptr)
+ {
+ asm_lines.push_back (std::move (tal));
+ continue;
+ }
+
/* Capture the disassembled instruction. */
tal.insn = gdb_dis_out.release ();
/* And capture the address the instruction is at. */
- tal.addr = orig_pc;
- print_address (gdbarch, orig_pc, &gdb_dis_out);
+ print_address (gdbarch, tal.addr, &gdb_dis_out);
tal.addr_string = gdb_dis_out.release ();
+ tal.addr_size = (term_out
+ ? len_without_escapes (tal.addr_string)
+ : tal.addr_string.size ());
- if (addr_size != nullptr)
- {
- size_t new_size;
-
- if (term_out)
- new_size = len_without_escapes (tal.addr_string);
- else
- new_size = tal.addr_string.size ();
- *addr_size = std::max (*addr_size, new_size);
- tal.addr_size = new_size;
- }
+ *addr_size = std::max (*addr_size, tal.addr_size);
asm_lines.push_back (std::move (tal));
}
diff --git a/gdb/tui/tui-status.c b/gdb/tui/tui-status.c
index c2d3873..1e09975 100644
--- a/gdb/tui/tui-status.c
+++ b/gdb/tui/tui-status.c
@@ -271,10 +271,14 @@ tui_show_frame_info (const frame_info_ptr &fi)
symtab_and_line sal = find_frame_sal (fi);
const char *func_name;
+ std::optional<CORE_ADDR> tmp_pc = get_frame_pc_if_available (fi);
/* find_frame_sal does not always set PC, but we want to ensure
that it is available in the SAL. */
- if (get_frame_pc_if_available (fi, &sal.pc))
- func_name = tui_get_function_from_frame (fi);
+ if (tmp_pc.has_value ())
+ {
+ sal.pc = *tmp_pc;
+ func_name = tui_get_function_from_frame (fi);
+ }
else
func_name = _("<unavailable>");
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index a545c48..618d72b 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -461,7 +461,9 @@ tui_source_window_base::rerender ()
/* find_frame_sal does not always set SAL.PC, but we want to ensure
that it is available in the SAL before updating the window. */
- get_frame_pc_if_available (frame, &sal.pc);
+ std::optional<CORE_ADDR> tmp_pc = get_frame_pc_if_available (frame);
+ if (tmp_pc.has_value ())
+ sal.pc = *tmp_pc;
maybe_update (get_frame_arch (frame), sal);
update_exec_info (false);
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 5883d6c..01aee2f 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -125,6 +125,19 @@ tui_rl_switch_mode (int notused1, int notused2)
}
else
{
+ /* If we type "foo", entering it into the readline buffer
+
+ (gdb) foo
+ ^
+ and then switch to TUI and back, we may get back
+
+ (gdb) foo
+ ^
+ which is confusing because "foo" is no longer part of the
+ readline buffer. Fix this by clearing it before switching to
+ TUI. */
+ rl_clear_visible_line ();
+
/* If tui_enable throws, we'll re-prep below. */
rl_deprep_terminal ();
tui_enable ();
diff --git a/gdb/valops.c b/gdb/valops.c
index 88f3e32..c260a79 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -45,9 +45,6 @@
/* Local functions. */
-static int typecmp (bool staticp, bool varargs, int nargs,
- struct field t1[], const gdb::array_view<value *> t2);
-
static struct value *search_struct_field (const char *, struct value *,
struct type *, int);
@@ -1766,7 +1763,7 @@ value_string (const gdb_byte *ptr, ssize_t count, struct type *char_type)
/* See if we can pass arguments in T2 to a function which takes arguments
- of types T1. T1 is a list of NARGS arguments, and T2 is an array_view
+ of types T1. T1 is an array_view of arguments, and T2 is an array_view
of the values we're trying to pass. If some arguments need coercion of
some sort, then the coerced values are written into T2. Return value is
0 if the arguments could be matched, or the position at which they
@@ -1783,8 +1780,8 @@ value_string (const gdb_byte *ptr, ssize_t count, struct type *char_type)
requested operation is type secure, shouldn't we? FIXME. */
static int
-typecmp (bool staticp, bool varargs, int nargs,
- struct field t1[], gdb::array_view<value *> t2)
+typecmp (bool staticp, bool varargs,
+ gdb::array_view<struct field> t1, gdb::array_view<value *> t2)
{
int i;
@@ -1794,7 +1791,7 @@ typecmp (bool staticp, bool varargs, int nargs,
t2 = t2.slice (1);
for (i = 0;
- (i < nargs) && t1[i].type ()->code () != TYPE_CODE_VOID;
+ (i < t1.size ()) && t1[i].type ()->code () != TYPE_CODE_VOID;
i++)
{
struct type *tt1, *tt2;
@@ -2227,7 +2224,6 @@ search_struct_method (const char *name, struct value **arg1p,
gdb_assert (args.has_value ());
if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
TYPE_FN_FIELD_TYPE (f, j)->has_varargs (),
- TYPE_FN_FIELD_TYPE (f, j)->num_fields (),
TYPE_FN_FIELD_ARGS (f, j), *args))
{
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))