branch'.
Cherrypick from master 2004-02-09 10:55:24 UTC Michael Chastain <mec@google.com> '2004-02-09 Michael Chastain <mec.gnu@mindspring.com>':
gdb/auxv.c
gdb/auxv.h
gdb/config/sparc/obsd.mt
gdb/config/sparc/obsd64.mt
gdb/sparc64obsd-tdep.c
gdb/sparcobsd-tdep.c
gdb/testsuite/gdb.asm/openbsd.inc
gdb/testsuite/gdb.base/chng-syms.c
gdb/testsuite/gdb.base/chng-syms.exp
gdb/testsuite/gdb.base/pending.c
gdb/testsuite/gdb.base/pending.exp
gdb/testsuite/gdb.base/pendshr.c
gdb/testsuite/gdb.threads/thread-specific.c
gdb/testsuite/gdb.threads/thread-specific.exp
gdb/tui/tui-command.c
gdb/tui/tui-command.h
gdb/tui/tui-data.c
gdb/tui/tui-data.h
gdb/tui/tui-disasm.c
gdb/tui/tui-disasm.h
gdb/tui/tui-io.c
gdb/tui/tui-io.h
gdb/tui/tui-layout.c
gdb/tui/tui-layout.h
gdb/tui/tui-regs.c
gdb/tui/tui-regs.h
gdb/tui/tui-source.c
gdb/tui/tui-source.h
gdb/tui/tui-stack.c
gdb/tui/tui-stack.h
gdb/tui/tui-win.c
gdb/tui/tui-win.h
gdb/tui/tui-windata.c
gdb/tui/tui-windata.h
gdb/tui/tui-wingeneral.c
gdb/tui/tui-wingeneral.h
gdb/tui/tui-winsource.c
gdb/tui/tui-winsource.h
sim/testsuite/sim/mips/ChangeLog
sim/testsuite/sim/mips/basic.exp
sim/testsuite/sim/mips/sanity.s
sim/testsuite/sim/mips/testutils.inc
--- /dev/null
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+ Copyright 2004 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "target.h"
+#include "gdbtypes.h"
+#include "command.h"
+#include "inferior.h"
+#include "valprint.h"
+#include "gdb_assert.h"
+
+#include "auxv.h"
+#include "elf/common.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+
+/* This function is called like a to_xfer_partial hook,
+ but must be called with TARGET_OBJECT_AUXV.
+ It handles access via /proc/PID/auxv, which is the common method.
+ This function is appropriate for doing:
+ #define NATIVE_XFER_AUXV procfs_xfer_auxv
+ for a native target that uses inftarg.c's child_xfer_partial hook. */
+
+LONGEST
+procfs_xfer_auxv (struct target_ops *ops,
+ int /* enum target_object */ object,
+ const char *annex,
+ void *readbuf,
+ const void *writebuf,
+ ULONGEST offset,
+ LONGEST len)
+{
+ char *pathname;
+ int fd;
+ LONGEST n;
+
+ gdb_assert (object == TARGET_OBJECT_AUXV);
+ gdb_assert (readbuf || writebuf);
+
+ pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
+ fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
+ xfree (pathname);
+ if (fd < 0)
+ return -1;
+
+ if (offset != (ULONGEST) 0
+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+ n = -1;
+ else if (readbuf != NULL)
+ n = read (fd, readbuf, len);
+ else
+ n = write (fd, writebuf, len);
+
+ (void) close (fd);
+
+ return n;
+}
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+ stored in *DATA. Return the size in bytes of this data.
+ If zero, there is no data and *DATA is null.
+ if < 0, there was an error and *DATA is null. */
+LONGEST
+target_auxv_read (struct target_ops *ops, char **data)
+{
+ size_t auxv_alloc = 512, auxv_pos = 0;
+ char *auxv = xmalloc (auxv_alloc);
+ int n;
+
+ while (1)
+ {
+ n = target_read_partial (ops, TARGET_OBJECT_AUXV,
+ NULL, &auxv[auxv_pos], 0,
+ auxv_alloc - auxv_pos);
+ if (n <= 0)
+ break;
+ auxv_pos += n;
+ if (auxv_pos < auxv_alloc) /* Read all there was. */
+ break;
+ gdb_assert (auxv_pos == auxv_alloc);
+ auxv_alloc *= 2;
+ auxv = xrealloc (auxv, auxv_alloc);
+ }
+
+ if (auxv_pos == 0)
+ {
+ xfree (auxv);
+ *data = NULL;
+ return n;
+ }
+
+ *data = auxv;
+ return auxv_pos;
+}
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+ Return 0 if *READPTR is already at the end of the buffer.
+ Return -1 if there is insufficient buffer for a whole entry.
+ Return 1 if an entry was read into *TYPEP and *VALP. */
+int
+target_auxv_parse (struct target_ops *ops, char **readptr, char *endptr,
+ CORE_ADDR *typep, CORE_ADDR *valp)
+{
+ const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
+ char *ptr = *readptr;
+
+ if (endptr == ptr)
+ return 0;
+
+ if (endptr - ptr < sizeof_auxv_field * 2)
+ return -1;
+
+ *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
+ ptr += sizeof_auxv_field;
+ *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
+ ptr += sizeof_auxv_field;
+
+ *readptr = ptr;
+ return 1;
+}
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+ Return zero if no such entry was found, or -1 if there was
+ an error getting the information. On success, return 1 after
+ storing the entry's value field in *VALP. */
+int
+target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
+{
+ CORE_ADDR type, val;
+ char *data;
+ int n = target_auxv_read (ops, &data);
+ char *ptr = data;
+ int ents = 0;
+
+ if (n <= 0)
+ return n;
+
+ while (1)
+ switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
+ {
+ case 1: /* Here's an entry, check it. */
+ if (type == match)
+ {
+ xfree (data);
+ *valp = val;
+ return 1;
+ }
+ break;
+ case 0: /* End of the vector. */
+ xfree (data);
+ return 0;
+ default: /* Bogosity. */
+ xfree (data);
+ return -1;
+ }
+
+ /*NOTREACHED*/
+}
+
+
+/* Print the contents of the target's AUXV on the specified file. */
+int
+fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
+{
+ CORE_ADDR type, val;
+ char *data;
+ int len = target_auxv_read (ops, &data);
+ char *ptr = data;
+ int ents = 0;
+
+ if (len <= 0)
+ return len;
+
+ while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
+ {
+ extern int addressprint;
+ const char *name = "???";
+ const char *description = "";
+ enum { dec, hex, str } flavor = hex;
+
+ switch (type)
+ {
+#define TAG(tag, text, kind) \
+ case tag: name = #tag; description = text; flavor = kind; break
+ TAG (AT_NULL, "End of vector", hex);
+ TAG (AT_IGNORE, "Entry should be ignored", hex);
+ TAG (AT_EXECFD, "File descriptor of program", dec);
+ TAG (AT_PHDR, "Program headers for program", hex);
+ TAG (AT_PHENT, "Size of program header entry", dec);
+ TAG (AT_PHNUM, "Number of program headers", dec);
+ TAG (AT_PAGESZ, "System page size", dec);
+ TAG (AT_BASE, "Base address of interpreter", hex);
+ TAG (AT_FLAGS, "Flags", hex);
+ TAG (AT_ENTRY, "Entry point of program", hex);
+ TAG (AT_NOTELF, "Program is not ELF", dec);
+ TAG (AT_UID, "Real user ID", dec);
+ TAG (AT_EUID, "Effective user ID", dec);
+ TAG (AT_GID, "Real group ID", dec);
+ TAG (AT_EGID, "Effective group ID", dec);
+ TAG (AT_CLKTCK, "Frequency of times()", dec);
+ TAG (AT_PLATFORM, "String identifying platform", str);
+ TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex);
+ TAG (AT_FPUCW, "Used FPU control word", dec);
+ TAG (AT_DCACHEBSIZE, "Data cache block size", dec);
+ TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec);
+ TAG (AT_UCACHEBSIZE, "Unified cache block size", dec);
+ TAG (AT_IGNOREPPC, "Entry should be ignored", dec);
+ TAG (AT_SYSINFO, "Special system info/entry points", hex);
+ TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex);
+ TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec);
+ TAG (AT_SUN_UID, "Effective user ID", dec);
+ TAG (AT_SUN_RUID, "Real user ID", dec);
+ TAG (AT_SUN_GID, "Effective group ID", dec);
+ TAG (AT_SUN_RGID, "Real group ID", dec);
+ TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex);
+ TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex);
+ TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str);
+ TAG (AT_SUN_LPAGESZ, "Large pagesize", dec);
+ TAG (AT_SUN_PLATFORM, "Platform name string", str);
+ TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex);
+ TAG (AT_SUN_IFLUSH, "Should flush icache?", dec);
+ TAG (AT_SUN_CPU, "CPU name string", str);
+ TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex);
+ TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec);
+ TAG (AT_SUN_EXECNAME,
+ "Canonicalized file name given to execve", str);
+ TAG (AT_SUN_MMU, "String for name of MMU module", str);
+ TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex);
+ }
+
+ fprintf_filtered (file, "%-4s %-20s %-30s ",
+ paddr_d (type), name, description);
+ switch (flavor)
+ {
+ case dec:
+ fprintf_filtered (file, "%s\n", paddr_d (val));
+ break;
+ case hex:
+ fprintf_filtered (file, "0x%s\n", paddr_nz (val));
+ break;
+ case str:
+ if (addressprint)
+ fprintf_filtered (file, "0x%s", paddr_nz (val));
+ val_print_string (val, -1, 1, file);
+ fprintf_filtered (file, "\n");
+ break;
+ }
+ ++ents;
+ }
+
+ xfree (data);
+
+ return ents;
+}
+
+static void
+info_auxv_command (char *cmd, int from_tty)
+{
+
+ if (! target_has_stack)
+ error ("The program has no auxiliary information now.");
+ else
+ {
+ int ents = fprint_target_auxv (gdb_stdout, ¤t_target);
+ if (ents < 0)
+ error ("No auxilary vector found, or failed reading it.");
+ else if (ents == 0)
+ error ("Auxilary vector is empty.");
+ }
+}
+
+
+extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
+
+void
+_initialize_auxv (void)
+{
+ add_info ("auxv", info_auxv_command,
+ "Display the inferior's auxiliary vector.\n\
+This is information provided by the operating system at program startup.");
+}
--- /dev/null
+/* Auxiliary vector support for GDB, the GNU debugger.
+
+ Copyright 2004 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef AUXV_H
+#define AUXV_H
+
+/* See "include/elf/common.h" for the definition of valid AT_* values. */
+
+
+/* Avoid miscellaneous includes in this file, so that it can be
+ included by nm-*.h for the procfs_xfer_auxv decl if that is
+ used in NATIVE_XFER_AUXV. */
+struct target_ops; /* Forward declaration. */
+
+
+/* Read all the auxv data into a contiguous xmalloc'd buffer,
+ stored in *DATA. Return the size in bytes of this data.
+ If zero, there is no data and *DATA is null.
+ if < 0, there was an error and *DATA is null. */
+extern LONGEST target_auxv_read (struct target_ops *ops, char **data);
+
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+ Return 0 if *READPTR is already at the end of the buffer.
+ Return -1 if there is insufficient buffer for a whole entry.
+ Return 1 if an entry was read into *TYPEP and *VALP. */
+extern int target_auxv_parse (struct target_ops *ops,
+ char **readptr, char *endptr,
+ CORE_ADDR *typep, CORE_ADDR *valp);
+
+/* Extract the auxiliary vector entry with a_type matching MATCH.
+ Return zero if no such entry was found, or -1 if there was
+ an error getting the information. On success, return 1 after
+ storing the entry's value field in *VALP. */
+extern int target_auxv_search (struct target_ops *ops,
+ CORE_ADDR match, CORE_ADDR *valp);
+
+/* Print the contents of the target's AUXV on the specified file. */
+extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
+
+
+/* This function is called like a to_xfer_partial hook,
+ but must be called with TARGET_OBJECT_AUXV.
+ It handles access via /proc/PID/auxv, which is the common method.
+ This function is appropriate for doing:
+ #define NATIVE_XFER_AUXV procfs_xfer_auxv
+ for a native target that uses inftarg.c's child_xfer_partial hook. */
+
+extern LONGEST procfs_xfer_auxv (struct target_ops *ops,
+ int /* enum target_object */ object,
+ const char *annex,
+ void *readbuf,
+ const void *writebuf,
+ ULONGEST offset,
+ LONGEST len);
+
+
+#endif
--- /dev/null
+# Target: OpenBSD/sparc
+TDEPFILES= sparc-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o nbsd-tdep.o \
+ corelow.o solib.o solib-svr4.o
+TM_FILE= tm-nbsd.h
--- /dev/null
+# Target: OpenBSD/sparc64
+TDEPFILES= sparc64-tdep.o sparc64nbsd-tdep.o sparc64obsd-tdep.o \
+ sparc-tdep.o sparcnbsd-tdep.o nbsd-tdep.o \
+ corelow.o solib.o solib-svr4.o
+TM_FILE= tm-nbsd.h
--- /dev/null
+/* Target-dependent code for OpenBSD/sparc64.
+
+ Copyright 2004 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "osabi.h"
+#include "regset.h"
+#include "symtab.h"
+#include "solib-svr4.h"
+#include "trad-frame.h"
+
+#include "gdb_assert.h"
+
+#include "sparc64-tdep.h"
+#include "nbsd-tdep.h"
+
+/* OpenBSD uses the traditional NetBSD core file format, even for
+ ports that use ELF. The core files don't use multiple register
+ sets. Instead, the general-purpose and floating-point registers
+ are lumped together in a single section. Unlike on NetBSD, OpenBSD
+ uses a different layout for its general-purpose registers than the
+ layout used for ptrace(2). */
+
+/* From <machine/reg.h>. */
+const struct sparc_gregset sparc64obsd_core_gregset =
+{
+ 0 * 8, /* "tstate" */
+ 1 * 8, /* %pc */
+ 2 * 8, /* %npc */
+ 3 * 8, /* %y */
+ -1, /* %fprs */
+ -1,
+ 7 * 8, /* %g1 */
+ 22 * 8, /* %l0 */
+ 4 /* sizeof (%y) */
+};
+
+static void
+sparc64obsd_supply_gregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *gregs, size_t len)
+{
+ const char *regs = gregs;
+
+ sparc64_supply_gregset (regset->descr, regcache, regnum, regs);
+ sparc64_supply_fpregset (regcache, regnum, regs + 288);
+}
+\f
+
+/* Signal trampolines. */
+
+/* The OpenBSD kernel maps the signal trampoline at some random
+ location in user space, which means that the traditional BSD way of
+ detecting it won't work.
+
+ The signal trampoline will be mapped at an address that is page
+ aligned. We recognize the signal trampoline by the looking for the
+ sigreturn system call. */
+
+static const int sparc64obsd_page_size = 8192;
+
+static int
+sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+ CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
+ unsigned long insn;
+
+ if (name)
+ return 0;
+
+ /* Check for "restore %g0, SYS_sigreturn, %g1". */
+ insn = sparc_fetch_instruction (start_pc + 0xe8);
+ if (insn != 0x83e82067)
+ return 0;
+
+ /* Check for "t ST_SYSCALL". */
+ insn = sparc_fetch_instruction (start_pc + 0xf0);
+ if (insn != 0x91d02000)
+ return 0;
+
+ return 1;
+}
+
+static struct sparc_frame_cache *
+sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+ struct sparc_frame_cache *cache;
+ CORE_ADDR addr;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = sparc_frame_cache (next_frame, this_cache);
+ gdb_assert (cache == *this_cache);
+
+ /* If we couldn't find the frame's function, we're probably dealing
+ with an on-stack signal trampoline. */
+ if (cache->pc == 0)
+ {
+ cache->pc = frame_pc_unwind (next_frame);
+ cache->pc &= ~(sparc64obsd_page_size - 1);
+
+ /* Since we couldn't find the frame's function, the cache was
+ initialized under the assumption that we're frameless. */
+ cache->frameless_p = 0;
+ addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
+ cache->base = addr;
+ }
+
+ /* We find the appropriate instance of `struct sigcontext' at a
+ fixed offset in the signal frame. */
+ addr = cache->base + BIAS + 128 + 16;
+ cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame);
+
+ return cache;
+}
+
+static void
+sparc64obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct sparc_frame_cache *cache =
+ sparc64obsd_frame_cache (next_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc64obsd_frame_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct sparc_frame_cache *cache =
+ sparc64obsd_frame_cache (next_frame, this_cache);
+
+ trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc64obsd_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ sparc64obsd_frame_this_id,
+ sparc64obsd_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (sparc64obsd_pc_in_sigtramp (pc, name))
+ return &sparc64obsd_frame_unwind;
+
+ return NULL;
+}
+\f
+
+static void
+sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ tdep->gregset = XMALLOC (struct regset);
+ tdep->gregset->descr = &sparc64obsd_core_gregset;
+ tdep->gregset->supply_regset = sparc64obsd_supply_gregset;
+ tdep->sizeof_gregset = 832;
+
+ set_gdbarch_pc_in_sigtramp (gdbarch, sparc64obsd_pc_in_sigtramp);
+ frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
+
+ sparc64_init_abi (info, gdbarch);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, nbsd_lp64_solib_svr4_fetch_link_map_offsets);
+}
+
+\f
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64obsd_tdep (void);
+
+void
+_initialize_sparc64obsd_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+ GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi);
+}
--- /dev/null
+/* Target-dependent code for OpenBSD/sparc.
+
+ Copyright 2004 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "floatformat.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+#include "symtab.h"
+#include "trad-frame.h"
+
+#include "gdb_assert.h"
+
+#include "sparc-tdep.h"
+#include "nbsd-tdep.h"
+
+/* Signal trampolines. */
+
+/* The OpenBSD kernel maps the signal trampoline at some random
+ location in user space, which means that the traditional BSD way of
+ detecting it won't work.
+
+ The signal trampoline will be mapped at an address that is page
+ aligned. We recognize the signal trampoline by the looking for the
+ sigreturn system call. */
+
+static const int sparc32obsd_page_size = 4096;
+
+static int
+sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+ CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
+ unsigned long insn;
+
+ if (name)
+ return 0;
+
+ /* Check for "restore %g0, SYS_sigreturn, %g1". */
+ insn = sparc_fetch_instruction (start_pc + 0xec);
+ if (insn != 0x83e82067)
+ return 0;
+
+ /* Check for "t ST_SYSCALL". */
+ insn = sparc_fetch_instruction (start_pc + 0xf4);
+ if (insn != 0x91d02000)
+ return 0;
+
+ return 1;
+}
+
+static struct sparc_frame_cache *
+sparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+ struct sparc_frame_cache *cache;
+ CORE_ADDR addr;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = sparc_frame_cache (next_frame, this_cache);
+ gdb_assert (cache == *this_cache);
+
+ /* If we couldn't find the frame's function, we're probably dealing
+ with an on-stack signal trampoline. */
+ if (cache->pc == 0)
+ {
+ cache->pc = frame_pc_unwind (next_frame);
+ cache->pc &= ~(sparc32obsd_page_size - 1);
+
+ /* Since we couldn't find the frame's function, the cache was
+ initialized under the assumption that we're frameless. */
+ cache->frameless_p = 0;
+ addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
+ cache->base = addr;
+ }
+
+ cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
+
+ return cache;
+}
+
+static void
+sparc32obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct sparc_frame_cache *cache =
+ sparc32obsd_frame_cache (next_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc32obsd_frame_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct sparc_frame_cache *cache =
+ sparc32obsd_frame_cache (next_frame, this_cache);
+
+ trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc32obsd_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ sparc32obsd_frame_this_id,
+ sparc32obsd_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc32obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (sparc32obsd_pc_in_sigtramp (pc, name))
+ return &sparc32obsd_frame_unwind;
+
+ return NULL;
+}
+\f
+
+static void
+sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* OpenBSD doesn't support the 128-bit `long double' from the psABI. */
+ set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+
+ set_gdbarch_pc_in_sigtramp (gdbarch, sparc32obsd_pc_in_sigtramp);
+ frame_unwind_append_sniffer (gdbarch, sparc32obsd_sigtramp_frame_sniffer);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+}
+
+\f
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc32obsd_tdep (void);
+
+void
+_initialize_sparc32obsd_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
+ sparc32obsd_init_abi);
+}
--- /dev/null
+ comment "openbsd .note"
+
+.section ".note.openbsdbsd.ident", "a"
+ .p2align 2
+
+ .long 8
+ .long 4
+ .long 1
+ .ascii "OpenBSD\0\0"
+ .long 200311
+
+ .p2align 2
--- /dev/null
+/*
+ * Test that GDB cleans up properly after errors that result when a
+ * breakpoint is reset.
+ */
+
+/* VARIABLE is a macro defined on the compiler command line. */
+
+#include <stdlib.h>
+
+int VARIABLE = 42;
+
+void stop_here ()
+{
+ VARIABLE *= 2;
+}
+
+int main ()
+{
+ stop_here ();
+ exit (0);
+}
+
--- /dev/null
+# Copyright 2004 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Author: Paul N. Hilfinger (Hilfinger@gnat.com)
+
+# Test that GDB cleans up properly after errors that result when a
+# breakpoint is reset.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# IDT/SIM apparently doesn't have enough file descriptors to allow the
+# problem checked by this test to occur.
+if [istarget "mips-idt-*"] {
+ return 0;
+}
+
+set testfile "chng-syms"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DVARIABLE=var1}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+set oldtimeout $timeout
+set timeout 10
+verbose "Timeout is now 10 seconds" 2
+
+proc expect_to_stop_here { ident } {
+ global gdb_prompt
+ global decimal
+
+ # the "at foo.c:36" output we get with -g.
+ # the "in func" output we get without -g.
+ gdb_expect {
+ -re "Breakpoint \[0-9\]*, stop_here .*$gdb_prompt $" {
+ return 1
+ }
+ -re "$gdb_prompt $" {
+ fail "running to stop_here $ident"
+ return 0
+ }
+ timeout {
+ fail "running to stop_here $ident (timeout)"
+ return 0
+ }
+ }
+ return 1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break stop_here if (var1 == 42)" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "setting conditional breakpoint on function"
+gdb_run_cmd
+
+expect_to_stop_here "first time"
+
+gdb_continue_to_end "breakpoint first time through"
+
+# Now we recompile the executable, but without a variable named "var1", first
+# waiting to insure that even on fast machines, the file modification times
+# are distinct. This will force GDB to reload the file on the
+# next "run" command, causing an error when GDB tries to tries to reset
+# the breakpoint.
+
+sleep 2
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DVARIABLE=var2}] != "" } {
+
+# Complication: Since GDB generally holds an open file descriptor on the
+# executable at this point, there are some systems in which the
+# re-compilation will fail. In such cases, we'll consider the test
+# (vacuously) passed providing that re-running it succeeds as before.
+
+ gdb_run_cmd
+ expect_to_stop_here "after re-compile fails"
+ gdb_continue_to_end "after re-compile fails"
+
+} else {
+
+ gdb_run_cmd
+ gdb_expect {
+ -re "Error in re-setting .*No symbol .var1..*Program exited normally.*" {
+ pass "running with invalidated bpt condition after executable changes"
+ }
+ timeout {
+ fail "(timeout) running with invalidated bpt condition after executable changes"
+ }
+ }
+
+}
+
+set timeout $oldtimeout
+verbose "Timeout is now $timeout seconds" 2
+return 0
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2004 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Please email any bugs, comments, and/or additions to this file to:
+ bug-gdb@prep.ai.mit.edu */
+
+#include <stdio.h>
+
+int k = 0;
+
+extern void pendfunc (int x);
+
+int main()
+{
+ pendfunc (3); /* break main here */
+ pendfunc (4);
+ k = 1;
+ pendfunc (3);
+ return 0;
+}
--- /dev/null
+# Copyright 2003, 2004
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was created by Jeff Johnston. (jjohnstn@redhat.com)
+# The shared library compilation portion was copied from shlib-call.exp which was
+# written by Elena Zannoni (ezannoni@redhat.com).
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+# are we on a target board?
+if ![isnative] then {
+ return 0
+}
+
+set testfile "pending"
+set libfile "pendshr"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Build the shared libraries this test case needs.
+#
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=+z"
+ } elseif { [istarget "mips-sgi-irix*"] } {
+ # Disable SGI compiler's implicit -Dsgi
+ set additional_flags "additional_flags=-Usgi"
+ } else {
+ # don't know what the compiler is...
+ set additional_flags ""
+ }
+} else {
+ if { ([istarget "powerpc*-*-aix*"]
+ || [istarget "rs6000*-*-aix*"]) } {
+ set additional_flags ""
+ } else {
+ set additional_flags "additional_flags=-fpic"
+ }
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}.c" "${objdir}/${subdir}/${libfile}.o" object [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [istarget "hppa*-*-hpux*"] {
+ remote_exec build "ld -b ${objdir}/${subdir}/${libfile}.o -o ${objdir}/${subdir}/${libfile}.sl"
+} else {
+ set additional_flags "additional_flags=-shared"
+ if {[gdb_compile "${objdir}/${subdir}/${libfile}.o" "${objdir}/${subdir}/${libfile}.sl" executable [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+
+if { ($gcc_compiled
+ && ([istarget "powerpc*-*-aix*"]
+ || [istarget "rs6000*-*-aix*"] )) } {
+ set additional_flags "additional_flags=-L${objdir}/${subdir}"
+} elseif { [istarget "mips-sgi-irix*"] } {
+ set additional_flags "additional_flags=-rpath ${objdir}/${subdir}"
+} else {
+ set additional_flags ""
+}
+if {[gdb_compile "${objdir}/${subdir}/${testfile}.o ${objdir}/${subdir}/${libfile}.sl" "${binfile}" executable [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+#
+# Test setting, querying, and modifying pending breakpoints
+#
+
+gdb_test_multiple "break pendfunc1" "set pending breakpoint" {
+ -re ".*Make breakpoint pending.*y or n. $" {
+ gdb_test "y" "Breakpoint.*pendfunc1.*pending." "set pending breakpoint"
+ }
+}
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*" \
+"single pending breakpoint info"
+
+#
+# Test breaking at existing function
+#
+
+set mainline [gdb_get_line_number "break main here"]
+
+gdb_test "break main" \
+ "Breakpoint.*at.* file .*$srcfile, line $mainline.*" \
+ "breakpoint function"
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
+"pending plus real breakpoint info"
+
+
+#
+# Test not setting a pending breakpoint
+#
+gdb_test_multiple "break pendfunc2" "Don't set pending breakpoint" {
+ -re ".*Make breakpoint pending.*y or n. $" {
+ gdb_test "n" "" "Don't set pending breakpoint"
+ }
+}
+
+#
+# Add condition to pending breakpoint
+#
+
+gdb_test "condition 1 k == 1" ""
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
+"pending plus condition"
+
+#
+# Disable pending breakpoint
+#
+
+gdb_test "disable 1" ""
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
+"pending disabled"
+
+#
+# Add commands to pending breakpoint
+#
+gdb_test "commands 1\nprint k\nend" "" \
+ "Set commands for pending breakpoint"
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[\t \]+print k.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
+"pending disabled plus commands"
+
+#
+# Try a pending break for a line in a source file with a condition
+#
+
+gdb_test_multiple "break pendshr.c:26 if x > 3" "Set pending breakpoint 2" {
+ -re ".*Make breakpoint pending.*y or n. $" {
+ gdb_test "y" "Breakpoint.*pendshr.c:26.*pending." \
+ "Set pending breakpoint 2"
+ }
+}
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+\[\t \]+stop only if k == 1.*
+\[\t \]+print k.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:26 if x > 3.*" \
+"multiple pending breakpoints"
+
+#
+# Run to main which should resolve a pending breakpoint
+#
+
+gdb_test "run" \
+"Breakpoint.*at.*
+Pending breakpoint \"pendshr.c:26 if x > 3\" resolved.*
+Breakpoint.*, main.*$mainline.*" \
+"running to main"
+
+#
+# Re-enable the first pending breakpoint which should resolve
+#
+
+gdb_test "enable 1" \
+"Breakpoint.*at.*
+Pending breakpoint \"pendfunc1.* resolved.*" \
+"re-enabling pending breakpoint that can resolve instantly"
+
+#
+# Continue to verify conditionals and commands for breakpoints are honored
+#
+
+gdb_test "continue" \
+".*Breakpoint.*pendfunc1.*at.*pendshr.c:26.*4;" \
+"continue to resolved breakpoint 2"
+
+gdb_test "continue" \
+".*Breakpoint.*pendfunc1.*at.*pendshr.c:26.*
+\[$\]1 = 1." \
+"continue to resolved breakpoint 1"
+
+delete_breakpoints
+
+gdb_breakpoint "main"
+
+#
+# Set non-existent pending breakpoint
+#
+gdb_test_multiple "break imaginary" "set imaginary pending breakpoint" {
+ -re ".*Make breakpoint pending.*y or n. $" {
+ gdb_test "y" "Breakpoint.*imaginary.*pending." \
+ "set imaginary pending breakpoint"
+ }
+}
+
+#
+# rerun program and make sure that any pending breakpoint remains and no
+# error messages are issued for the missing function
+#
+
+rerun_to_main
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
+\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*imaginary.*" \
+"verify pending breakpoint after restart"
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2004 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Please email any bugs, comments, and/or additions to this file to:
+ bug-gdb@prep.ai.mit.edu */
+
+#include <stdio.h>
+
+void pendfunc1 (int x)
+{
+ int y = x + 4;
+ printf ("in pendfunc1, x is %d\n", x);
+}
+
+void pendfunc (int x)
+{
+ pendfunc1 (x);
+}
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2004 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+void *thread_function(void *arg);
+
+unsigned int args[1];
+
+int main() {
+ int res;
+ pthread_t threads[2];
+ void *thread_result;
+ long i = 1;
+
+ args[0] = 1;
+ res = pthread_create(&threads[0],
+ NULL,
+ thread_function,
+ (void *) 0);
+
+ /* thread-specific.exp: last thread start. */
+ args[1] = 1;
+
+ /* Don't run forever. Run just short of it :) */
+ while (i > 0)
+ {
+ /* thread-specific.exp: main loop. */
+ (i) ++;
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+void *thread_function(void *arg) {
+ int my_number = (long) arg;
+ int *myp = &args[my_number];
+
+ /* Don't run forever. Run just short of it :) */
+ while (*myp > 0)
+ {
+ /* thread-specific.exp: thread loop. */
+ (*myp) ++;
+ }
+
+ pthread_exit(NULL);
+}
--- /dev/null
+# Copyright 2004 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Daniel Jacobowitz <drow@mvista.com>.
+# It tests that the correct breakpoint is reported when we hit a
+# thread-specific breakpoint inserted for several threads.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "thread-specific"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
+ return -1
+}
+
+# Return a list of the valid thread IDs, with the initial thread first.
+proc get_thread_list { } {
+ global gdb_prompt
+ global expect_out
+
+ set thr_list ""
+
+ gdb_test_multiple "info threads" "get threads list" {
+ -re "info threads\r\n" {
+ exp_continue
+ }
+ -re "^\\* *(\[0-9\]*) Thread \[^\n\]*main\[^\n\]*\n" {
+ set thr_list "$expect_out(1,string) $thr_list"
+ exp_continue
+ }
+ -re "^ *(\[0-9\]*) Thread \[^\n\]*\n" {
+ lappend thr_list $expect_out(1,string)
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { [llength $thr_list] != 0 } {
+ pass "get threads list"
+ } else {
+ fail "get threads list (no threads)"
+ }
+ }
+ }
+
+ return $thr_list
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+gdb_test "set width 0" ""
+
+runto_main
+
+gdb_breakpoint [gdb_get_line_number "thread-specific.exp: last thread start"]
+gdb_continue_to_breakpoint "all threads started"
+
+set line [gdb_get_line_number "thread-specific.exp: thread loop"]
+set threads [get_thread_list]
+
+gdb_test_multiple "break $line thread [lindex $threads 0]" \
+ "breakpoint $line main thread" {
+ -re "Breakpoint (\[0-9\]*) at.* file .*$srcfile, line.*$gdb_prompt $" {
+ set main_breakpoint $expect_out(1,string)
+ pass "breakpoint $line main thread"
+ }
+}
+
+foreach thread [lrange $threads 1 end] {
+ gdb_breakpoint "$line thread $thread"
+}
+
+gdb_test_multiple "continue" "continue to thread-specific breakpoint" {
+ -re "Breakpoint $main_breakpoint, .* at .*\r\n$gdb_prompt $" {
+ fail "continue to thread-specific breakpoint (wrong breakpoint)"
+ }
+ -re "Breakpoint .* at .*\r\n$gdb_prompt $" {
+ pass "continue to thread-specific breakpoint"
+ }
+}
+
+return 0
--- /dev/null
+/* Specific command window processing.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-win.h"
+#include "tui/tui-io.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/* Dispatch the correct tui function based upon the control character. */
+unsigned int
+tui_dispatch_ctrl_char (unsigned int ch)
+{
+ struct tui_win_info *win_info = tui_win_with_focus ();
+ WINDOW *w = TUI_CMD_WIN->generic.handle;
+
+ /*
+ ** If the command window has the logical focus, or no-one does
+ ** assume it is the command window; in this case, pass the
+ ** character on through and do nothing here.
+ */
+ if (win_info == NULL || win_info == TUI_CMD_WIN)
+ return ch;
+ else
+ {
+ unsigned int c = 0, ch_copy = ch;
+ int i;
+ char *term;
+
+ /* If this is an xterm, page next/prev keys aren't returned
+ ** by keypad as a single char, so we must handle them here.
+ ** Seems like a bug in the curses library?
+ */
+ term = (char *) getenv ("TERM");
+ for (i = 0; (term && term[i]); i++)
+ term[i] = toupper (term[i]);
+ if ((strcmp (term, "XTERM") == 0) && key_is_start_sequence (ch))
+ {
+ unsigned int page_ch = 0;
+ unsigned int tmp_char;
+
+ tmp_char = 0;
+ while (!key_is_end_sequence (tmp_char))
+ {
+ tmp_char = (int) wgetch (w);
+ if (tmp_char == ERR)
+ {
+ return ch;
+ }
+ if (!tmp_char)
+ break;
+ if (tmp_char == 53)
+ page_ch = KEY_PPAGE;
+ else if (tmp_char == 54)
+ page_ch = KEY_NPAGE;
+ else
+ {
+ return 0;
+ }
+ }
+ ch_copy = page_ch;
+ }
+
+ switch (ch_copy)
+ {
+ case KEY_NPAGE:
+ tui_scroll_forward (win_info, 0);
+ break;
+ case KEY_PPAGE:
+ tui_scroll_backward (win_info, 0);
+ break;
+ case KEY_DOWN:
+ case KEY_SF:
+ tui_scroll_forward (win_info, 1);
+ break;
+ case KEY_UP:
+ case KEY_SR:
+ tui_scroll_backward (win_info, 1);
+ break;
+ case KEY_RIGHT:
+ tui_scroll_left (win_info, 1);
+ break;
+ case KEY_LEFT:
+ tui_scroll_right (win_info, 1);
+ break;
+ case '\f':
+ tui_refresh_all_win ();
+ break;
+ default:
+ c = ch_copy;
+ break;
+ }
+ return c;
+ }
+}
--- /dev/null
+/* Specific command window processing.
+
+ Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+ Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_COMMAND_H
+#define TUI_COMMAND_H
+
+extern unsigned int tui_dispatch_ctrl_char (unsigned int);
+
+#endif
--- /dev/null
+/* TUI data manipulation routines.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+
+#include "gdb_string.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/****************************
+** GLOBAL DECLARATIONS
+****************************/
+struct tui_win_info *(tui_win_list[MAX_MAJOR_WINDOWS]);
+
+/***************************
+** Private data
+****************************/
+static enum tui_layout_type current_layout = UNDEFINED_LAYOUT;
+static int term_height, term_width;
+static struct tui_gen_win_info _locator;
+static struct tui_gen_win_info exec_info[2];
+static struct tui_win_info * src_win_list[2];
+static struct tui_list source_windows = {(void **) src_win_list, 0};
+static int default_tab_len = DEFAULT_TAB_LEN;
+static struct tui_win_info * win_with_focus = (struct tui_win_info *) NULL;
+static struct tui_layout_def layout_def =
+{SRC_WIN, /* DISPLAY_MODE */
+ FALSE, /* SPLIT */
+ TUI_UNDEFINED_REGS, /* REGS_DISPLAY_TYPE */
+ TUI_SFLOAT_REGS}; /* FLOAT_REGS_DISPLAY_TYPE */
+static int win_resized = FALSE;
+
+
+/*********************************
+** Static function forward decls
+**********************************/
+static void free_content (tui_win_content, int, enum tui_win_type);
+static void free_content_elements (tui_win_content, int, enum tui_win_type);
+
+
+
+/*********************************
+** PUBLIC FUNCTIONS
+**********************************/
+
+int
+tui_win_is_source_type (enum tui_win_type win_type)
+{
+ return (win_type == SRC_WIN || win_type == DISASSEM_WIN);
+}
+
+int
+tui_win_is_auxillary (enum tui_win_type win_type)
+{
+ return (win_type > MAX_MAJOR_WINDOWS);
+}
+
+int
+tui_win_has_locator (struct tui_win_info *win_info)
+{
+ return (win_info != NULL \
+ && win_info->detail.source_info.has_locator);
+}
+
+void
+tui_set_win_highlight (struct tui_win_info *win_info, int highlight)
+{
+ if (win_info != NULL)
+ win_info->is_highlighted = highlight;
+}
+
+/******************************************
+** ACCESSORS & MUTATORS FOR PRIVATE DATA
+******************************************/
+
+/* Answer a whether the terminal window has been resized or not. */
+int
+tui_win_resized (void)
+{
+ return win_resized;
+}
+
+
+/* Set a whether the terminal window has been resized or not. */
+void
+tui_set_win_resized_to (int resized)
+{
+ win_resized = resized;
+}
+
+
+/* Answer a pointer to the current layout definition. */
+struct tui_layout_def *
+tui_layout_def (void)
+{
+ return &layout_def;
+}
+
+
+/* Answer the window with the logical focus. */
+struct tui_win_info *
+tui_win_with_focus (void)
+{
+ return win_with_focus;
+}
+
+
+/* Set the window that has the logical focus. */
+void
+tui_set_win_with_focus (struct tui_win_info * win_info)
+{
+ win_with_focus = win_info;
+}
+
+
+/* Answer the length in chars, of tabs. */
+int
+tui_default_tab_len (void)
+{
+ return default_tab_len;
+}
+
+
+/* Set the length in chars, of tabs. */
+void
+tui_set_default_tab_len (int len)
+{
+ default_tab_len = len;
+}
+
+
+/* Accessor for the current source window. Usually there is only one
+ source window (either source or disassembly), but both can be
+ displayed at the same time. */
+struct tui_list *
+tui_source_windows (void)
+{
+ return &source_windows;
+}
+
+
+/* Clear the list of source windows. Usually there is only one source
+ window (either source or disassembly), but both can be displayed at
+ the same time. */
+void
+tui_clear_source_windows (void)
+{
+ source_windows.list[0] = NULL;
+ source_windows.list[1] = NULL;
+ source_windows.count = 0;
+}
+
+
+/* Clear the pertinant detail in the source windows. */
+void
+tui_clear_source_windows_detail (void)
+{
+ int i;
+
+ for (i = 0; i < (tui_source_windows ())->count; i++)
+ tui_clear_win_detail ((struct tui_win_info *) (tui_source_windows ())->list[i]);
+}
+
+
+/* Add a window to the list of source windows. Usually there is only
+ one source window (either source or disassembly), but both can be
+ displayed at the same time. */
+void
+tui_add_to_source_windows (struct tui_win_info * win_info)
+{
+ if (source_windows.count < 2)
+ source_windows.list[source_windows.count++] = (void *) win_info;
+}
+
+
+/* Clear the pertinant detail in the windows. */
+void
+tui_clear_win_detail (struct tui_win_info * win_info)
+{
+ if (win_info != NULL)
+ {
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ win_info->detail.source_info.start_line_or_addr.addr = 0;
+ win_info->detail.source_info.horizontal_offset = 0;
+ break;
+ case CMD_WIN:
+ win_info->detail.command_info.cur_line =
+ win_info->detail.command_info.curch = 0;
+ break;
+ case DATA_WIN:
+ win_info->detail.data_display_info.data_content =
+ (tui_win_content) NULL;
+ win_info->detail.data_display_info.data_content_count = 0;
+ win_info->detail.data_display_info.regs_content =
+ (tui_win_content) NULL;
+ win_info->detail.data_display_info.regs_content_count = 0;
+ win_info->detail.data_display_info.regs_display_type =
+ TUI_UNDEFINED_REGS;
+ win_info->detail.data_display_info.regs_column_count = 1;
+ win_info->detail.data_display_info.display_regs = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+/* Accessor for the source execution info ptr. */
+struct tui_gen_win_info *
+tui_source_exec_info_win_ptr (void)
+{
+ return &exec_info[0];
+}
+
+
+/* Accessor for the disassem execution info ptr. */
+struct tui_gen_win_info *
+tui_disassem_exec_info_win_ptr (void)
+{
+ return &exec_info[1];
+}
+
+
+/* Accessor for the locator win info. Answers a pointer to the static
+ locator win info struct. */
+struct tui_gen_win_info *
+tui_locator_win_info_ptr (void)
+{
+ return &_locator;
+}
+
+
+/* Accessor for the term_height. */
+int
+tui_term_height (void)
+{
+ return term_height;
+}
+
+
+/* Mutator for the term height. */
+void
+tui_set_term_height_to (int h)
+{
+ term_height = h;
+}
+
+
+/* Accessor for the term_width. */
+int
+tui_term_width (void)
+{
+ return term_width;
+}
+
+
+/* Mutator for the term_width. */
+void
+tui_set_term_width_to (int w)
+{
+ term_width = w;
+}
+
+
+/* Accessor for the current layout. */
+enum tui_layout_type
+tui_current_layout (void)
+{
+ return current_layout;
+}
+
+
+/* Mutator for the current layout. */
+void
+tui_set_current_layout_to (enum tui_layout_type new_layout)
+{
+ current_layout = new_layout;
+}
+
+
+/* Set the origin of the window. */
+void
+set_gen_win_origin (struct tui_gen_win_info * win_info, int x, int y)
+{
+ win_info->origin.x = x;
+ win_info->origin.y = y;
+}
+
+
+/*****************************
+** OTHER PUBLIC FUNCTIONS
+*****************************/
+
+
+/* Answer the next window in the list, cycling back to the top if
+ necessary. */
+struct tui_win_info *
+tui_next_win (struct tui_win_info * cur_win)
+{
+ enum tui_win_type type = cur_win->generic.type;
+ struct tui_win_info * next_win = (struct tui_win_info *) NULL;
+
+ if (cur_win->generic.type == CMD_WIN)
+ type = SRC_WIN;
+ else
+ type = cur_win->generic.type + 1;
+ while (type != cur_win->generic.type && (next_win == NULL))
+ {
+ if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+ next_win = tui_win_list[type];
+ else
+ {
+ if (type == CMD_WIN)
+ type = SRC_WIN;
+ else
+ type++;
+ }
+ }
+
+ return next_win;
+}
+
+
+/* Answer the prev window in the list, cycling back to the bottom if
+ necessary. */
+struct tui_win_info *
+tui_prev_win (struct tui_win_info * cur_win)
+{
+ enum tui_win_type type = cur_win->generic.type;
+ struct tui_win_info * prev = (struct tui_win_info *) NULL;
+
+ if (cur_win->generic.type == SRC_WIN)
+ type = CMD_WIN;
+ else
+ type = cur_win->generic.type - 1;
+ while (type != cur_win->generic.type && (prev == NULL))
+ {
+ if (tui_win_list[type]->generic.is_visible)
+ prev = tui_win_list[type];
+ else
+ {
+ if (type == SRC_WIN)
+ type = CMD_WIN;
+ else
+ type--;
+ }
+ }
+
+ return prev;
+}
+
+
+/* Answer the window represented by name. */
+struct tui_win_info *
+tui_partial_win_by_name (char *name)
+{
+ struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+ if (name != (char *) NULL)
+ {
+ int i = 0;
+
+ while (i < MAX_MAJOR_WINDOWS && win_info == NULL)
+ {
+ if (tui_win_list[i] != 0)
+ {
+ char *cur_name = tui_win_name (&tui_win_list[i]->generic);
+ if (strlen (name) <= strlen (cur_name) &&
+ strncmp (name, cur_name, strlen (name)) == 0)
+ win_info = tui_win_list[i];
+ }
+ i++;
+ }
+ }
+
+ return win_info;
+}
+
+
+/* Answer the name of the window. */
+char *
+tui_win_name (struct tui_gen_win_info * win_info)
+{
+ char *name = (char *) NULL;
+
+ switch (win_info->type)
+ {
+ case SRC_WIN:
+ name = SRC_NAME;
+ break;
+ case CMD_WIN:
+ name = CMD_NAME;
+ break;
+ case DISASSEM_WIN:
+ name = DISASSEM_NAME;
+ break;
+ case DATA_WIN:
+ name = DATA_NAME;
+ break;
+ default:
+ name = "";
+ break;
+ }
+
+ return name;
+}
+
+
+void
+tui_initialize_static_data (void)
+{
+ tui_init_generic_part (tui_source_exec_info_win_ptr ());
+ tui_init_generic_part (tui_disassem_exec_info_win_ptr ());
+ tui_init_generic_part (tui_locator_win_info_ptr ());
+}
+
+
+struct tui_gen_win_info *
+tui_alloc_generic_win_info (void)
+{
+ struct tui_gen_win_info * win;
+
+ if ((win = (struct tui_gen_win_info *) xmalloc (
+ sizeof (struct tui_gen_win_info *))) != (struct tui_gen_win_info *) NULL)
+ tui_init_generic_part (win);
+
+ return win;
+}
+
+
+void
+tui_init_generic_part (struct tui_gen_win_info * win)
+{
+ win->width =
+ win->height =
+ win->origin.x =
+ win->origin.y =
+ win->viewport_height =
+ win->content_size =
+ win->last_visible_line = 0;
+ win->handle = (WINDOW *) NULL;
+ win->content = NULL;
+ win->content_in_use =
+ win->is_visible = FALSE;
+ win->title = 0;
+}
+
+
+/*
+ ** init_content_element().
+ */
+void
+init_content_element (struct tui_win_element * element, enum tui_win_type type)
+{
+ element->highlight = FALSE;
+ switch (type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ element->which_element.source.line = (char *) NULL;
+ element->which_element.source.line_or_addr.line_no = 0;
+ element->which_element.source.is_exec_point = FALSE;
+ element->which_element.source.has_break = FALSE;
+ break;
+ case DATA_WIN:
+ tui_init_generic_part (&element->which_element.data_window);
+ element->which_element.data_window.type = DATA_ITEM_WIN;
+ ((struct tui_gen_win_info *) & element->which_element.data_window)->content =
+ (void **) tui_alloc_content (1, DATA_ITEM_WIN);
+ ((struct tui_gen_win_info *)
+ & element->which_element.data_window)->content_size = 1;
+ break;
+ case CMD_WIN:
+ element->which_element.command.line = (char *) NULL;
+ break;
+ case DATA_ITEM_WIN:
+ element->which_element.data.name = (char *) NULL;
+ element->which_element.data.type = TUI_REGISTER;
+ element->which_element.data.item_no = UNDEFINED_ITEM;
+ element->which_element.data.value = NULL;
+ element->which_element.data.highlight = FALSE;
+ break;
+ case LOCATOR_WIN:
+ element->which_element.locator.file_name[0] =
+ element->which_element.locator.proc_name[0] = (char) 0;
+ element->which_element.locator.line_no = 0;
+ element->which_element.locator.addr = 0;
+ break;
+ case EXEC_INFO_WIN:
+ memset(element->which_element.simple_string, ' ',
+ sizeof(element->which_element.simple_string));
+ break;
+ default:
+ break;
+ }
+}
+
+void
+init_win_info (struct tui_win_info * win_info)
+{
+ tui_init_generic_part (&win_info->generic);
+ win_info->can_highlight =
+ win_info->is_highlighted = FALSE;
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ win_info->detail.source_info.execution_info = (struct tui_gen_win_info *) NULL;
+ win_info->detail.source_info.has_locator = FALSE;
+ win_info->detail.source_info.horizontal_offset = 0;
+ win_info->detail.source_info.start_line_or_addr.addr = 0;
+ win_info->detail.source_info.filename = 0;
+ break;
+ case DATA_WIN:
+ win_info->detail.data_display_info.data_content = (tui_win_content) NULL;
+ win_info->detail.data_display_info.data_content_count = 0;
+ win_info->detail.data_display_info.regs_content = (tui_win_content) NULL;
+ win_info->detail.data_display_info.regs_content_count = 0;
+ win_info->detail.data_display_info.regs_display_type =
+ TUI_UNDEFINED_REGS;
+ win_info->detail.data_display_info.regs_column_count = 1;
+ win_info->detail.data_display_info.display_regs = FALSE;
+ break;
+ case CMD_WIN:
+ win_info->detail.command_info.cur_line = 0;
+ win_info->detail.command_info.curch = 0;
+ break;
+ default:
+ win_info->detail.opaque = NULL;
+ break;
+ }
+}
+
+
+struct tui_win_info *
+tui_alloc_win_info (enum tui_win_type type)
+{
+ struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+ win_info = (struct tui_win_info *) xmalloc (sizeof (struct tui_win_info));
+ if ((win_info != NULL))
+ {
+ win_info->generic.type = type;
+ init_win_info (win_info);
+ }
+
+ return win_info;
+}
+
+
+/* Allocates the content and elements in a block. */
+tui_win_content
+tui_alloc_content (int num_elements, enum tui_win_type type)
+{
+ tui_win_content content = (tui_win_content) NULL;
+ char *element_block_ptr = (char *) NULL;
+ int i;
+
+ if ((content = (tui_win_content)
+ xmalloc (sizeof (struct tui_win_element *) * num_elements)) != (tui_win_content) NULL)
+ { /*
+ ** All windows, except the data window, can allocate the elements
+ ** in a chunk. The data window cannot because items can be
+ ** added/removed from the data display by the user at any time.
+ */
+ if (type != DATA_WIN)
+ {
+ if ((element_block_ptr = (char *)
+ xmalloc (sizeof (struct tui_win_element) * num_elements)) != (char *) NULL)
+ {
+ for (i = 0; i < num_elements; i++)
+ {
+ content[i] = (struct tui_win_element *) element_block_ptr;
+ init_content_element (content[i], type);
+ element_block_ptr += sizeof (struct tui_win_element);
+ }
+ }
+ else
+ {
+ xfree (content);
+ content = (tui_win_content) NULL;
+ }
+ }
+ }
+
+ return content;
+}
+
+
+/* Adds the input number of elements to the windows's content. If no
+ content has been allocated yet, alloc_content() is called to do
+ this. The index of the first element added is returned, unless
+ there is a memory allocation error, in which case, (-1) is
+ returned. */
+int
+tui_add_content_elements (struct tui_gen_win_info * win_info, int num_elements)
+{
+ struct tui_win_element * element_ptr;
+ int i, index_start;
+
+ if (win_info->content == NULL)
+ {
+ win_info->content = (void **) tui_alloc_content (num_elements, win_info->type);
+ index_start = 0;
+ }
+ else
+ index_start = win_info->content_size;
+ if (win_info->content != NULL)
+ {
+ for (i = index_start; (i < num_elements + index_start); i++)
+ {
+ if ((element_ptr = (struct tui_win_element *)
+ xmalloc (sizeof (struct tui_win_element))) != (struct tui_win_element *) NULL)
+ {
+ win_info->content[i] = (void *) element_ptr;
+ init_content_element (element_ptr, win_info->type);
+ win_info->content_size++;
+ }
+ else /* things must be really hosed now! We ran out of memory!? */
+ return (-1);
+ }
+ }
+
+ return index_start;
+}
+
+
+/* Delete all curses windows associated with win_info, leaving everything
+ else intact. */
+void
+tui_del_window (struct tui_win_info * win_info)
+{
+ struct tui_gen_win_info * generic_win;
+
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ generic_win = tui_locator_win_info_ptr ();
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ generic_win->is_visible = FALSE;
+ }
+ if (win_info->detail.source_info.filename)
+ {
+ xfree (win_info->detail.source_info.filename);
+ win_info->detail.source_info.filename = 0;
+ }
+ generic_win = win_info->detail.source_info.execution_info;
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ generic_win->is_visible = FALSE;
+ }
+ break;
+ case DATA_WIN:
+ if (win_info->generic.content != NULL)
+ {
+ tui_del_data_windows (win_info->detail.data_display_info.regs_content,
+ win_info->detail.data_display_info.regs_content_count);
+ tui_del_data_windows (win_info->detail.data_display_info.data_content,
+ win_info->detail.data_display_info.data_content_count);
+ }
+ break;
+ default:
+ break;
+ }
+ if (win_info->generic.handle != (WINDOW *) NULL)
+ {
+ tui_delete_win (win_info->generic.handle);
+ win_info->generic.handle = (WINDOW *) NULL;
+ win_info->generic.is_visible = FALSE;
+ }
+}
+
+
+void
+tui_free_window (struct tui_win_info * win_info)
+{
+ struct tui_gen_win_info * generic_win;
+
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ generic_win = tui_locator_win_info_ptr ();
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ }
+ tui_free_win_content (generic_win);
+ if (win_info->detail.source_info.filename)
+ {
+ xfree (win_info->detail.source_info.filename);
+ win_info->detail.source_info.filename = 0;
+ }
+ generic_win = win_info->detail.source_info.execution_info;
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ tui_free_win_content (generic_win);
+ }
+ break;
+ case DATA_WIN:
+ if (win_info->generic.content != NULL)
+ {
+ tui_free_data_content (win_info->detail.data_display_info.regs_content,
+ win_info->detail.data_display_info.regs_content_count);
+ win_info->detail.data_display_info.regs_content =
+ (tui_win_content) NULL;
+ win_info->detail.data_display_info.regs_content_count = 0;
+ tui_free_data_content (win_info->detail.data_display_info.data_content,
+ win_info->detail.data_display_info.data_content_count);
+ win_info->detail.data_display_info.data_content =
+ (tui_win_content) NULL;
+ win_info->detail.data_display_info.data_content_count = 0;
+ win_info->detail.data_display_info.regs_display_type =
+ TUI_UNDEFINED_REGS;
+ win_info->detail.data_display_info.regs_column_count = 1;
+ win_info->detail.data_display_info.display_regs = FALSE;
+ win_info->generic.content = NULL;
+ win_info->generic.content_size = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ if (win_info->generic.handle != (WINDOW *) NULL)
+ {
+ tui_delete_win (win_info->generic.handle);
+ win_info->generic.handle = (WINDOW *) NULL;
+ tui_free_win_content (&win_info->generic);
+ }
+ if (win_info->generic.title)
+ xfree (win_info->generic.title);
+ xfree (win_info);
+}
+
+
+void
+tui_free_all_source_wins_content (void)
+{
+ int i;
+
+ for (i = 0; i < (tui_source_windows ())->count; i++)
+ {
+ struct tui_win_info * win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+ if (win_info != NULL)
+ {
+ tui_free_win_content (&(win_info->generic));
+ tui_free_win_content (win_info->detail.source_info.execution_info);
+ }
+ }
+}
+
+
+void
+tui_free_win_content (struct tui_gen_win_info * win_info)
+{
+ if (win_info->content != NULL)
+ {
+ free_content ((tui_win_content) win_info->content,
+ win_info->content_size,
+ win_info->type);
+ win_info->content = NULL;
+ }
+ win_info->content_size = 0;
+}
+
+
+void
+tui_del_data_windows (tui_win_content content, int content_size)
+{
+ int i;
+
+ /*
+ ** Remember that data window content elements are of type struct tui_gen_win_info *,
+ ** each of which whose single element is a data element.
+ */
+ for (i = 0; i < content_size; i++)
+ {
+ struct tui_gen_win_info * generic_win = &content[i]->which_element.data_window;
+
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ generic_win->is_visible = FALSE;
+ }
+ }
+}
+
+
+void
+tui_free_data_content (tui_win_content content, int content_size)
+{
+ int i;
+
+ /*
+ ** Remember that data window content elements are of type struct tui_gen_win_info *,
+ ** each of which whose single element is a data element.
+ */
+ for (i = 0; i < content_size; i++)
+ {
+ struct tui_gen_win_info * generic_win = &content[i]->which_element.data_window;
+
+ if (generic_win != (struct tui_gen_win_info *) NULL)
+ {
+ tui_delete_win (generic_win->handle);
+ generic_win->handle = (WINDOW *) NULL;
+ tui_free_win_content (generic_win);
+ }
+ }
+ free_content (content,
+ content_size,
+ DATA_WIN);
+}
+
+
+/**********************************
+** LOCAL STATIC FUNCTIONS **
+**********************************/
+
+
+static void
+free_content (tui_win_content content, int content_size, enum tui_win_type win_type)
+{
+ if (content != (tui_win_content) NULL)
+ {
+ free_content_elements (content, content_size, win_type);
+ xfree (content);
+ }
+}
+
+
+/*
+ ** free_content_elements().
+ */
+static void
+free_content_elements (tui_win_content content, int content_size, enum tui_win_type type)
+{
+ if (content != (tui_win_content) NULL)
+ {
+ int i;
+
+ if (type == SRC_WIN || type == DISASSEM_WIN)
+ {
+ /* free whole source block */
+ xfree (content[0]->which_element.source.line);
+ }
+ else
+ {
+ for (i = 0; i < content_size; i++)
+ {
+ struct tui_win_element * element;
+
+ element = content[i];
+ if (element != (struct tui_win_element *) NULL)
+ {
+ switch (type)
+ {
+ case DATA_WIN:
+ xfree (element);
+ break;
+ case DATA_ITEM_WIN:
+ /*
+ ** Note that data elements are not allocated
+ ** in a single block, but individually, as needed.
+ */
+ if (element->which_element.data.type != TUI_REGISTER)
+ xfree ((void *)element->which_element.data.name);
+ xfree (element->which_element.data.value);
+ xfree (element);
+ break;
+ case CMD_WIN:
+ xfree (element->which_element.command.line);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ if (type != DATA_WIN && type != DATA_ITEM_WIN)
+ xfree (content[0]); /* free the element block */
+ }
+}
--- /dev/null
+/* TUI data manipulation routines.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_DATA_H
+#define TUI_DATA_H
+
+#if defined (HAVE_NCURSES_H)
+#include <ncurses.h>
+#elif defined (HAVE_CURSES_H)
+#include <curses.h>
+#endif
+
+/* Generic window information */
+struct tui_gen_win_info
+{
+ WINDOW *handle; /* window handle */
+ enum tui_win_type type; /* type of window */
+ int width; /* window width */
+ int height; /* window height */
+ struct tui_point origin; /* origin of window */
+ void **content; /* content of window */
+ int content_size; /* Size of content (# of elements) */
+ int content_in_use; /* Can it be used, or is it already used? */
+ int viewport_height; /* viewport height */
+ int last_visible_line; /* index of last visible line */
+ int is_visible; /* whether the window is visible or not */
+ char *title; /* Window title to display. */
+};
+
+/* Constant definitions */
+#define DEFAULT_TAB_LEN 8
+#define NO_SRC_STRING "[ No Source Available ]"
+#define NO_DISASSEM_STRING "[ No Assembly Available ]"
+#define NO_REGS_STRING "[ Register Values Unavailable ]"
+#define NO_DATA_STRING "[ No Data Values Displayed ]"
+#define MAX_CONTENT_COUNT 100
+#define SRC_NAME "SRC"
+#define CMD_NAME "CMD"
+#define DATA_NAME "REGS"
+#define DISASSEM_NAME "ASM"
+#define TUI_NULL_STR ""
+#define DEFAULT_HISTORY_COUNT 25
+#define BOX_WINDOW TRUE
+#define DONT_BOX_WINDOW FALSE
+#define HILITE TRUE
+#define NO_HILITE FALSE
+#define WITH_LOCATOR TRUE
+#define NO_LOCATOR FALSE
+#define EMPTY_SOURCE_PROMPT TRUE
+#define NO_EMPTY_SOURCE_PROMPT FALSE
+#define UNDEFINED_ITEM -1
+#define MIN_WIN_HEIGHT 3
+#define MIN_CMD_WIN_HEIGHT 3
+
+/* Strings to display in the TUI status line. */
+#define PROC_PREFIX "In: "
+#define LINE_PREFIX "Line: "
+#define PC_PREFIX "PC: "
+#define SINGLE_KEY "(SingleKey)"
+
+/* Minimum/Maximum length of some fields displayed in the TUI status line. */
+#define MIN_LINE_WIDTH 4 /* Use at least 4 digits for line numbers. */
+#define MIN_PROC_WIDTH 12
+#define MAX_TARGET_WIDTH 10
+#define MAX_PID_WIDTH 14
+
+#define TUI_FLOAT_REGS_NAME "$FREGS"
+#define TUI_FLOAT_REGS_NAME_LOWER "$fregs"
+#define TUI_GENERAL_REGS_NAME "$GREGS"
+#define TUI_GENERAL_REGS_NAME_LOWER "$gregs"
+#define TUI_SPECIAL_REGS_NAME "$SREGS"
+#define TUI_SPECIAL_REGS_NAME_LOWER "$sregs"
+#define TUI_GENERAL_SPECIAL_REGS_NAME "$REGS"
+#define TUI_GENERAL_SPECIAL_REGS_NAME_LOWER "$regs"
+
+/* Scroll direction enum. */
+enum tui_scroll_direction
+{
+ FORWARD_SCROLL,
+ BACKWARD_SCROLL,
+ LEFT_SCROLL,
+ RIGHT_SCROLL
+};
+
+
+/* General list struct. */
+struct tui_list
+{
+ void **list;
+ int count;
+};
+
+
+/* The kinds of layouts available */
+enum tui_layout_type
+{
+ SRC_COMMAND,
+ DISASSEM_COMMAND,
+ SRC_DISASSEM_COMMAND,
+ SRC_DATA_COMMAND,
+ DISASSEM_DATA_COMMAND,
+ UNDEFINED_LAYOUT
+};
+
+/* Basic data types that can be displayed in the data window. */
+enum tui_data_type
+{
+ TUI_REGISTER,
+ TUI_SCALAR,
+ TUI_COMPLEX,
+ TUI_STRUCT
+};
+
+/* Types of register displays */
+enum tui_register_display_type
+{
+ TUI_UNDEFINED_REGS,
+ TUI_GENERAL_REGS,
+ TUI_SFLOAT_REGS,
+ TUI_DFLOAT_REGS,
+ TUI_SPECIAL_REGS,
+ TUI_GENERAL_AND_SPECIAL_REGS
+};
+
+/* Structure describing source line or line address */
+union tui_line_or_address
+{
+ int line_no;
+ CORE_ADDR addr;
+};
+
+/* Current Layout definition */
+struct tui_layout_def
+{
+ enum tui_win_type display_mode;
+ int split;
+ enum tui_register_display_type regs_display_type;
+ enum tui_register_display_type float_regs_display_type;
+};
+
+/* Elements in the Source/Disassembly Window */
+struct tui_source_element
+{
+ char *line;
+ union tui_line_or_address line_or_addr;
+ int is_exec_point;
+ int has_break;
+};
+
+
+/* Elements in the data display window content */
+struct tui_data_element
+{
+ const char *name;
+ int item_no; /* the register number, or data display number */
+ enum tui_data_type type;
+ void *value;
+ int highlight;
+};
+
+
+/* Elements in the command window content */
+struct tui_command_element
+{
+ char *line;
+};
+
+
+#define MAX_LOCATOR_ELEMENT_LEN 100
+
+/* Elements in the locator window content */
+struct tui_locator_element
+{
+ char file_name[MAX_LOCATOR_ELEMENT_LEN];
+ char proc_name[MAX_LOCATOR_ELEMENT_LEN];
+ int line_no;
+ CORE_ADDR addr;
+};
+
+/* Flags to tell what kind of breakpoint is at current line. */
+#define TUI_BP_ENABLED 0x01
+#define TUI_BP_DISABLED 0x02
+#define TUI_BP_HIT 0x04
+#define TUI_BP_CONDITIONAL 0x08
+#define TUI_BP_HARDWARE 0x10
+
+/* Position of breakpoint markers in the exec info string. */
+#define TUI_BP_HIT_POS 0
+#define TUI_BP_BREAK_POS 1
+#define TUI_EXEC_POS 2
+#define TUI_EXECINFO_SIZE 4
+
+typedef char tui_exec_info_content[TUI_EXECINFO_SIZE];
+
+/* An content element in a window */
+union tui_which_element
+{
+ struct tui_source_element source; /* the source elements */
+ struct tui_gen_win_info data_window; /* data display elements */
+ struct tui_data_element data; /* elements of data_window */
+ struct tui_command_element command; /* command elements */
+ struct tui_locator_element locator; /* locator elements */
+ tui_exec_info_content simple_string; /* simple char based elements */
+};
+
+struct tui_win_element
+{
+ int highlight;
+ union tui_which_element which_element;
+};
+
+
+/* This describes the content of the window. */
+typedef struct tui_win_element **tui_win_content;
+
+
+/* This struct defines the specific information about a data display window */
+struct tui_data_info
+{
+ tui_win_content data_content; /* start of data display content */
+ int data_content_count;
+ tui_win_content regs_content; /* start of regs display content */
+ int regs_content_count;
+ enum tui_register_display_type regs_display_type;
+ int regs_column_count;
+ int display_regs; /* Should regs be displayed at all? */
+};
+
+
+struct tui_source_info
+{
+ int has_locator; /* Does locator belongs to this window? */
+ /* Execution information window. */
+ struct tui_gen_win_info *execution_info;
+ int horizontal_offset; /* used for horizontal scroll */
+ union tui_line_or_address start_line_or_addr;
+ char* filename;
+};
+
+
+struct tui_command_info
+{
+ int cur_line; /* The current line position */
+ int curch; /* The current cursor position */
+ int start_line;
+};
+
+
+/* This defines information about each logical window */
+struct tui_win_info
+{
+ struct tui_gen_win_info generic; /* general window information */
+ union
+ {
+ struct tui_source_info source_info;
+ struct tui_data_info data_display_info;
+ struct tui_command_info command_info;
+ void *opaque;
+ }
+ detail;
+ int can_highlight; /* Can this window ever be highlighted? */
+ int is_highlighted; /* Is this window highlighted? */
+};
+
+extern int tui_win_is_source_type (enum tui_win_type win_type);
+extern int tui_win_is_auxillary (enum tui_win_type win_type);
+extern int tui_win_has_locator (struct tui_win_info *win_info);
+extern void tui_set_win_highlight (struct tui_win_info *win_info,
+ int highlight);
+
+
+/* Global Data */
+extern struct tui_win_info *(tui_win_list[MAX_MAJOR_WINDOWS]);
+
+#define TUI_SRC_WIN tui_win_list[SRC_WIN]
+#define TUI_DISASM_WIN tui_win_list[DISASSEM_WIN]
+#define TUI_DATA_WIN tui_win_list[DATA_WIN]
+#define TUI_CMD_WIN tui_win_list[CMD_WIN]
+
+/* Data Manipulation Functions */
+extern void tui_initialize_static_data (void);
+extern struct tui_gen_win_info *tui_alloc_generic_win_info (void);
+extern struct tui_win_info *tui_alloc_win_info (enum tui_win_type);
+extern void tui_init_generic_part (struct tui_gen_win_info *);
+extern void tui_init_win_info (struct tui_win_info *);
+extern tui_win_content tui_alloc_content (int, enum tui_win_type);
+extern int tui_add_content_elements (struct tui_gen_win_info *, int);
+extern void tui_init_content_element (struct tui_win_element *, enum tui_win_type);
+extern void tui_free_window (struct tui_win_info *);
+extern void tui_free_win_content (struct tui_gen_win_info *);
+extern void tui_free_data_content (tui_win_content, int);
+extern void tui_free_all_source_wins_content (void);
+extern void tui_del_window (struct tui_win_info *);
+extern void tui_del_data_windows (tui_win_content, int);
+extern struct tui_win_info *tui_partial_win_by_name (char *);
+extern char *tui_win_name (struct tui_gen_win_info *);
+extern enum tui_layout_type tui_current_layout (void);
+extern void tui_set_current_layout_to (enum tui_layout_type);
+extern int tui_term_height (void);
+extern void tui_set_term_height_to (int);
+extern int tui_term_width (void);
+extern void tui_set_term_width_to (int);
+extern void tui_set_gen_win_origin (struct tui_gen_win_info *, int, int);
+extern struct tui_gen_win_info *tui_locator_win_info_ptr (void);
+extern struct tui_gen_win_info *tui_source_exec_info_win_ptr (void);
+extern struct tui_gen_win_info *tui_disassem_exec_info_win_ptr (void);
+extern struct tui_list * tui_source_windows (void);
+extern void tui_clear_source_windows (void);
+extern void tui_clear_source_windows_detail (void);
+extern void tui_clear_win_detail (struct tui_win_info * win_info);
+extern void tui_add_to_source_windows (struct tui_win_info *);
+extern int tui_default_tab_len (void);
+extern void tui_set_default_tab_len (int);
+extern struct tui_win_info *tui_win_with_focus (void);
+extern void tui_set_win_with_focus (struct tui_win_info *);
+extern struct tui_layout_def * tui_layout_def (void);
+extern int tui_win_resized (void);
+extern void tui_set_win_resized_to (int);
+
+extern struct tui_win_info *tui_next_win (struct tui_win_info *);
+extern struct tui_win_info *tui_prev_win (struct tui_win_info *);
+
+extern void tui_add_to_source_windows (struct tui_win_info * win_info);
+
+#endif /* TUI_DATA_H */
--- /dev/null
+/* Disassembly display.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "value.h"
+#include "source.h"
+#include "disasm.h"
+#include "gdb_string.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-win.h"
+#include "tui/tui-layout.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+struct tui_asm_line
+{
+ CORE_ADDR addr;
+ char* addr_string;
+ char* insn;
+};
+
+/* Function to set the disassembly window's content.
+ Disassemble count lines starting at pc.
+ Return address of the count'th instruction after pc. */
+static CORE_ADDR
+tui_disassemble (struct tui_asm_line* lines, CORE_ADDR pc, int count)
+{
+ struct ui_file *gdb_dis_out;
+
+ /* now init the ui_file structure */
+ gdb_dis_out = tui_sfileopen (256);
+
+ /* Now construct each line */
+ for (; count > 0; count--, lines++)
+ {
+ if (lines->addr_string)
+ xfree (lines->addr_string);
+ if (lines->insn)
+ xfree (lines->insn);
+
+ print_address (pc, gdb_dis_out);
+ lines->addr = pc;
+ lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
+
+ ui_file_rewind (gdb_dis_out);
+
+ pc = pc + gdb_print_insn (pc, gdb_dis_out);
+
+ lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
+
+ /* reset the buffer to empty */
+ ui_file_rewind (gdb_dis_out);
+ }
+ ui_file_delete (gdb_dis_out);
+ return pc;
+}
+
+/* Find the disassembly address that corresponds to FROM lines
+ above or below the PC. Variable sized instructions are taken
+ into account by the algorithm. */
+static CORE_ADDR
+tui_find_disassembly_address (CORE_ADDR pc, int from)
+{
+ CORE_ADDR new_low;
+ int max_lines;
+ int i;
+ struct tui_asm_line* lines;
+
+ max_lines = (from > 0) ? from : - from;
+ if (max_lines <= 1)
+ return pc;
+
+ lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
+ * max_lines);
+ memset (lines, 0, sizeof (struct tui_asm_line) * max_lines);
+
+ new_low = pc;
+ if (from > 0)
+ {
+ tui_disassemble (lines, pc, max_lines);
+ new_low = lines[max_lines - 1].addr;
+ }
+ else
+ {
+ CORE_ADDR last_addr;
+ int pos;
+ struct minimal_symbol* msymbol;
+
+ /* Find backward an address which is a symbol
+ and for which disassembling from that address will fill
+ completely the window. */
+ pos = max_lines - 1;
+ do {
+ new_low -= 1 * max_lines;
+ msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
+
+ if (msymbol)
+ new_low = SYMBOL_VALUE_ADDRESS (msymbol);
+ else
+ new_low += 1 * max_lines;
+
+ tui_disassemble (lines, new_low, max_lines);
+ last_addr = lines[pos].addr;
+ } while (last_addr > pc && msymbol);
+
+ /* Scan forward disassembling one instruction at a time
+ until the last visible instruction of the window
+ matches the pc. We keep the disassembled instructions
+ in the 'lines' window and shift it downward (increasing
+ its addresses). */
+ if (last_addr < pc)
+ do
+ {
+ CORE_ADDR next_addr;
+
+ pos++;
+ if (pos >= max_lines)
+ pos = 0;
+
+ next_addr = tui_disassemble (&lines[pos], last_addr, 1);
+
+ /* If there are some problems while disassembling exit. */
+ if (next_addr <= last_addr)
+ break;
+ last_addr = next_addr;
+ } while (last_addr <= pc);
+ pos++;
+ if (pos >= max_lines)
+ pos = 0;
+ new_low = lines[pos].addr;
+ }
+ for (i = 0; i < max_lines; i++)
+ {
+ xfree (lines[i].addr_string);
+ xfree (lines[i].insn);
+ }
+ return new_low;
+}
+
+/* Function to set the disassembly window's content. */
+enum tui_status
+tui_set_disassem_content (CORE_ADDR pc)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int i;
+ int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
+ int line_width, max_lines;
+ CORE_ADDR cur_pc;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ int tab_len = tui_default_tab_len ();
+ struct tui_asm_line* lines;
+ int insn_pos;
+ int addr_size, max_size;
+ char* line;
+
+ if (pc == 0)
+ return TUI_FAILURE;
+
+ ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
+ if (ret != TUI_SUCCESS)
+ return ret;
+
+ TUI_DISASM_WIN->detail.source_info.start_line_or_addr.addr = pc;
+ cur_pc = (CORE_ADDR)
+ (((struct tui_win_element *) locator->content[0])->which_element.locator.addr);
+
+ max_lines = TUI_DISASM_WIN->generic.height - 2; /* account for hilite */
+
+ /* Get temporary table that will hold all strings (addr & insn). */
+ lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
+ * max_lines);
+ memset (lines, 0, sizeof (struct tui_asm_line) * max_lines);
+
+ line_width = TUI_DISASM_WIN->generic.width - 1;
+
+ tui_disassemble (lines, pc, max_lines);
+
+ /* See what is the maximum length of an address and of a line. */
+ addr_size = 0;
+ max_size = 0;
+ for (i = 0; i < max_lines; i++)
+ {
+ size_t len = strlen (lines[i].addr_string);
+ if (len > addr_size)
+ addr_size = len;
+
+ len = strlen (lines[i].insn) + tab_len;
+ if (len > max_size)
+ max_size = len;
+ }
+ max_size += addr_size + tab_len;
+
+ /* Allocate memory to create each line. */
+ line = (char*) alloca (max_size);
+ insn_pos = (1 + (addr_size / tab_len)) * tab_len;
+
+ /* Now construct each line */
+ for (i = 0; i < max_lines; i++)
+ {
+ struct tui_win_element * element;
+ struct tui_source_element* src;
+ int cur_len;
+
+ element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
+ src = &element->which_element.source;
+ strcpy (line, lines[i].addr_string);
+ cur_len = strlen (line);
+
+ /* Add spaces to make the instructions start on the same column */
+ while (cur_len < insn_pos)
+ {
+ strcat (line, " ");
+ cur_len++;
+ }
+
+ strcat (line, lines[i].insn);
+
+ /* Now copy the line taking the offset into account */
+ if (strlen (line) > offset)
+ strcpy (src->line, &line[offset]);
+ else
+ src->line[0] = '\0';
+
+ src->line_or_addr.addr = lines[i].addr;
+ src->is_exec_point = lines[i].addr == cur_pc;
+
+ /* See whether there is a breakpoint installed. */
+ src->has_break = (!src->is_exec_point
+ && breakpoint_here_p (pc) != no_breakpoint_here);
+
+ xfree (lines[i].addr_string);
+ xfree (lines[i].insn);
+ }
+ TUI_DISASM_WIN->generic.content_size = i;
+ return TUI_SUCCESS;
+}
+
+
+/* Function to display the disassembly window with disassembled code. */
+void
+tui_show_disassem (CORE_ADDR start_addr)
+{
+ struct symtab *s = find_pc_symtab (start_addr);
+ struct tui_win_info * win_with_focus = tui_win_with_focus ();
+ union tui_line_or_address val;
+
+ val.addr = start_addr;
+ tui_add_win_to_layout (DISASSEM_WIN);
+ tui_update_source_window (TUI_DISASM_WIN, s, val, FALSE);
+ /*
+ ** if the focus was in the src win, put it in the asm win, if the
+ ** source view isn't split
+ */
+ if (tui_current_layout () != SRC_DISASSEM_COMMAND && win_with_focus == TUI_SRC_WIN)
+ tui_set_win_focus_to (TUI_DISASM_WIN);
+
+ return;
+}
+
+
+/* Function to display the disassembly window. */
+void
+tui_show_disassem_and_update_source (CORE_ADDR start_addr)
+{
+ struct symtab_and_line sal;
+
+ tui_show_disassem (start_addr);
+ if (tui_current_layout () == SRC_DISASSEM_COMMAND)
+ {
+ union tui_line_or_address val;
+
+ /*
+ ** Update what is in the source window if it is displayed too,
+ ** note that it follows what is in the disassembly window and visa-versa
+ */
+ sal = find_pc_line (start_addr, 0);
+ val.line_no = sal.line;
+ tui_update_source_window (TUI_SRC_WIN, sal.symtab, val, TRUE);
+ if (sal.symtab)
+ {
+ set_current_source_symtab_and_line (&sal);
+ tui_update_locator_filename (sal.symtab->filename);
+ }
+ else
+ tui_update_locator_filename ("?");
+ }
+
+ return;
+}
+
+CORE_ADDR
+tui_get_begin_asm_address (void)
+{
+ struct tui_gen_win_info * locator;
+ struct tui_locator_element * element;
+ CORE_ADDR addr;
+
+ locator = tui_locator_win_info_ptr ();
+ element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+
+ if (element->addr == 0)
+ {
+ struct minimal_symbol *main_symbol;
+
+ /* Find address of the start of program.
+ Note: this should be language specific. */
+ main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
+ if (main_symbol == 0)
+ main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
+ if (main_symbol == 0)
+ main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
+ if (main_symbol)
+ addr = SYMBOL_VALUE_ADDRESS (main_symbol);
+ else
+ addr = 0;
+ }
+ else /* the target is executing */
+ addr = element->addr;
+
+ return addr;
+}
+
+/* Determine what the low address will be to display in the TUI's
+ disassembly window. This may or may not be the same as the
+ low address input. */
+CORE_ADDR
+tui_get_low_disassembly_address (CORE_ADDR low, CORE_ADDR pc)
+{
+ int pos;
+
+ /* Determine where to start the disassembly so that the pc is about in the
+ middle of the viewport. */
+ pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
+ pc = tui_find_disassembly_address (pc, -pos);
+
+ if (pc < low)
+ pc = low;
+ return pc;
+}
+
+/* Scroll the disassembly forward or backward vertically. */
+void
+tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
+ int num_to_scroll)
+{
+ if (TUI_DISASM_WIN->generic.content != NULL)
+ {
+ CORE_ADDR pc;
+ tui_win_content content;
+ struct symtab *s;
+ union tui_line_or_address val;
+ int max_lines, dir;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+ content = (tui_win_content) TUI_DISASM_WIN->generic.content;
+ if (cursal.symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+ else
+ s = cursal.symtab;
+
+ /* account for hilite */
+ max_lines = TUI_DISASM_WIN->generic.height - 2;
+ pc = content[0]->which_element.source.line_or_addr.addr;
+ dir = (scroll_direction == FORWARD_SCROLL) ? max_lines : - max_lines;
+
+ val.addr = tui_find_disassembly_address (pc, dir);
+ tui_update_source_window_as_is (TUI_DISASM_WIN, s, val, FALSE);
+ }
+}
--- /dev/null
+/* Disassembly display.
+
+ Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+ Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_DISASM_H
+#define TUI_DISASM_H
+
+#include "tui/tui.h" /* For enum tui_status. */
+#include "tui/tui-data.h" /* For enum tui_scroll_direction. */
+
+extern enum tui_status tui_set_disassem_content (CORE_ADDR);
+extern void tui_show_disassem (CORE_ADDR);
+extern void tui_show_disassem_and_update_source (CORE_ADDR);
+extern void tui_vertical_disassem_scroll (enum tui_scroll_direction, int);
+extern CORE_ADDR tui_get_begin_asm_address (void);
+
+#endif
--- /dev/null
+/* TUI support I/O functions.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "terminal.h"
+#include "target.h"
+#include "event-loop.h"
+#include "event-top.h"
+#include "command.h"
+#include "top.h"
+#include "readline/readline.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-io.h"
+#include "tui/tui-command.h"
+#include "tui/tui-win.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-file.h"
+#include "ui-out.h"
+#include "cli-out.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+int
+key_is_start_sequence (int ch)
+{
+ return (ch == 27);
+}
+
+int
+key_is_end_sequence (int ch)
+{
+ return (ch == 126);
+}
+
+int
+key_is_backspace (int ch)
+{
+ return (ch == 8);
+}
+
+int
+key_is_command_char (int ch)
+{
+ return ((ch == KEY_NPAGE) || (ch == KEY_PPAGE)
+ || (ch == KEY_LEFT) || (ch == KEY_RIGHT)
+ || (ch == KEY_UP) || (ch == KEY_DOWN)
+ || (ch == KEY_SF) || (ch == KEY_SR)
+ || (ch == (int)'\f') || key_is_start_sequence (ch));
+}
+
+/* Use definition from readline 4.3. */
+#undef CTRL_CHAR
+#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
+
+/* This file controls the IO interactions between gdb and curses.
+ When the TUI is enabled, gdb has two modes a curses and a standard
+ mode.
+
+ In curses mode, the gdb outputs are made in a curses command window.
+ For this, the gdb_stdout and gdb_stderr are redirected to the specific
+ ui_file implemented by TUI. The output is handled by tui_puts().
+ The input is also controlled by curses with tui_getc(). The readline
+ library uses this function to get its input. Several readline hooks
+ are installed to redirect readline output to the TUI (see also the
+ note below).
+
+ In normal mode, the gdb outputs are restored to their origin, that
+ is as if TUI is not used. Readline also uses its original getc()
+ function with stdin.
+
+ Note SCz/2001-07-21: the current readline is not clean in its management of
+ the output. Even if we install a redisplay handler, it sometimes writes on
+ a stdout file. It is important to redirect every output produced by
+ readline, otherwise the curses window will be garbled. This is implemented
+ with a pipe that TUI reads and readline writes to. A gdb input handler
+ is created so that reading the pipe is handled automatically.
+ This will probably not work on non-Unix platforms. The best fix is
+ to make readline clean enougth so that is never write on stdout.
+
+ Note SCz/2002-09-01: we now use more readline hooks and it seems that
+ with them we don't need the pipe anymore (verified by creating the pipe
+ and closing its end so that write causes a SIGPIPE). The old pipe code
+ is still there and can be conditionally removed by
+ #undef TUI_USE_PIPE_FOR_READLINE. */
+
+/* For gdb 5.3, prefer to continue the pipe hack as a backup wheel. */
+#define TUI_USE_PIPE_FOR_READLINE
+/*#undef TUI_USE_PIPE_FOR_READLINE*/
+
+/* TUI output files. */
+static struct ui_file *tui_stdout;
+static struct ui_file *tui_stderr;
+struct ui_out *tui_out;
+
+/* GDB output files in non-curses mode. */
+static struct ui_file *tui_old_stdout;
+static struct ui_file *tui_old_stderr;
+struct ui_out *tui_old_uiout;
+
+/* Readline previous hooks. */
+static Function *tui_old_rl_getc_function;
+static VFunction *tui_old_rl_redisplay_function;
+static VFunction *tui_old_rl_prep_terminal;
+static VFunction *tui_old_rl_deprep_terminal;
+static int tui_old_readline_echoing_p;
+
+/* Readline output stream.
+ Should be removed when readline is clean. */
+static FILE *tui_rl_outstream;
+static FILE *tui_old_rl_outstream;
+#ifdef TUI_USE_PIPE_FOR_READLINE
+static int tui_readline_pipe[2];
+#endif
+
+/* The last gdb prompt that was registered in readline.
+ This may be the main gdb prompt or a secondary prompt. */
+static char *tui_rl_saved_prompt;
+
+static unsigned int tui_handle_resize_during_io (unsigned int);
+
+static void
+tui_putc (char c)
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ tui_puts (buf);
+}
+
+/* Print the string in the curses command window. */
+void
+tui_puts (const char *string)
+{
+ static int tui_skip_line = -1;
+ char c;
+ WINDOW *w;
+
+ w = TUI_CMD_WIN->generic.handle;
+ while ((c = *string++) != 0)
+ {
+ /* Catch annotation and discard them. We need two \032 and
+ discard until a \n is seen. */
+ if (c == '\032')
+ {
+ tui_skip_line++;
+ }
+ else if (tui_skip_line != 1)
+ {
+ tui_skip_line = -1;
+ waddch (w, c);
+ }
+ else if (c == '\n')
+ tui_skip_line = -1;
+ }
+ getyx (w, TUI_CMD_WIN->detail.command_info.cur_line,
+ TUI_CMD_WIN->detail.command_info.curch);
+ TUI_CMD_WIN->detail.command_info.start_line = TUI_CMD_WIN->detail.command_info.cur_line;
+
+ /* We could defer the following. */
+ wrefresh (w);
+ fflush (stdout);
+}
+
+/* Readline callback.
+ Redisplay the command line with its prompt after readline has
+ changed the edited text. */
+void
+tui_redisplay_readline (void)
+{
+ int prev_col;
+ int height;
+ int col, line;
+ int c_pos;
+ int c_line;
+ int in;
+ WINDOW *w;
+ char *prompt;
+ int start_line;
+
+ /* Detect when we temporarily left SingleKey and now the readline
+ edit buffer is empty, automatically restore the SingleKey mode. */
+ if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0)
+ tui_set_key_mode (TUI_SINGLE_KEY_MODE);
+
+ if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
+ prompt = "";
+ else
+ prompt = tui_rl_saved_prompt;
+
+ c_pos = -1;
+ c_line = -1;
+ w = TUI_CMD_WIN->generic.handle;
+ start_line = TUI_CMD_WIN->detail.command_info.start_line;
+ wmove (w, start_line, 0);
+ prev_col = 0;
+ height = 1;
+ for (in = 0; prompt && prompt[in]; in++)
+ {
+ waddch (w, prompt[in]);
+ getyx (w, line, col);
+ if (col < prev_col)
+ height++;
+ prev_col = col;
+ }
+ for (in = 0; in < rl_end; in++)
+ {
+ unsigned char c;
+
+ c = (unsigned char) rl_line_buffer[in];
+ if (in == rl_point)
+ {
+ getyx (w, c_line, c_pos);
+ }
+
+ if (CTRL_CHAR (c) || c == RUBOUT)
+ {
+ waddch (w, '^');
+ waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
+ }
+ else
+ {
+ waddch (w, c);
+ }
+ if (c == '\n')
+ {
+ getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
+ TUI_CMD_WIN->detail.command_info.curch);
+ }
+ getyx (w, line, col);
+ if (col < prev_col)
+ height++;
+ prev_col = col;
+ }
+ wclrtobot (w);
+ getyx (w, TUI_CMD_WIN->detail.command_info.start_line,
+ TUI_CMD_WIN->detail.command_info.curch);
+ if (c_line >= 0)
+ {
+ wmove (w, c_line, c_pos);
+ TUI_CMD_WIN->detail.command_info.cur_line = c_line;
+ TUI_CMD_WIN->detail.command_info.curch = c_pos;
+ }
+ TUI_CMD_WIN->detail.command_info.start_line -= height - 1;
+
+ wrefresh (w);
+ fflush(stdout);
+}
+
+/* Readline callback to prepare the terminal. It is called once
+ each time we enter readline. Terminal is already setup in curses mode. */
+static void
+tui_prep_terminal (int notused1)
+{
+ /* Save the prompt registered in readline to correctly display it.
+ (we can't use gdb_prompt() due to secondary prompts and can't use
+ rl_prompt because it points to an alloca buffer). */
+ xfree (tui_rl_saved_prompt);
+ tui_rl_saved_prompt = xstrdup (rl_prompt);
+}
+
+/* Readline callback to restore the terminal. It is called once
+ each time we leave readline. There is nothing to do in curses mode. */
+static void
+tui_deprep_terminal (void)
+{
+}
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+/* Read readline output pipe and feed the command window with it.
+ Should be removed when readline is clean. */
+static void
+tui_readline_output (int code, gdb_client_data data)
+{
+ int size;
+ char buf[256];
+
+ size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
+ if (size > 0 && tui_active)
+ {
+ buf[size] = 0;
+ tui_puts (buf);
+ }
+}
+#endif
+
+/* Return the portion of PATHNAME that should be output when listing
+ possible completions. If we are hacking filename completion, we
+ are only interested in the basename, the portion following the
+ final slash. Otherwise, we return what we were passed.
+
+ Comes from readline/complete.c */
+static char *
+printable_part (char *pathname)
+{
+ char *temp;
+
+ temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
+#if defined (__MSDOS__)
+ if (rl_filename_completion_desired && temp == 0 && isalpha (pathname[0]) && pathname[1] == ':')
+ temp = pathname + 1;
+#endif
+ return (temp ? ++temp : pathname);
+}
+
+/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
+ are using it, check for and output a single character for `special'
+ filenames. Return the number of characters we output. */
+
+#define PUTX(c) \
+ do { \
+ if (CTRL_CHAR (c)) \
+ { \
+ tui_puts ("^"); \
+ tui_putc (UNCTRL (c)); \
+ printed_len += 2; \
+ } \
+ else if (c == RUBOUT) \
+ { \
+ tui_puts ("^?"); \
+ printed_len += 2; \
+ } \
+ else \
+ { \
+ tui_putc (c); \
+ printed_len++; \
+ } \
+ } while (0)
+
+static int
+print_filename (char *to_print, char *full_pathname)
+{
+ int printed_len = 0;
+ char *s;
+
+ for (s = to_print; *s; s++)
+ {
+ PUTX (*s);
+ }
+ return printed_len;
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed.
+ Comes from readline/complete.c */
+static int
+get_y_or_n (void)
+{
+ extern int _rl_abort_internal ();
+ int c;
+
+ for (;;)
+ {
+ c = rl_read_key ();
+ if (c == 'y' || c == 'Y' || c == ' ')
+ return (1);
+ if (c == 'n' || c == 'N' || c == RUBOUT)
+ return (0);
+ if (c == ABORT_CHAR)
+ _rl_abort_internal ();
+ beep ();
+ }
+}
+
+/* A convenience function for displaying a list of strings in
+ columnar format on readline's output stream. MATCHES is the list
+ of strings, in argv format, LEN is the number of strings in MATCHES,
+ and MAX is the length of the longest string in MATCHES.
+
+ Comes from readline/complete.c and modified to write in
+ the TUI command window using tui_putc/tui_puts. */
+static void
+tui_rl_display_match_list (char **matches, int len, int max)
+{
+ typedef int QSFUNC (const void *, const void *);
+ extern int _rl_qsort_string_compare (const void*, const void*);
+ extern int _rl_print_completions_horizontally;
+
+ int count, limit, printed_len;
+ int i, j, k, l;
+ char *temp;
+
+ /* Screen dimension correspond to the TUI command window. */
+ int screenwidth = TUI_CMD_WIN->generic.width;
+
+ /* If there are many items, then ask the user if she really wants to
+ see them all. */
+ if (len >= rl_completion_query_items)
+ {
+ char msg[256];
+
+ sprintf (msg, "\nDisplay all %d possibilities? (y or n)", len);
+ tui_puts (msg);
+ if (get_y_or_n () == 0)
+ {
+ tui_puts ("\n");
+ return;
+ }
+ }
+
+ /* How many items of MAX length can we fit in the screen window? */
+ max += 2;
+ limit = screenwidth / max;
+ if (limit != 1 && (limit * max == screenwidth))
+ limit--;
+
+ /* Avoid a possible floating exception. If max > screenwidth,
+ limit will be 0 and a divide-by-zero fault will result. */
+ if (limit == 0)
+ limit = 1;
+
+ /* How many iterations of the printing loop? */
+ count = (len + (limit - 1)) / limit;
+
+ /* Watch out for special case. If LEN is less than LIMIT, then
+ just do the inner printing loop.
+ 0 < len <= limit implies count = 1. */
+
+ /* Sort the items if they are not already sorted. */
+ if (rl_ignore_completion_duplicates == 0)
+ qsort (matches + 1, len, sizeof (char *),
+ (QSFUNC *)_rl_qsort_string_compare);
+
+ tui_putc ('\n');
+
+ if (_rl_print_completions_horizontally == 0)
+ {
+ /* Print the sorted items, up-and-down alphabetically, like ls. */
+ for (i = 1; i <= count; i++)
+ {
+ for (j = 0, l = i; j < limit; j++)
+ {
+ if (l > len || matches[l] == 0)
+ break;
+ else
+ {
+ temp = printable_part (matches[l]);
+ printed_len = print_filename (temp, matches[l]);
+
+ if (j + 1 < limit)
+ for (k = 0; k < max - printed_len; k++)
+ tui_putc (' ');
+ }
+ l += count;
+ }
+ tui_putc ('\n');
+ }
+ }
+ else
+ {
+ /* Print the sorted items, across alphabetically, like ls -x. */
+ for (i = 1; matches[i]; i++)
+ {
+ temp = printable_part (matches[i]);
+ printed_len = print_filename (temp, matches[i]);
+ /* Have we reached the end of this line? */
+ if (matches[i+1])
+ {
+ if (i && (limit > 1) && (i % limit) == 0)
+ tui_putc ('\n');
+ else
+ for (k = 0; k < max - printed_len; k++)
+ tui_putc (' ');
+ }
+ }
+ tui_putc ('\n');
+ }
+}
+
+/* Setup the IO for curses or non-curses mode.
+ - In non-curses mode, readline and gdb use the standard input and
+ standard output/error directly.
+ - In curses mode, the standard output/error is controlled by TUI
+ with the tui_stdout and tui_stderr. The output is redirected in
+ the curses command window. Several readline callbacks are installed
+ so that readline asks for its input to the curses command window
+ with wgetch(). */
+void
+tui_setup_io (int mode)
+{
+ extern int readline_echoing_p;
+
+ if (mode)
+ {
+ /* Redirect readline to TUI. */
+ tui_old_rl_redisplay_function = rl_redisplay_function;
+ tui_old_rl_deprep_terminal = rl_deprep_term_function;
+ tui_old_rl_prep_terminal = rl_prep_term_function;
+ tui_old_rl_getc_function = rl_getc_function;
+ tui_old_rl_outstream = rl_outstream;
+ tui_old_readline_echoing_p = readline_echoing_p;
+ rl_redisplay_function = tui_redisplay_readline;
+ rl_deprep_term_function = tui_deprep_terminal;
+ rl_prep_term_function = tui_prep_terminal;
+ rl_getc_function = tui_getc;
+ readline_echoing_p = 0;
+ rl_outstream = tui_rl_outstream;
+ rl_prompt = 0;
+ rl_completion_display_matches_hook = tui_rl_display_match_list;
+ rl_already_prompted = 0;
+
+ /* Keep track of previous gdb output. */
+ tui_old_stdout = gdb_stdout;
+ tui_old_stderr = gdb_stderr;
+ tui_old_uiout = uiout;
+
+ /* Reconfigure gdb output. */
+ gdb_stdout = tui_stdout;
+ gdb_stderr = tui_stderr;
+ gdb_stdlog = gdb_stdout; /* for moment */
+ gdb_stdtarg = gdb_stderr; /* for moment */
+ uiout = tui_out;
+
+ /* Save tty for SIGCONT. */
+ savetty ();
+ }
+ else
+ {
+ /* Restore gdb output. */
+ gdb_stdout = tui_old_stdout;
+ gdb_stderr = tui_old_stderr;
+ gdb_stdlog = gdb_stdout; /* for moment */
+ gdb_stdtarg = gdb_stderr; /* for moment */
+ uiout = tui_old_uiout;
+
+ /* Restore readline. */
+ rl_redisplay_function = tui_old_rl_redisplay_function;
+ rl_deprep_term_function = tui_old_rl_deprep_terminal;
+ rl_prep_term_function = tui_old_rl_prep_terminal;
+ rl_getc_function = tui_old_rl_getc_function;
+ rl_outstream = tui_old_rl_outstream;
+ rl_completion_display_matches_hook = 0;
+ readline_echoing_p = tui_old_readline_echoing_p;
+ rl_already_prompted = 0;
+
+ /* Save tty for SIGCONT. */
+ savetty ();
+ }
+}
+
+#ifdef SIGCONT
+/* Catch SIGCONT to restore the terminal and refresh the screen. */
+static void
+tui_cont_sig (int sig)
+{
+ if (tui_active)
+ {
+ /* Restore the terminal setting because another process (shell)
+ might have changed it. */
+ resetty ();
+
+ /* Force a refresh of the screen. */
+ tui_refresh_all_win ();
+
+ /* Update cursor position on the screen. */
+ wmove (TUI_CMD_WIN->generic.handle,
+ TUI_CMD_WIN->detail.command_info.start_line,
+ TUI_CMD_WIN->detail.command_info.curch);
+ wrefresh (TUI_CMD_WIN->generic.handle);
+ }
+ signal (sig, tui_cont_sig);
+}
+#endif
+
+/* Initialize the IO for gdb in curses mode. */
+void
+tui_initialize_io (void)
+{
+#ifdef SIGCONT
+ signal (SIGCONT, tui_cont_sig);
+#endif
+
+ /* Create tui output streams. */
+ tui_stdout = tui_fileopen (stdout);
+ tui_stderr = tui_fileopen (stderr);
+ tui_out = tui_out_new (tui_stdout);
+
+ /* Create the default UI. It is not created because we installed
+ a init_ui_hook. */
+ tui_old_uiout = uiout = cli_out_new (gdb_stdout);
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+ /* Temporary solution for readline writing to stdout:
+ redirect readline output in a pipe, read that pipe and
+ output the content in the curses command window. */
+ if (pipe (tui_readline_pipe) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
+ exit (1);
+ }
+ tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
+ if (tui_rl_outstream == 0)
+ {
+ fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
+ exit (1);
+ }
+ setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0);
+
+#ifdef O_NONBLOCK
+ (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+ (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
+#endif
+#endif
+ add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
+#else
+ tui_rl_outstream = stdout;
+#endif
+}
+
+/* Get a character from the command window. This is called from the readline
+ package. */
+int
+tui_getc (FILE *fp)
+{
+ int ch;
+ WINDOW *w;
+
+ w = TUI_CMD_WIN->generic.handle;
+
+#ifdef TUI_USE_PIPE_FOR_READLINE
+ /* Flush readline output. */
+ tui_readline_output (GDB_READABLE, 0);
+#endif
+
+ ch = wgetch (w);
+ ch = tui_handle_resize_during_io (ch);
+
+ /* The \n must be echoed because it will not be printed by readline. */
+ if (ch == '\n')
+ {
+ /* When hitting return with an empty input, gdb executes the last
+ command. If we emit a newline, this fills up the command window
+ with empty lines with gdb prompt at beginning. Instead of that,
+ stay on the same line but provide a visual effect to show the
+ user we recognized the command. */
+ if (rl_end == 0)
+ {
+ wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0);
+
+ /* Clear the line. This will blink the gdb prompt since
+ it will be redrawn at the same line. */
+ wclrtoeol (w);
+ wrefresh (w);
+ napms (20);
+ }
+ else
+ {
+ wmove (w, TUI_CMD_WIN->detail.command_info.cur_line,
+ TUI_CMD_WIN->detail.command_info.curch);
+ waddch (w, ch);
+ }
+ }
+
+ if (key_is_command_char (ch))
+ { /* Handle prev/next/up/down here */
+ ch = tui_dispatch_ctrl_char (ch);
+ }
+
+ if (ch == '\n' || ch == '\r' || ch == '\f')
+ TUI_CMD_WIN->detail.command_info.curch = 0;
+ if (ch == KEY_BACKSPACE)
+ return '\b';
+
+ return ch;
+}
+
+
+/* Cleanup when a resize has occured.
+ Returns the character that must be processed. */
+static unsigned int
+tui_handle_resize_during_io (unsigned int original_ch)
+{
+ if (tui_win_resized ())
+ {
+ tui_refresh_all_win ();
+ dont_repeat ();
+ tui_set_win_resized_to (FALSE);
+ return '\n';
+ }
+ else
+ return original_ch;
+}
--- /dev/null
+/* TUI support I/O functions.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_IO_H
+#define TUI_IO_H
+
+struct ui_out;
+
+/* Print the string in the curses command window. */
+extern void tui_puts (const char *);
+
+/* Setup the IO for curses or non-curses mode. */
+extern void tui_setup_io (int mode);
+
+/* Initialize the IO for gdb in curses mode. */
+extern void tui_initialize_io (void);
+
+/* Get a character from the command window. */
+extern int tui_getc (FILE *);
+
+/* Readline callback.
+ Redisplay the command line with its prompt after readline has
+ changed the edited text. */
+extern void tui_redisplay_readline (void);
+
+extern struct ui_out *tui_out;
+extern struct ui_out *tui_old_uiout;
+
+extern int key_is_start_sequence (int ch);
+extern int key_is_end_sequence (int ch);
+extern int key_is_backspace (int ch);
+extern int key_is_command_char (int ch);
+
+#endif
--- /dev/null
+/* TUI layout window management.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "frame.h"
+#include "source.h"
+#include <ctype.h>
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-windata.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-regs.h"
+#include "tui/tui-win.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-disasm.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/*******************************
+** Static Local Decls
+********************************/
+static void show_layout (enum tui_layout_type);
+static void init_gen_win_info (struct tui_gen_win_info *, enum tui_win_type, int, int, int, int);
+static void init_and_make_win (void **, enum tui_win_type, int, int, int, int, int);
+static void show_source_or_disasm_and_command (enum tui_layout_type);
+static void make_source_or_disasm_window (struct tui_win_info * *, enum tui_win_type, int, int);
+static void make_command_window (struct tui_win_info * *, int, int);
+static void make_source_window (struct tui_win_info * *, int, int);
+static void make_disasm_window (struct tui_win_info * *, int, int);
+static void make_data_window (struct tui_win_info * *, int, int);
+static void show_source_command (void);
+static void show_disasm_command (void);
+static void show_source_disasm_command (void);
+static void show_data (enum tui_layout_type);
+static enum tui_layout_type next_layout (void);
+static enum tui_layout_type prev_layout (void);
+static void tui_layout_command (char *, int);
+static void tui_toggle_layout_command (char *, int);
+static void tui_toggle_split_layout_command (char *, int);
+static CORE_ADDR extract_display_start_addr (void);
+static void tui_handle_xdb_layout (struct tui_layout_def *);
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+
+#define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"
+
+/* Show the screen layout defined. */
+static void
+show_layout (enum tui_layout_type layout)
+{
+ enum tui_layout_type cur_layout = tui_current_layout ();
+
+ if (layout != cur_layout)
+ {
+ /*
+ ** Since the new layout may cause changes in window size, we
+ ** should free the content and reallocate on next display of
+ ** source/asm
+ */
+ tui_free_all_source_wins_content ();
+ tui_clear_source_windows ();
+ if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND)
+ {
+ show_data (layout);
+ tui_refresh_all (tui_win_list);
+ }
+ else
+ {
+ /* First make the current layout be invisible */
+ tui_make_all_invisible ();
+ tui_make_invisible (tui_locator_win_info_ptr ());
+
+ switch (layout)
+ {
+ /* Now show the new layout */
+ case SRC_COMMAND:
+ show_source_command ();
+ tui_add_to_source_windows (TUI_SRC_WIN);
+ break;
+ case DISASSEM_COMMAND:
+ show_disasm_command ();
+ tui_add_to_source_windows (TUI_DISASM_WIN);
+ break;
+ case SRC_DISASSEM_COMMAND:
+ show_source_disasm_command ();
+ tui_add_to_source_windows (TUI_SRC_WIN);
+ tui_add_to_source_windows (TUI_DISASM_WIN);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
+/* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
+ SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.
+ If the layout is SRC_DATA_COMMAND, DISASSEM_DATA_COMMAND, or
+ UNDEFINED_LAYOUT, then the data window is populated according to
+ regs_display_type. */
+enum tui_status
+tui_set_layout (enum tui_layout_type layout_type,
+ enum tui_register_display_type regs_display_type)
+{
+ enum tui_status status = TUI_SUCCESS;
+
+ if (layout_type != UNDEFINED_LAYOUT || regs_display_type != TUI_UNDEFINED_REGS)
+ {
+ enum tui_layout_type cur_layout = tui_current_layout (), new_layout = UNDEFINED_LAYOUT;
+ int regs_populate = FALSE;
+ CORE_ADDR addr = extract_display_start_addr ();
+ struct tui_win_info * new_win_with_focus = (struct tui_win_info *) NULL;
+ struct tui_win_info * win_with_focus = tui_win_with_focus ();
+ struct tui_layout_def * layout_def = tui_layout_def ();
+
+
+ if (layout_type == UNDEFINED_LAYOUT &&
+ regs_display_type != TUI_UNDEFINED_REGS)
+ {
+ if (cur_layout == SRC_DISASSEM_COMMAND)
+ new_layout = DISASSEM_DATA_COMMAND;
+ else if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
+ new_layout = SRC_DATA_COMMAND;
+ else if (cur_layout == DISASSEM_COMMAND ||
+ cur_layout == DISASSEM_DATA_COMMAND)
+ new_layout = DISASSEM_DATA_COMMAND;
+ }
+ else
+ new_layout = layout_type;
+
+ regs_populate = (new_layout == SRC_DATA_COMMAND ||
+ new_layout == DISASSEM_DATA_COMMAND ||
+ regs_display_type != TUI_UNDEFINED_REGS);
+ if (new_layout != cur_layout || regs_display_type != TUI_UNDEFINED_REGS)
+ {
+ if (new_layout != cur_layout)
+ {
+ show_layout (new_layout);
+ /*
+ ** Now determine where focus should be
+ */
+ if (win_with_focus != TUI_CMD_WIN)
+ {
+ switch (new_layout)
+ {
+ case SRC_COMMAND:
+ tui_set_win_focus_to (TUI_SRC_WIN);
+ layout_def->display_mode = SRC_WIN;
+ layout_def->split = FALSE;
+ break;
+ case DISASSEM_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = tui_get_begin_asm_address ();
+ tui_set_win_focus_to (TUI_DISASM_WIN);
+ layout_def->display_mode = DISASSEM_WIN;
+ layout_def->split = FALSE;
+ break;
+ case SRC_DISASSEM_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = tui_get_begin_asm_address ();
+ if (win_with_focus == TUI_SRC_WIN)
+ tui_set_win_focus_to (TUI_SRC_WIN);
+ else
+ tui_set_win_focus_to (TUI_DISASM_WIN);
+ layout_def->split = TRUE;
+ break;
+ case SRC_DATA_COMMAND:
+ if (win_with_focus != TUI_DATA_WIN)
+ tui_set_win_focus_to (TUI_SRC_WIN);
+ else
+ tui_set_win_focus_to (TUI_DATA_WIN);
+ layout_def->display_mode = SRC_WIN;
+ layout_def->split = FALSE;
+ break;
+ case DISASSEM_DATA_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = tui_get_begin_asm_address ();
+ if (win_with_focus != TUI_DATA_WIN)
+ tui_set_win_focus_to (TUI_DISASM_WIN);
+ else
+ tui_set_win_focus_to (TUI_DATA_WIN);
+ layout_def->display_mode = DISASSEM_WIN;
+ layout_def->split = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (new_win_with_focus != (struct tui_win_info *) NULL)
+ tui_set_win_focus_to (new_win_with_focus);
+ /*
+ ** Now update the window content
+ */
+ if (!regs_populate &&
+ (new_layout == SRC_DATA_COMMAND ||
+ new_layout == DISASSEM_DATA_COMMAND))
+ tui_display_all_data ();
+
+ tui_update_source_windows_with_addr (addr);
+ }
+ if (regs_populate)
+ {
+ layout_def->regs_display_type =
+ (regs_display_type == TUI_UNDEFINED_REGS ?
+ TUI_GENERAL_REGS : regs_display_type);
+ tui_show_registers (layout_def->regs_display_type);
+ }
+ }
+ }
+ else
+ status = TUI_FAILURE;
+
+ return status;
+}
+
+/* Add the specified window to the layout in a logical way. This
+ means setting up the most logical layout given the window to be
+ added. */
+void
+tui_add_win_to_layout (enum tui_win_type type)
+{
+ enum tui_layout_type cur_layout = tui_current_layout ();
+
+ switch (type)
+ {
+ case SRC_WIN:
+ if (cur_layout != SRC_COMMAND &&
+ cur_layout != SRC_DISASSEM_COMMAND &&
+ cur_layout != SRC_DATA_COMMAND)
+ {
+ tui_clear_source_windows_detail ();
+ if (cur_layout == DISASSEM_DATA_COMMAND)
+ show_layout (SRC_DATA_COMMAND);
+ else
+ show_layout (SRC_COMMAND);
+ }
+ break;
+ case DISASSEM_WIN:
+ if (cur_layout != DISASSEM_COMMAND &&
+ cur_layout != SRC_DISASSEM_COMMAND &&
+ cur_layout != DISASSEM_DATA_COMMAND)
+ {
+ tui_clear_source_windows_detail ();
+ if (cur_layout == SRC_DATA_COMMAND)
+ show_layout (DISASSEM_DATA_COMMAND);
+ else
+ show_layout (DISASSEM_COMMAND);
+ }
+ break;
+ case DATA_WIN:
+ if (cur_layout != SRC_DATA_COMMAND &&
+ cur_layout != DISASSEM_DATA_COMMAND)
+ {
+ if (cur_layout == DISASSEM_COMMAND)
+ show_layout (DISASSEM_DATA_COMMAND);
+ else
+ show_layout (SRC_DATA_COMMAND);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+/* Answer the height of a window. If it hasn't been created yet,
+ answer what the height of a window would be based upon its type and
+ the layout. */
+int
+tui_default_win_height (enum tui_win_type type, enum tui_layout_type layout)
+{
+ int h;
+
+ if (tui_win_list[type] != (struct tui_win_info *) NULL)
+ h = tui_win_list[type]->generic.height;
+ else
+ {
+ switch (layout)
+ {
+ case SRC_COMMAND:
+ case DISASSEM_COMMAND:
+ if (TUI_CMD_WIN == NULL)
+ h = tui_term_height () / 2;
+ else
+ h = tui_term_height () - TUI_CMD_WIN->generic.height;
+ break;
+ case SRC_DISASSEM_COMMAND:
+ case SRC_DATA_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ if (TUI_CMD_WIN == NULL)
+ h = tui_term_height () / 3;
+ else
+ h = (tui_term_height () - TUI_CMD_WIN->generic.height) / 2;
+ break;
+ default:
+ h = 0;
+ break;
+ }
+ }
+
+ return h;
+}
+
+
+/* Answer the height of a window. If it hasn't been created yet,
+ answer what the height of a window would be based upon its type and
+ the layout. */
+int
+tui_default_win_viewport_height (enum tui_win_type type,
+ enum tui_layout_type layout)
+{
+ int h;
+
+ h = tui_default_win_height (type, layout);
+
+ if (tui_win_list[type] == TUI_CMD_WIN)
+ h -= 1;
+ else
+ h -= 2;
+
+ return h;
+}
+
+
+/* Function to initialize gdb commands, for tui window layout
+ manipulation. */
+void
+_initialize_tui_layout (void)
+{
+ add_com ("layout", class_tui, tui_layout_command,
+ "Change the layout of windows.\n\
+Usage: layout prev | next | <layout_name> \n\
+Layout names are:\n\
+ src : Displays source and command windows.\n\
+ asm : Displays disassembly and command windows.\n\
+ split : Displays source, disassembly and command windows.\n\
+ regs : Displays register window. If existing layout\n\
+ is source/command or assembly/command, the \n\
+ register window is displayed. If the\n\
+ source/assembly/command (split) is displayed, \n\
+ the register window is displayed with \n\
+ the window that has current logical focus.\n");
+ if (xdb_commands)
+ {
+ add_com ("td", class_tui, tui_toggle_layout_command,
+ "Toggle between Source/Command and Disassembly/Command layouts.\n");
+ add_com ("ts", class_tui, tui_toggle_split_layout_command,
+ "Toggle between Source/Command or Disassembly/Command and \n\
+Source/Disassembly/Command layouts.\n");
+ }
+}
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+/* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA,
+ REGS, $REGS, $GREGS, $FREGS, $SREGS. */
+enum tui_status
+tui_set_layout_for_display_command (const char *layout_name)
+{
+ enum tui_status status = TUI_SUCCESS;
+
+ if (layout_name != (char *) NULL)
+ {
+ int i;
+ char *buf_ptr;
+ enum tui_layout_type new_layout = UNDEFINED_LAYOUT;
+ enum tui_register_display_type dpy_type = TUI_UNDEFINED_REGS;
+ enum tui_layout_type cur_layout = tui_current_layout ();
+
+ buf_ptr = (char *) xstrdup (layout_name);
+ for (i = 0; (i < strlen (layout_name)); i++)
+ buf_ptr[i] = toupper (buf_ptr[i]);
+
+ /* First check for ambiguous input */
+ if (strlen (buf_ptr) <= 1 && (*buf_ptr == 'S' || *buf_ptr == '$'))
+ {
+ warning ("Ambiguous command input.\n");
+ status = TUI_FAILURE;
+ }
+ else
+ {
+ if (subset_compare (buf_ptr, "SRC"))
+ new_layout = SRC_COMMAND;
+ else if (subset_compare (buf_ptr, "ASM"))
+ new_layout = DISASSEM_COMMAND;
+ else if (subset_compare (buf_ptr, "SPLIT"))
+ new_layout = SRC_DISASSEM_COMMAND;
+ else if (subset_compare (buf_ptr, "REGS") ||
+ subset_compare (buf_ptr, TUI_GENERAL_SPECIAL_REGS_NAME) ||
+ subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME) ||
+ subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME) ||
+ subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
+ {
+ if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
+ new_layout = SRC_DATA_COMMAND;
+ else
+ new_layout = DISASSEM_DATA_COMMAND;
+
+/* could ifdef out the following code. when compile with -z, there are null
+ pointer references that cause a core dump if 'layout regs' is the first
+ layout command issued by the user. HP has asked us to hook up this code
+ - edie epstein
+ */
+ if (subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME))
+ {
+ if (TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+ TUI_SFLOAT_REGS &&
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+ TUI_DFLOAT_REGS)
+ dpy_type = TUI_SFLOAT_REGS;
+ else
+ dpy_type =
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type;
+ }
+ else if (subset_compare (buf_ptr,
+ TUI_GENERAL_SPECIAL_REGS_NAME))
+ dpy_type = TUI_GENERAL_AND_SPECIAL_REGS;
+ else if (subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME))
+ dpy_type = TUI_GENERAL_REGS;
+ else if (subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME))
+ dpy_type = TUI_SPECIAL_REGS;
+ else if (TUI_DATA_WIN)
+ {
+ if (TUI_DATA_WIN->detail.data_display_info.regs_display_type !=
+ TUI_UNDEFINED_REGS)
+ dpy_type =
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type;
+ else
+ dpy_type = TUI_GENERAL_REGS;
+ }
+
+/* end of potential ifdef
+ */
+
+/* if ifdefed out code above, then assume that the user wishes to display the
+ general purpose registers
+ */
+
+/* dpy_type = TUI_GENERAL_REGS;
+ */
+ }
+ else if (subset_compare (buf_ptr, "NEXT"))
+ new_layout = next_layout ();
+ else if (subset_compare (buf_ptr, "PREV"))
+ new_layout = prev_layout ();
+ else
+ status = TUI_FAILURE;
+ xfree (buf_ptr);
+
+ tui_set_layout (new_layout, dpy_type);
+ }
+ }
+ else
+ status = TUI_FAILURE;
+
+ return status;
+}
+
+
+static CORE_ADDR
+extract_display_start_addr (void)
+{
+ enum tui_layout_type cur_layout = tui_current_layout ();
+ CORE_ADDR addr;
+ CORE_ADDR pc;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+ switch (cur_layout)
+ {
+ case SRC_COMMAND:
+ case SRC_DATA_COMMAND:
+ find_line_pc (cursal.symtab,
+ TUI_SRC_WIN->detail.source_info.start_line_or_addr.line_no,
+ &pc);
+ addr = pc;
+ break;
+ case DISASSEM_COMMAND:
+ case SRC_DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ addr = TUI_DISASM_WIN->detail.source_info.start_line_or_addr.addr;
+ break;
+ default:
+ addr = 0;
+ break;
+ }
+
+ return addr;
+}
+
+
+static void
+tui_handle_xdb_layout (struct tui_layout_def * layout_def)
+{
+ if (layout_def->split)
+ {
+ tui_set_layout (SRC_DISASSEM_COMMAND, TUI_UNDEFINED_REGS);
+ tui_set_win_focus_to (tui_win_list[layout_def->display_mode]);
+ }
+ else
+ {
+ if (layout_def->display_mode == SRC_WIN)
+ tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
+ else
+ tui_set_layout (DISASSEM_DATA_COMMAND, layout_def->regs_display_type);
+ }
+}
+
+
+static void
+tui_toggle_layout_command (char *arg, int from_tty)
+{
+ struct tui_layout_def * layout_def = tui_layout_def ();
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (layout_def->display_mode == SRC_WIN)
+ layout_def->display_mode = DISASSEM_WIN;
+ else
+ layout_def->display_mode = SRC_WIN;
+
+ if (!layout_def->split)
+ tui_handle_xdb_layout (layout_def);
+}
+
+
+static void
+tui_toggle_split_layout_command (char *arg, int from_tty)
+{
+ struct tui_layout_def * layout_def = tui_layout_def ();
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ layout_def->split = (!layout_def->split);
+ tui_handle_xdb_layout (layout_def);
+}
+
+
+static void
+tui_layout_command (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+
+ /* Switch to the selected layout. */
+ if (tui_set_layout_for_display_command (arg) != TUI_SUCCESS)
+ warning ("Invalid layout specified.\n%s", LAYOUT_USAGE);
+
+}
+
+/* Answer the previous layout to cycle to. */
+static enum tui_layout_type
+next_layout (void)
+{
+ enum tui_layout_type new_layout;
+
+ new_layout = tui_current_layout ();
+ if (new_layout == UNDEFINED_LAYOUT)
+ new_layout = SRC_COMMAND;
+ else
+ {
+ new_layout++;
+ if (new_layout == UNDEFINED_LAYOUT)
+ new_layout = SRC_COMMAND;
+ }
+
+ return new_layout;
+}
+
+
+/* Answer the next layout to cycle to. */
+static enum tui_layout_type
+prev_layout (void)
+{
+ enum tui_layout_type new_layout;
+
+ new_layout = tui_current_layout ();
+ if (new_layout == SRC_COMMAND)
+ new_layout = DISASSEM_DATA_COMMAND;
+ else
+ {
+ new_layout--;
+ if (new_layout == UNDEFINED_LAYOUT)
+ new_layout = DISASSEM_DATA_COMMAND;
+ }
+
+ return new_layout;
+}
+
+
+
+static void
+make_command_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+ init_and_make_win ((void **) win_info_ptr,
+ CMD_WIN,
+ height,
+ tui_term_width (),
+ 0,
+ origin_y,
+ DONT_BOX_WINDOW);
+
+ (*win_info_ptr)->can_highlight = FALSE;
+}
+
+
+/*
+ ** make_source_window().
+ */
+static void
+make_source_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+ make_source_or_disasm_window (win_info_ptr, SRC_WIN, height, origin_y);
+
+ return;
+} /* make_source_window */
+
+
+/*
+ ** make_disasm_window().
+ */
+static void
+make_disasm_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+ make_source_or_disasm_window (win_info_ptr, DISASSEM_WIN, height, origin_y);
+
+ return;
+} /* make_disasm_window */
+
+
+static void
+make_data_window (struct tui_win_info * * win_info_ptr, int height, int origin_y)
+{
+ init_and_make_win ((void **) win_info_ptr,
+ DATA_WIN,
+ height,
+ tui_term_width (),
+ 0,
+ origin_y,
+ BOX_WINDOW);
+}
+
+
+
+/* Show the Source/Command layout. */
+static void
+show_source_command (void)
+{
+ show_source_or_disasm_and_command (SRC_COMMAND);
+}
+
+
+/* Show the Dissassem/Command layout. */
+static void
+show_disasm_command (void)
+{
+ show_source_or_disasm_and_command (DISASSEM_COMMAND);
+}
+
+
+/* Show the Source/Disassem/Command layout. */
+static void
+show_source_disasm_command (void)
+{
+ if (tui_current_layout () != SRC_DISASSEM_COMMAND)
+ {
+ int cmd_height, src_height, asm_height;
+
+ if (TUI_CMD_WIN != NULL)
+ cmd_height = TUI_CMD_WIN->generic.height;
+ else
+ cmd_height = tui_term_height () / 3;
+
+ src_height = (tui_term_height () - cmd_height) / 2;
+ asm_height = tui_term_height () - (src_height + cmd_height);
+
+ if (TUI_SRC_WIN == NULL)
+ make_source_window (&TUI_SRC_WIN, src_height, 0);
+ else
+ {
+ init_gen_win_info (&TUI_SRC_WIN->generic,
+ TUI_SRC_WIN->generic.type,
+ src_height,
+ TUI_SRC_WIN->generic.width,
+ TUI_SRC_WIN->detail.source_info.execution_info->width,
+ 0);
+ TUI_SRC_WIN->can_highlight = TRUE;
+ init_gen_win_info (TUI_SRC_WIN->detail.source_info.execution_info,
+ EXEC_INFO_WIN,
+ src_height,
+ 3,
+ 0,
+ 0);
+ tui_make_visible (&TUI_SRC_WIN->generic);
+ tui_make_visible (TUI_SRC_WIN->detail.source_info.execution_info);
+ TUI_SRC_WIN->detail.source_info.has_locator = FALSE;;
+ }
+ if (TUI_SRC_WIN != NULL)
+ {
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+ tui_show_source_content (TUI_SRC_WIN);
+ if (TUI_DISASM_WIN == NULL)
+ {
+ make_disasm_window (&TUI_DISASM_WIN, asm_height, src_height - 1);
+ init_and_make_win ((void **) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ (src_height + asm_height) - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ init_gen_win_info (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ (src_height + asm_height) - 1);
+ TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
+ init_gen_win_info (
+ &TUI_DISASM_WIN->generic,
+ TUI_DISASM_WIN->generic.type,
+ asm_height,
+ TUI_DISASM_WIN->generic.width,
+ TUI_DISASM_WIN->detail.source_info.execution_info->width,
+ src_height - 1);
+ init_gen_win_info (TUI_DISASM_WIN->detail.source_info.execution_info,
+ EXEC_INFO_WIN,
+ asm_height,
+ 3,
+ 0,
+ src_height - 1);
+ TUI_DISASM_WIN->can_highlight = TRUE;
+ tui_make_visible (&TUI_DISASM_WIN->generic);
+ tui_make_visible (TUI_DISASM_WIN->detail.source_info.execution_info);
+ }
+ if (TUI_DISASM_WIN != NULL)
+ {
+ TUI_SRC_WIN->detail.source_info.has_locator = FALSE;
+ TUI_DISASM_WIN->detail.source_info.has_locator = TRUE;
+ tui_make_visible (locator);
+ tui_show_locator_content ();
+ tui_show_source_content (TUI_DISASM_WIN);
+
+ if (TUI_CMD_WIN == NULL)
+ make_command_window (&TUI_CMD_WIN,
+ cmd_height,
+ tui_term_height () - cmd_height);
+ else
+ {
+ init_gen_win_info (&TUI_CMD_WIN->generic,
+ TUI_CMD_WIN->generic.type,
+ TUI_CMD_WIN->generic.height,
+ TUI_CMD_WIN->generic.width,
+ 0,
+ TUI_CMD_WIN->generic.origin.y);
+ TUI_CMD_WIN->can_highlight = FALSE;
+ tui_make_visible (&TUI_CMD_WIN->generic);
+ }
+ if (TUI_CMD_WIN != NULL)
+ tui_refresh_win (&TUI_CMD_WIN->generic);
+ }
+ }
+ tui_set_current_layout_to (SRC_DISASSEM_COMMAND);
+ }
+}
+
+
+/* Show the Source/Data/Command or the Dissassembly/Data/Command
+ layout. */
+static void
+show_data (enum tui_layout_type new_layout)
+{
+ int total_height = (tui_term_height () - TUI_CMD_WIN->generic.height);
+ int src_height, data_height;
+ enum tui_win_type win_type;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+
+ data_height = total_height / 2;
+ src_height = total_height - data_height;
+ tui_make_all_invisible ();
+ tui_make_invisible (locator);
+ make_data_window (&TUI_DATA_WIN, data_height, 0);
+ TUI_DATA_WIN->can_highlight = TRUE;
+ if (new_layout == SRC_DATA_COMMAND)
+ win_type = SRC_WIN;
+ else
+ win_type = DISASSEM_WIN;
+ if (tui_win_list[win_type] == NULL)
+ {
+ if (win_type == SRC_WIN)
+ make_source_window (&tui_win_list[win_type], src_height, data_height - 1);
+ else
+ make_disasm_window (&tui_win_list[win_type], src_height, data_height - 1);
+ init_and_make_win ((void **) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ total_height - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ init_gen_win_info (&tui_win_list[win_type]->generic,
+ tui_win_list[win_type]->generic.type,
+ src_height,
+ tui_win_list[win_type]->generic.width,
+ tui_win_list[win_type]->detail.source_info.execution_info->width,
+ data_height - 1);
+ init_gen_win_info (tui_win_list[win_type]->detail.source_info.execution_info,
+ EXEC_INFO_WIN,
+ src_height,
+ 3,
+ 0,
+ data_height - 1);
+ tui_make_visible (&tui_win_list[win_type]->generic);
+ tui_make_visible (tui_win_list[win_type]->detail.source_info.execution_info);
+ init_gen_win_info (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ total_height - 1);
+ }
+ tui_win_list[win_type]->detail.source_info.has_locator = TRUE;
+ tui_make_visible (locator);
+ tui_show_locator_content ();
+ tui_add_to_source_windows (tui_win_list[win_type]);
+ tui_set_current_layout_to (new_layout);
+}
+
+/*
+ ** init_gen_win_info().
+ */
+static void
+init_gen_win_info (struct tui_gen_win_info * win_info, enum tui_win_type type,
+ int height, int width, int origin_x, int origin_y)
+{
+ int h = height;
+
+ win_info->type = type;
+ win_info->width = width;
+ win_info->height = h;
+ if (h > 1)
+ {
+ win_info->viewport_height = h - 1;
+ if (win_info->type != CMD_WIN)
+ win_info->viewport_height--;
+ }
+ else
+ win_info->viewport_height = 1;
+ win_info->origin.x = origin_x;
+ win_info->origin.y = origin_y;
+
+ return;
+} /* init_gen_win_info */
+
+/*
+ ** init_and_make_win().
+ */
+static void
+init_and_make_win (void ** win_info_ptr, enum tui_win_type win_type,
+ int height, int width, int origin_x, int origin_y, int box_it)
+{
+ void *opaque_win_info = *win_info_ptr;
+ struct tui_gen_win_info * generic;
+
+ if (opaque_win_info == NULL)
+ {
+ if (tui_win_is_auxillary (win_type))
+ opaque_win_info = (void *) tui_alloc_generic_win_info ();
+ else
+ opaque_win_info = (void *) tui_alloc_win_info (win_type);
+ }
+ if (tui_win_is_auxillary (win_type))
+ generic = (struct tui_gen_win_info *) opaque_win_info;
+ else
+ generic = &((struct tui_win_info *) opaque_win_info)->generic;
+
+ if (opaque_win_info != NULL)
+ {
+ init_gen_win_info (generic, win_type, height, width, origin_x, origin_y);
+ if (!tui_win_is_auxillary (win_type))
+ {
+ if (generic->type == CMD_WIN)
+ ((struct tui_win_info *) opaque_win_info)->can_highlight = FALSE;
+ else
+ ((struct tui_win_info *) opaque_win_info)->can_highlight = TRUE;
+ }
+ tui_make_window (generic, box_it);
+ }
+ *win_info_ptr = opaque_win_info;
+}
+
+
+static void
+make_source_or_disasm_window (struct tui_win_info * * win_info_ptr, enum tui_win_type type,
+ int height, int origin_y)
+{
+ struct tui_gen_win_info * execution_info = (struct tui_gen_win_info *) NULL;
+
+ /*
+ ** Create the exeuction info window.
+ */
+ if (type == SRC_WIN)
+ execution_info = tui_source_exec_info_win_ptr ();
+ else
+ execution_info = tui_disassem_exec_info_win_ptr ();
+ init_and_make_win ((void **) & execution_info,
+ EXEC_INFO_WIN,
+ height,
+ 3,
+ 0,
+ origin_y,
+ DONT_BOX_WINDOW);
+ /*
+ ** Now create the source window.
+ */
+ init_and_make_win ((void **) win_info_ptr,
+ type,
+ height,
+ tui_term_width () - execution_info->width,
+ execution_info->width,
+ origin_y,
+ BOX_WINDOW);
+
+ (*win_info_ptr)->detail.source_info.execution_info = execution_info;
+}
+
+
+/* Show the Source/Command or the Disassem layout. */
+static void
+show_source_or_disasm_and_command (enum tui_layout_type layout_type)
+{
+ if (tui_current_layout () != layout_type)
+ {
+ struct tui_win_info * *win_info_ptr;
+ int src_height, cmd_height;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+ if (TUI_CMD_WIN != NULL)
+ cmd_height = TUI_CMD_WIN->generic.height;
+ else
+ cmd_height = tui_term_height () / 3;
+ src_height = tui_term_height () - cmd_height;
+
+
+ if (layout_type == SRC_COMMAND)
+ win_info_ptr = &TUI_SRC_WIN;
+ else
+ win_info_ptr = &TUI_DISASM_WIN;
+
+ if ((*win_info_ptr) == NULL)
+ {
+ if (layout_type == SRC_COMMAND)
+ make_source_window (win_info_ptr, src_height - 1, 0);
+ else
+ make_disasm_window (win_info_ptr, src_height - 1, 0);
+ init_and_make_win ((void **) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ src_height - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ init_gen_win_info (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ tui_term_width (),
+ 0,
+ src_height - 1);
+ (*win_info_ptr)->detail.source_info.has_locator = TRUE;
+ init_gen_win_info (
+ &(*win_info_ptr)->generic,
+ (*win_info_ptr)->generic.type,
+ src_height - 1,
+ (*win_info_ptr)->generic.width,
+ (*win_info_ptr)->detail.source_info.execution_info->width,
+ 0);
+ init_gen_win_info ((*win_info_ptr)->detail.source_info.execution_info,
+ EXEC_INFO_WIN,
+ src_height - 1,
+ 3,
+ 0,
+ 0);
+ (*win_info_ptr)->can_highlight = TRUE;
+ tui_make_visible (&(*win_info_ptr)->generic);
+ tui_make_visible ((*win_info_ptr)->detail.source_info.execution_info);
+ }
+ if ((*win_info_ptr) != NULL)
+ {
+ (*win_info_ptr)->detail.source_info.has_locator = TRUE;
+ tui_make_visible (locator);
+ tui_show_locator_content ();
+ tui_show_source_content (*win_info_ptr);
+
+ if (TUI_CMD_WIN == NULL)
+ {
+ make_command_window (&TUI_CMD_WIN, cmd_height, src_height);
+ tui_refresh_win (&TUI_CMD_WIN->generic);
+ }
+ else
+ {
+ init_gen_win_info (&TUI_CMD_WIN->generic,
+ TUI_CMD_WIN->generic.type,
+ TUI_CMD_WIN->generic.height,
+ TUI_CMD_WIN->generic.width,
+ TUI_CMD_WIN->generic.origin.x,
+ TUI_CMD_WIN->generic.origin.y);
+ TUI_CMD_WIN->can_highlight = FALSE;
+ tui_make_visible (&TUI_CMD_WIN->generic);
+ }
+ }
+ tui_set_current_layout_to (layout_type);
+ }
+}
--- /dev/null
+/* TUI layout window management.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_LAYOUT_H
+#define TUI_LAYOUT_H
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+
+extern void tui_add_win_to_layout (enum tui_win_type);
+extern int tui_default_win_height (enum tui_win_type, enum tui_layout_type);
+extern int tui_default_win_viewport_height (enum tui_win_type,
+ enum tui_layout_type);
+extern enum tui_status tui_set_layout (enum tui_layout_type,
+ enum tui_register_display_type);
+
+#endif /*TUI_LAYOUT_H */
--- /dev/null
+/* TUI display registers in window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "regcache.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+#include "tui/tui-layout.h"
+#include "tui/tui-win.h"
+#include "tui/tui-windata.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/*****************************************
+** LOCAL DEFINITIONS **
+******************************************/
+#define DOUBLE_FLOAT_LABEL_WIDTH 6
+#define DOUBLE_FLOAT_LABEL_FMT "%6.6s: "
+#define DOUBLE_FLOAT_VALUE_WIDTH 30 /*min of 16 but may be in sci notation */
+
+#define SINGLE_FLOAT_LABEL_WIDTH 6
+#define SINGLE_FLOAT_LABEL_FMT "%6.6s: "
+#define SINGLE_FLOAT_VALUE_WIDTH 25 /* min of 8 but may be in sci notation */
+
+#define SINGLE_LABEL_WIDTH 16
+#define SINGLE_LABEL_FMT "%10.10s: "
+#define SINGLE_VALUE_WIDTH 20 /* minimum of 8 but may be in sci notation */
+
+/* In the code HP gave Cygnus, this was actually a function call to a
+ PA-specific function, which was supposed to determine whether the
+ target was a 64-bit or 32-bit processor. However, the 64-bit
+ support wasn't complete, so we didn't merge that in, so we leave
+ this here as a stub. */
+#define IS_64BIT 0
+
+/*****************************************
+** STATIC DATA **
+******************************************/
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+static enum tui_status tui_set_regs_content
+ (int, int, struct frame_info *, enum tui_register_display_type, int);
+static const char *tui_register_name (int);
+static enum tui_status tui_get_register_raw_value (int, char *, struct frame_info *);
+static void tui_set_register_element
+ (int, struct frame_info *, struct tui_data_element *, int);
+static void tui_display_register (int, struct tui_gen_win_info *, enum precision_type);
+static void tui_register_format
+ (char *, int, int, struct tui_data_element *, enum precision_type);
+static enum tui_status tui_set_general_regs_content (int);
+static enum tui_status tui_set_special_regs_content (int);
+static enum tui_status tui_set_general_and_special_regs_content (int);
+static enum tui_status tui_set_float_regs_content (enum tui_register_display_type, int);
+static int tui_reg_value_has_changed
+ (struct tui_data_element *, struct frame_info *, char *);
+static void tui_show_float_command (char *, int);
+static void tui_show_general_command (char *, int);
+static void tui_show_special_command (char *, int);
+static void tui_v_show_registers_command_support (enum tui_register_display_type);
+static void _tui_toggle_float_regs_command (char *, int);
+static void tui_scroll_regs_forward_command (char *, int);
+static void tui_scroll_regs_backward_command (char *, int);
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/* Answer the number of the last line in the regs display. If there
+ are no registers (-1) is returned. */
+int
+tui_last_regs_line_no (void)
+{
+ int num_lines = (-1);
+
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+ {
+ num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count);
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count)
+ num_lines++;
+ }
+ return num_lines;
+}
+
+
+/* Answer the line number that the register element at element_no is
+ on. If element_no is greater than the number of register elements
+ there are, -1 is returned. */
+int
+tui_line_from_reg_element_no (int element_no)
+{
+ if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ {
+ int i, line = (-1);
+
+ i = 1;
+ while (line == (-1))
+ {
+ if (element_no <
+ (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
+ line = i - 1;
+ else
+ i++;
+ }
+
+ return line;
+ }
+ else
+ return (-1);
+}
+
+
+/* Answer the index of the first element in line_no. If line_no is past
+ the register area (-1) is returned. */
+int
+tui_first_reg_element_no_inline (int line_no)
+{
+ if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
+ <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ return ((line_no + 1) *
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count;
+ else
+ return (-1);
+}
+
+
+/* Answer the index of the last element in line_no. If line_no is
+ past the register area (-1) is returned. */
+int
+tui_last_reg_element_no_in_line (int line_no)
+{
+ if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ return ((line_no + 1) *
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
+ else
+ return (-1);
+}
+
+
+/* Calculate the number of columns that should be used to display the
+ registers. */
+int
+tui_calculate_regs_column_count (enum tui_register_display_type dpy_type)
+{
+ int col_count, col_width;
+
+ if (IS_64BIT || dpy_type == TUI_DFLOAT_REGS)
+ col_width = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
+ else
+ {
+ if (dpy_type == TUI_SFLOAT_REGS)
+ col_width = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
+ else
+ col_width = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
+ }
+ col_count = (TUI_DATA_WIN->generic.width - 2) / col_width;
+
+ return col_count;
+}
+
+
+/* Show the registers int the data window as indicated by dpy_type. If
+ there is any other registers being displayed, then they are
+ cleared. What registers are displayed is dependent upon dpy_type. */
+void
+tui_show_registers (enum tui_register_display_type dpy_type)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int refresh_values_only = FALSE;
+
+ /* Say that registers should be displayed, even if there is a problem */
+ TUI_DATA_WIN->detail.data_display_info.display_regs = TRUE;
+
+ if (target_has_registers)
+ {
+ refresh_values_only =
+ (dpy_type == TUI_DATA_WIN->detail.data_display_info.regs_display_type);
+ switch (dpy_type)
+ {
+ case TUI_GENERAL_REGS:
+ ret = tui_set_general_regs_content (refresh_values_only);
+ break;
+ case TUI_SFLOAT_REGS:
+ case TUI_DFLOAT_REGS:
+ ret = tui_set_float_regs_content (dpy_type, refresh_values_only);
+ break;
+
+/* could ifdef out */
+
+ case TUI_SPECIAL_REGS:
+ ret = tui_set_special_regs_content (refresh_values_only);
+ break;
+ case TUI_GENERAL_AND_SPECIAL_REGS:
+ ret = tui_set_general_and_special_regs_content (refresh_values_only);
+ break;
+
+/* end of potential if def */
+
+ default:
+ break;
+ }
+ }
+ if (ret == TUI_FAILURE)
+ {
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type = TUI_UNDEFINED_REGS;
+ tui_erase_data_content (NO_REGS_STRING);
+ }
+ else
+ {
+ int i;
+
+ /* Clear all notation of changed values */
+ for (i = 0; (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
+ {
+ struct tui_gen_win_info * data_item_win;
+
+ data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+ regs_content[i]->which_element.data_window;
+ (&((struct tui_win_element *)
+ data_item_win->content[0])->which_element.data)->highlight = FALSE;
+ }
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type = dpy_type;
+ tui_display_all_data ();
+ }
+ (tui_layout_def ())->regs_display_type = dpy_type;
+
+ return;
+}
+
+
+/* Function to display the registers in the content from
+ 'start_element_no' until the end of the register content or the end
+ of the display height. No checking for displaying past the end of
+ the registers is done here. */
+void
+tui_display_registers_from (int start_element_no)
+{
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+ {
+ int i = start_element_no;
+ int j, value_chars_wide, item_win_width, cur_y, label_width;
+ enum precision_type precision;
+
+ precision = (TUI_DATA_WIN->detail.data_display_info.regs_display_type
+ == TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision;
+ if (IS_64BIT ||
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
+ {
+ value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
+ label_width = DOUBLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+ TUI_SFLOAT_REGS)
+ {
+ value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
+ label_width = SINGLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ value_chars_wide = SINGLE_VALUE_WIDTH;
+ label_width = SINGLE_LABEL_WIDTH;
+ }
+ }
+ item_win_width = value_chars_wide + label_width;
+ /*
+ ** Now create each data "sub" window, and write the display into it.
+ */
+ cur_y = 1;
+ while (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count &&
+ cur_y <= TUI_DATA_WIN->generic.viewport_height)
+ {
+ for (j = 0;
+ (j < TUI_DATA_WIN->detail.data_display_info.regs_column_count &&
+ i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); j++)
+ {
+ struct tui_gen_win_info * data_item_win;
+ struct tui_data_element * data_element_ptr;
+
+ /* create the window if necessary */
+ data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+ regs_content[i]->which_element.data_window;
+ data_element_ptr = &((struct tui_win_element *)
+ data_item_win->content[0])->which_element.data;
+ if (data_item_win->handle == (WINDOW *) NULL)
+ {
+ data_item_win->height = 1;
+ data_item_win->width = (precision == double_precision) ?
+ item_win_width + 2 : item_win_width + 1;
+ data_item_win->origin.x = (item_win_width * j) + 1;
+ data_item_win->origin.y = cur_y;
+ tui_make_window (data_item_win, DONT_BOX_WINDOW);
+ scrollok (data_item_win->handle, FALSE);
+ }
+ touchwin (data_item_win->handle);
+
+ /*
+ ** Get the printable representation of the register
+ ** and display it
+ */
+ tui_display_register (
+ data_element_ptr->item_no, data_item_win, precision);
+ i++; /* next register */
+ }
+ cur_y++; /* next row; */
+ }
+ }
+
+ return;
+}
+
+
+/* Function to display the registers in the content from
+ 'start_element_no' on 'start_line_no' until the end of the register
+ content or the end of the display height. This function checks
+ that we won't display off the end of the register display. */
+void
+tui_display_reg_element_at_line (int start_element_no, int start_line_no)
+{
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+ {
+ int element_no = start_element_no;
+
+ if (start_element_no != 0 && start_line_no != 0)
+ {
+ int last_line_no, first_line_on_last_page;
+
+ last_line_no = tui_last_regs_line_no ();
+ first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
+ if (first_line_on_last_page < 0)
+ first_line_on_last_page = 0;
+ /*
+ ** If there is no other data displayed except registers,
+ ** and the element_no causes us to scroll past the end of the
+ ** registers, adjust what element to really start the display at.
+ */
+ if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
+ start_line_no > first_line_on_last_page)
+ element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
+ }
+ tui_display_registers_from (element_no);
+ }
+}
+
+
+
+/* Function to display the registers starting at line line_no in the
+ data window. Answers the line number that the display actually
+ started from. If nothing is displayed (-1) is returned. */
+int
+tui_display_registers_from_line (int line_no, int force_display)
+{
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
+ {
+ int line, element_no;
+
+ if (line_no < 0)
+ line = 0;
+ else if (force_display)
+ { /*
+ ** If we must display regs (force_display is true), then make
+ ** sure that we don't display off the end of the registers.
+ */
+ if (line_no >= tui_last_regs_line_no ())
+ {
+ if ((line = tui_line_from_reg_element_no (
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
+ line = 0;
+ }
+ else
+ line = line_no;
+ }
+ else
+ line = line_no;
+
+ element_no = tui_first_reg_element_no_inline (line);
+ if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ tui_display_reg_element_at_line (element_no, line);
+ else
+ line = (-1);
+
+ return line;
+ }
+
+ return (-1); /* nothing was displayed */
+}
+
+
+/* This function check all displayed registers for changes in values,
+ given a particular frame. If the values have changed, they are
+ updated with the new value and highlighted. */
+void
+tui_check_register_values (struct frame_info *frame)
+{
+ if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+ {
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0 &&
+ TUI_DATA_WIN->detail.data_display_info.display_regs)
+ tui_show_registers ((tui_layout_def ())->regs_display_type);
+ else
+ {
+ int i, j;
+ char raw_buf[MAX_REGISTER_SIZE];
+
+ for (i = 0;
+ (i < TUI_DATA_WIN->detail.data_display_info.regs_content_count); i++)
+ {
+ struct tui_data_element * data_element_ptr;
+ struct tui_gen_win_info * data_item_win_ptr;
+ int was_hilighted;
+
+ data_item_win_ptr = &TUI_DATA_WIN->detail.data_display_info.
+ regs_content[i]->which_element.data_window;
+ data_element_ptr = &((struct tui_win_element *)
+ data_item_win_ptr->content[0])->which_element.data;
+ was_hilighted = data_element_ptr->highlight;
+ data_element_ptr->highlight =
+ tui_reg_value_has_changed (data_element_ptr, frame, &raw_buf[0]);
+ if (data_element_ptr->highlight)
+ {
+ int size;
+
+ size = DEPRECATED_REGISTER_RAW_SIZE (data_element_ptr->item_no);
+ for (j = 0; j < size; j++)
+ ((char *) data_element_ptr->value)[j] = raw_buf[j];
+ tui_display_register (
+ data_element_ptr->item_no,
+ data_item_win_ptr,
+ ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+ TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision));
+ }
+ else if (was_hilighted)
+ {
+ data_element_ptr->highlight = FALSE;
+ tui_display_register (
+ data_element_ptr->item_no,
+ data_item_win_ptr,
+ ((TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+ TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision));
+ }
+ }
+ }
+ }
+ return;
+}
+
+
+/*
+ ** tui_toggle_float_regs().
+ */
+void
+tui_toggle_float_regs (void)
+{
+ struct tui_layout_def * layout_def = tui_layout_def ();
+
+ if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
+ layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
+ else
+ layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
+
+ if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible &&
+ (TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_SFLOAT_REGS ||
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS))
+ tui_show_registers (layout_def->float_regs_display_type);
+
+ return;
+} /* tui_toggle_float_regs */
+
+
+void
+_initialize_tui_regs (void)
+{
+ if (xdb_commands)
+ {
+ add_com ("fr", class_tui, tui_show_float_command,
+ "Display only floating point registers\n");
+ add_com ("gr", class_tui, tui_show_general_command,
+ "Display only general registers\n");
+ add_com ("sr", class_tui, tui_show_special_command,
+ "Display only special registers\n");
+ add_com ("+r", class_tui, tui_scroll_regs_forward_command,
+ "Scroll the registers window forward\n");
+ add_com ("-r", class_tui, tui_scroll_regs_backward_command,
+ "Scroll the register window backward\n");
+ add_com ("tf", class_tui, _tui_toggle_float_regs_command,
+ "Toggle between single and double precision floating point registers.\n");
+ add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
+ class_tui,
+ _tui_toggle_float_regs_command,
+ "Toggle between single and double precision floating point \
+registers.\n",
+ &togglelist);
+ }
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
+
+
+/*
+ ** tui_register_name().
+ ** Return the register name.
+ */
+static const char *
+tui_register_name (int reg_num)
+{
+ return REGISTER_NAME (reg_num);
+}
+extern int pagination_enabled;
+
+static void
+tui_restore_gdbout (void *ui)
+{
+ ui_file_delete (gdb_stdout);
+ gdb_stdout = (struct ui_file*) ui;
+ pagination_enabled = 1;
+}
+
+/*
+ ** tui_register_format
+ ** Function to format the register name and value into a buffer,
+ ** suitable for printing or display
+ */
+static void
+tui_register_format (char *buf, int buf_len, int reg_num,
+ struct tui_data_element * data_element,
+ enum precision_type precision)
+{
+ struct ui_file *stream;
+ struct ui_file *old_stdout;
+ const char *name;
+ struct cleanup *cleanups;
+ char *p;
+ int pos;
+
+ name = REGISTER_NAME (reg_num);
+ if (name == 0)
+ {
+ strcpy (buf, "");
+ return;
+ }
+
+ pagination_enabled = 0;
+ old_stdout = gdb_stdout;
+ stream = tui_sfileopen (buf_len);
+ gdb_stdout = stream;
+ cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
+ gdbarch_print_registers_info (current_gdbarch, stream, deprecated_selected_frame,
+ reg_num, 1);
+
+ /* Save formatted output in the buffer. */
+ p = tui_file_get_strbuf (stream);
+ pos = 0;
+ while (*p && *p == *name++ && buf_len)
+ {
+ *buf++ = *p++;
+ buf_len--;
+ pos++;
+ }
+ while (*p == ' ')
+ p++;
+ while (pos < 8 && buf_len)
+ {
+ *buf++ = ' ';
+ buf_len--;
+ pos++;
+ }
+ strncpy (buf, p, buf_len);
+
+ /* Remove the possible \n. */
+ p = strchr (buf, '\n');
+ if (p)
+ *p = 0;
+
+ do_cleanups (cleanups);
+}
+
+
+#define NUM_GENERAL_REGS 32
+/* Set the content of the data window to consist of the general
+ registers. */
+static enum tui_status
+tui_set_general_regs_content (int refresh_values_only)
+{
+ return (tui_set_regs_content (0,
+ NUM_GENERAL_REGS - 1,
+ deprecated_selected_frame,
+ TUI_GENERAL_REGS,
+ refresh_values_only));
+
+}
+
+
+#ifndef PCOQ_HEAD_REGNUM
+#define START_SPECIAL_REGS 0
+#else
+#define START_SPECIAL_REGS PCOQ_HEAD_REGNUM
+#endif
+
+/* Set the content of the data window to consist of the special
+ registers. */
+static enum tui_status
+tui_set_special_regs_content (int refresh_values_only)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int end_reg_num;
+
+ end_reg_num = FP0_REGNUM - 1;
+ ret = tui_set_regs_content (START_SPECIAL_REGS,
+ end_reg_num,
+ deprecated_selected_frame,
+ TUI_SPECIAL_REGS,
+ refresh_values_only);
+
+ return ret;
+}
+
+
+/* Set the content of the data window to consist of the special
+ registers. */
+static enum tui_status
+tui_set_general_and_special_regs_content (int refresh_values_only)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int end_reg_num = (-1);
+
+ end_reg_num = FP0_REGNUM - 1;
+ ret = tui_set_regs_content (
+ 0, end_reg_num, deprecated_selected_frame, TUI_SPECIAL_REGS, refresh_values_only);
+
+ return ret;
+}
+
+/* Set the content of the data window to consist of the float
+ registers. */
+static enum tui_status
+tui_set_float_regs_content (enum tui_register_display_type dpy_type,
+ int refresh_values_only)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int start_reg_num;
+
+ start_reg_num = FP0_REGNUM;
+ ret = tui_set_regs_content (start_reg_num,
+ NUM_REGS - 1,
+ deprecated_selected_frame,
+ dpy_type,
+ refresh_values_only);
+
+ return ret;
+}
+
+
+/* Answer TRUE if the register's value has changed, FALSE otherwise.
+ If TRUE, new_value is filled in with the new value. */
+static int
+tui_reg_value_has_changed (struct tui_data_element * data_element,
+ struct frame_info *frame, char *new_value)
+{
+ int has_changed = FALSE;
+
+ if (data_element->item_no != UNDEFINED_ITEM &&
+ tui_register_name (data_element->item_no) != (char *) NULL)
+ {
+ char raw_buf[MAX_REGISTER_SIZE];
+ int i;
+
+ if (tui_get_register_raw_value (data_element->item_no, raw_buf, frame) == TUI_SUCCESS)
+ {
+ int size = DEPRECATED_REGISTER_RAW_SIZE (data_element->item_no);
+
+ for (i = 0; (i < size && !has_changed); i++)
+ has_changed = (((char *) data_element->value)[i] != raw_buf[i]);
+ if (has_changed && new_value != (char *) NULL)
+ {
+ for (i = 0; i < size; i++)
+ new_value[i] = raw_buf[i];
+ }
+ }
+ }
+ return has_changed;
+}
+
+
+
+/* Get the register raw value. The raw value is returned in reg_value. */
+static enum tui_status
+tui_get_register_raw_value (int reg_num, char *reg_value, struct frame_info *frame)
+{
+ enum tui_status ret = TUI_FAILURE;
+
+ if (target_has_registers)
+ {
+ get_frame_register (frame, reg_num, reg_value);
+ /* NOTE: cagney/2003-03-13: This is bogus. It is refering to
+ the register cache and not the frame which could have pulled
+ the register value off the stack. */
+ if (register_cached (reg_num) >= 0)
+ ret = TUI_SUCCESS;
+ }
+ return ret;
+}
+
+
+
+/* Function to initialize a data element with the input and the
+ register value. */
+static void
+tui_set_register_element (int reg_num, struct frame_info *frame,
+ struct tui_data_element * data_element,
+ int refresh_value_only)
+{
+ if (data_element != (struct tui_data_element *) NULL)
+ {
+ if (!refresh_value_only)
+ {
+ data_element->item_no = reg_num;
+ data_element->name = tui_register_name (reg_num);
+ data_element->highlight = FALSE;
+ }
+ if (data_element->value == NULL)
+ data_element->value = xmalloc (MAX_REGISTER_SIZE);
+ if (data_element->value != NULL)
+ tui_get_register_raw_value (reg_num, data_element->value, frame);
+ }
+}
+
+
+/* Set the content of the data window to consist of the registers
+ numbered from start_reg_num to end_reg_num. Note that if
+ refresh_values_only is TRUE, start_reg_num and end_reg_num are
+ ignored. */
+static enum tui_status
+tui_set_regs_content (int start_reg_num, int end_reg_num,
+ struct frame_info *frame,
+ enum tui_register_display_type dpy_type,
+ int refresh_values_only)
+{
+ enum tui_status ret = TUI_FAILURE;
+ int num_regs = end_reg_num - start_reg_num + 1;
+ int allocated_here = FALSE;
+
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0 &&
+ !refresh_values_only)
+ {
+ tui_free_data_content (TUI_DATA_WIN->detail.data_display_info.regs_content,
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count);
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count = 0;
+ }
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content_count <= 0)
+ {
+ TUI_DATA_WIN->detail.data_display_info.regs_content =
+ tui_alloc_content (num_regs, DATA_WIN);
+ allocated_here = TRUE;
+ }
+
+ if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL)
+ {
+ int i;
+
+ if (!refresh_values_only || allocated_here)
+ {
+ TUI_DATA_WIN->generic.content = NULL;
+ TUI_DATA_WIN->generic.content_size = 0;
+ tui_add_content_elements (&TUI_DATA_WIN->generic, num_regs);
+ TUI_DATA_WIN->detail.data_display_info.regs_content =
+ (tui_win_content) TUI_DATA_WIN->generic.content;
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count = num_regs;
+ }
+ /*
+ ** Now set the register names and values
+ */
+ for (i = start_reg_num; (i <= end_reg_num); i++)
+ {
+ struct tui_gen_win_info * data_item_win;
+
+ data_item_win = &TUI_DATA_WIN->detail.data_display_info.
+ regs_content[i - start_reg_num]->which_element.data_window;
+ tui_set_register_element (
+ i,
+ frame,
+ &((struct tui_win_element *) data_item_win->content[0])->which_element.data,
+ !allocated_here && refresh_values_only);
+ }
+ TUI_DATA_WIN->detail.data_display_info.regs_column_count =
+ tui_calculate_regs_column_count (dpy_type);
+#ifdef LATER
+ if (TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
+ {
+ /* delete all the windows? */
+ /* realloc content equal to data_content_count + regs_content_count */
+ /* append TUI_DATA_WIN->detail.data_display_info.data_content to content */
+ }
+#endif
+ TUI_DATA_WIN->generic.content_size =
+ TUI_DATA_WIN->detail.data_display_info.regs_content_count +
+ TUI_DATA_WIN->detail.data_display_info.data_content_count;
+ ret = TUI_SUCCESS;
+ }
+
+ return ret;
+}
+
+
+/* Function to display a register in a window. If hilite is TRUE,
+ than the value will be displayed in reverse video. */
+static void
+tui_display_register (int reg_num,
+ struct tui_gen_win_info * win_info, /* the data item window */
+ enum precision_type precision)
+{
+ if (win_info->handle != (WINDOW *) NULL)
+ {
+ int i;
+ char buf[40];
+ int value_chars_wide, label_width;
+ struct tui_data_element * data_element_ptr = &((tui_win_content)
+ win_info->content)[0]->which_element.data;
+
+ if (IS_64BIT ||
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type == TUI_DFLOAT_REGS)
+ {
+ value_chars_wide = DOUBLE_FLOAT_VALUE_WIDTH;
+ label_width = DOUBLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ if (TUI_DATA_WIN->detail.data_display_info.regs_display_type ==
+ TUI_SFLOAT_REGS)
+ {
+ value_chars_wide = SINGLE_FLOAT_VALUE_WIDTH;
+ label_width = SINGLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ value_chars_wide = SINGLE_VALUE_WIDTH;
+ label_width = SINGLE_LABEL_WIDTH;
+ }
+ }
+
+ buf[0] = (char) 0;
+ tui_register_format (buf,
+ value_chars_wide + label_width,
+ reg_num,
+ data_element_ptr,
+ precision);
+
+ if (data_element_ptr->highlight)
+ wstandout (win_info->handle);
+
+ wmove (win_info->handle, 0, 0);
+ for (i = 1; i < win_info->width; i++)
+ waddch (win_info->handle, ' ');
+ wmove (win_info->handle, 0, 0);
+ waddstr (win_info->handle, buf);
+
+ if (data_element_ptr->highlight)
+ wstandend (win_info->handle);
+ tui_refresh_win (win_info);
+ }
+}
+
+
+static void
+tui_v_show_registers_command_support (enum tui_register_display_type dpy_type)
+{
+
+ if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+ { /* Data window already displayed, show the registers */
+ if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != dpy_type)
+ tui_show_registers (dpy_type);
+ }
+ else
+ (tui_layout_def ())->regs_display_type = dpy_type;
+
+ return;
+}
+
+
+static void
+tui_show_float_command (char *arg, int from_tty)
+{
+ if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible ||
+ (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS &&
+ TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS))
+ tui_v_show_registers_command_support ((tui_layout_def ())->float_regs_display_type);
+}
+
+
+static void
+tui_show_general_command (char *arg, int from_tty)
+{
+ tui_v_show_registers_command_support (TUI_GENERAL_REGS);
+}
+
+
+static void
+tui_show_special_command (char *arg, int from_tty)
+{
+ tui_v_show_registers_command_support (TUI_SPECIAL_REGS);
+}
+
+
+static void
+_tui_toggle_float_regs_command (char *arg, int from_tty)
+{
+ if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+ tui_toggle_float_regs ();
+ else
+ {
+ struct tui_layout_def * layout_def = tui_layout_def ();
+
+ if (layout_def->float_regs_display_type == TUI_SFLOAT_REGS)
+ layout_def->float_regs_display_type = TUI_DFLOAT_REGS;
+ else
+ layout_def->float_regs_display_type = TUI_SFLOAT_REGS;
+ }
+}
+
+
+static void
+tui_scroll_regs_forward_command (char *arg, int from_tty)
+{
+ tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
+}
+
+
+static void
+tui_scroll_regs_backward_command (char *arg, int from_tty)
+{
+ tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
+}
--- /dev/null
+/* TUI display registers in window.
+
+ Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+ Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_REGS_H
+#define TUI_REGS_H
+
+#include "tui/tui-data.h" /* For struct tui_register_display_type. */
+
+extern void tui_check_register_values (struct frame_info *);
+extern void tui_show_registers (enum tui_register_display_type);
+extern void tui_display_registers_from (int);
+extern int tui_display_registers_from_line (int, int);
+extern int tui_last_regs_line_no (void);
+extern int tui_first_reg_element_inline (int);
+extern int tui_line_from_reg_element_no (int);
+extern void tui_toggle_float_regs (void);
+extern int tui_calculate_regs_column_count (enum tui_register_display_type);
+extern int tui_first_reg_element_no_inline (int lineno);
+
+#endif
--- /dev/null
+/* TUI display source window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "source.h"
+#include "symtab.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-source.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Function to display source in the source window. */
+enum tui_status
+tui_set_source_content (struct symtab *s, int line_no, int noerror)
+{
+ enum tui_status ret = TUI_FAILURE;
+
+ if (s != (struct symtab *) NULL && s->filename != (char *) NULL)
+ {
+ FILE *stream;
+ int i, desc, c, line_width, nlines;
+ char *src_line = 0;
+
+ if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
+ {
+ line_width = TUI_SRC_WIN->generic.width - 1;
+ /* Take hilite (window border) into account, when calculating
+ the number of lines */
+ nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
+ desc = open_source_file (s);
+ if (desc < 0)
+ {
+ if (!noerror)
+ {
+ char *name = alloca (strlen (s->filename) + 100);
+ sprintf (name, "%s:%d", s->filename, line_no);
+ print_sys_errmsg (name, errno);
+ }
+ ret = TUI_FAILURE;
+ }
+ else
+ {
+ if (s->line_charpos == 0)
+ find_source_lines (s, desc);
+
+ if (line_no < 1 || line_no > s->nlines)
+ {
+ close (desc);
+ printf_unfiltered (
+ "Line number %d out of range; %s has %d lines.\n",
+ line_no, s->filename, s->nlines);
+ }
+ else if (lseek (desc, s->line_charpos[line_no - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (s->filename);
+ }
+ else
+ {
+ int offset, cur_line_no, cur_line, cur_len, threshold;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ struct tui_source_info * src = &TUI_SRC_WIN->detail.source_info;
+
+ if (TUI_SRC_WIN->generic.title)
+ xfree (TUI_SRC_WIN->generic.title);
+ TUI_SRC_WIN->generic.title = xstrdup (s->filename);
+
+ if (src->filename)
+ xfree (src->filename);
+ src->filename = xstrdup (s->filename);
+
+ /* Determine the threshold for the length of the line
+ and the offset to start the display. */
+ offset = src->horizontal_offset;
+ threshold = (line_width - 1) + offset;
+ stream = fdopen (desc, FOPEN_RT);
+ clearerr (stream);
+ cur_line = 0;
+ cur_line_no = src->start_line_or_addr.line_no = line_no;
+ if (offset > 0)
+ src_line = (char *) xmalloc (
+ (threshold + 1) * sizeof (char));
+ while (cur_line < nlines)
+ {
+ struct tui_win_element * element = (struct tui_win_element *)
+ TUI_SRC_WIN->generic.content[cur_line];
+
+ /* get the first character in the line */
+ c = fgetc (stream);
+
+ if (offset == 0)
+ src_line = ((struct tui_win_element *)
+ TUI_SRC_WIN->generic.content[
+ cur_line])->which_element.source.line;
+ /* Init the line with the line number */
+ sprintf (src_line, "%-6d", cur_line_no);
+ cur_len = strlen (src_line);
+ i = cur_len -
+ ((cur_len / tui_default_tab_len ()) * tui_default_tab_len ());
+ while (i < tui_default_tab_len ())
+ {
+ src_line[cur_len] = ' ';
+ i++;
+ cur_len++;
+ }
+ src_line[cur_len] = (char) 0;
+
+ /* Set whether element is the execution point and
+ whether there is a break point on it. */
+ element->which_element.source.line_or_addr.line_no =
+ cur_line_no;
+ element->which_element.source.is_exec_point =
+ (strcmp (((struct tui_win_element *)
+ locator->content[0])->which_element.locator.file_name,
+ s->filename) == 0
+ && cur_line_no == ((struct tui_win_element *)
+ locator->content[0])->which_element.locator.line_no);
+ if (c != EOF)
+ {
+ i = strlen (src_line) - 1;
+ do
+ {
+ if ((c != '\n') &&
+ (c != '\r') && (++i < threshold))
+ {
+ if (c < 040 && c != '\t')
+ {
+ src_line[i++] = '^';
+ src_line[i] = c + 0100;
+ }
+ else if (c == 0177)
+ {
+ src_line[i++] = '^';
+ src_line[i] = '?';
+ }
+ else
+ { /* Store the charcter in the line
+ buffer. If it is a tab, then
+ translate to the correct number of
+ chars so we don't overwrite our
+ buffer. */
+ if (c == '\t')
+ {
+ int j, max_tab_len = tui_default_tab_len ();
+
+ for (j = i - (
+ (i / max_tab_len) * max_tab_len);
+ ((j < max_tab_len) &&
+ i < threshold);
+ i++, j++)
+ src_line[i] = ' ';
+ i--;
+ }
+ else
+ src_line[i] = c;
+ }
+ src_line[i + 1] = 0;
+ }
+ else
+ { /* If we have not reached EOL, then eat
+ chars until we do */
+ while (c != EOF && c != '\n' && c != '\r')
+ c = fgetc (stream);
+ }
+ }
+ while (c != EOF && c != '\n' && c != '\r' &&
+ i < threshold && (c = fgetc (stream)));
+ }
+ /* Now copy the line taking the offset into account */
+ if (strlen (src_line) > offset)
+ strcpy (((struct tui_win_element *) TUI_SRC_WIN->generic.content[
+ cur_line])->which_element.source.line,
+ &src_line[offset]);
+ else
+ ((struct tui_win_element *)
+ TUI_SRC_WIN->generic.content[
+ cur_line])->which_element.source.line[0] = (char) 0;
+ cur_line++;
+ cur_line_no++;
+ }
+ if (offset > 0)
+ xfree (src_line);
+ fclose (stream);
+ TUI_SRC_WIN->generic.content_size = nlines;
+ ret = TUI_SUCCESS;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+
+/* elz: this function sets the contents of the source window to empty
+ except for a line in the middle with a warning message about the
+ source not being available. This function is called by
+ tui_erase_source_contents(), which in turn is invoked when the
+ source files cannot be accessed. */
+
+void
+tui_set_source_content_nil (struct tui_win_info * win_info, char *warning_string)
+{
+ int line_width;
+ int n_lines;
+ int curr_line = 0;
+
+ line_width = win_info->generic.width - 1;
+ n_lines = win_info->generic.height - 2;
+
+ /* set to empty each line in the window, except for the one
+ which contains the message */
+ while (curr_line < win_info->generic.content_size)
+ {
+ /* set the information related to each displayed line
+ to null: i.e. the line number is 0, there is no bp,
+ it is not where the program is stopped */
+
+ struct tui_win_element * element =
+ (struct tui_win_element *) win_info->generic.content[curr_line];
+ element->which_element.source.line_or_addr.line_no = 0;
+ element->which_element.source.is_exec_point = FALSE;
+ element->which_element.source.has_break = FALSE;
+
+ /* set the contents of the line to blank */
+ element->which_element.source.line[0] = (char) 0;
+
+ /* if the current line is in the middle of the screen, then we
+ want to display the 'no source available' message in it.
+ Note: the 'weird' arithmetic with the line width and height
+ comes from the function tui_erase_source_content(). We need
+ to keep the screen and the window's actual contents in synch. */
+
+ if (curr_line == (n_lines / 2 + 1))
+ {
+ int i;
+ int xpos;
+ int warning_length = strlen (warning_string);
+ char *src_line;
+
+ src_line = element->which_element.source.line;
+
+ if (warning_length >= ((line_width - 1) / 2))
+ xpos = 1;
+ else
+ xpos = (line_width - 1) / 2 - warning_length;
+
+ for (i = 0; i < xpos; i++)
+ src_line[i] = ' ';
+
+ sprintf (src_line + i, "%s", warning_string);
+
+ for (i = xpos + warning_length; i < line_width; i++)
+ src_line[i] = ' ';
+
+ src_line[i] = '\n';
+
+ } /* end if */
+
+ curr_line++;
+
+ } /* end while */
+}
+
+
+/* Function to display source in the source window. This function
+ initializes the horizontal scroll to 0. */
+void
+tui_show_symtab_source (struct symtab *s, union tui_line_or_address line, int noerror)
+{
+ TUI_SRC_WIN->detail.source_info.horizontal_offset = 0;
+ tui_update_source_window_as_is (TUI_SRC_WIN, s, line, noerror);
+}
+
+
+/* Answer whether the source is currently displayed in the source
+ window. */
+int
+tui_source_is_displayed (char *fname)
+{
+ return (TUI_SRC_WIN->generic.content_in_use &&
+ (strcmp (((struct tui_win_element *) (tui_locator_win_info_ptr ())->
+ content[0])->which_element.locator.file_name, fname) == 0));
+}
+
+
+/* Scroll the source forward or backward vertically. */
+void
+tui_vertical_source_scroll (enum tui_scroll_direction scroll_direction,
+ int num_to_scroll)
+{
+ if (TUI_SRC_WIN->generic.content != NULL)
+ {
+ union tui_line_or_address l;
+ struct symtab *s;
+ tui_win_content content = (tui_win_content) TUI_SRC_WIN->generic.content;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+ if (cursal.symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+ else
+ s = cursal.symtab;
+
+ if (scroll_direction == FORWARD_SCROLL)
+ {
+ l.line_no = content[0]->which_element.source.line_or_addr.line_no +
+ num_to_scroll;
+ if (l.line_no > s->nlines)
+ /*line = s->nlines - win_info->generic.content_size + 1; */
+ /*elz: fix for dts 23398 */
+ l.line_no = content[0]->which_element.source.line_or_addr.line_no;
+ }
+ else
+ {
+ l.line_no = content[0]->which_element.source.line_or_addr.line_no -
+ num_to_scroll;
+ if (l.line_no <= 0)
+ l.line_no = 1;
+ }
+
+ print_source_lines (s, l.line_no, l.line_no + 1, 0);
+ }
+}
--- /dev/null
+/* TUI display source window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_SOURCE_H
+#define TUI_SOURCE_H
+
+#include "tui/tui-data.h"
+
+struct symtab;
+struct tui_win_info;
+
+extern void tui_set_source_content_nil (struct tui_win_info *, char *);
+
+extern enum tui_status tui_set_source_content (struct symtab *, int, int);
+extern void tui_show_symtab_source (struct symtab *, union tui_line_or_address, int);
+extern int tui_source_is_displayed (char *);
+extern void tui_vertical_source_scroll (enum tui_scroll_direction, int);
+
+#endif
--- /dev/null
+/* TUI display locator.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "command.h"
+#include "inferior.h"
+#include "target.h"
+#include "top.h"
+#include "gdb_string.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-source.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-file.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Get a printable name for the function at the address.
+ The symbol name is demangled if demangling is turned on.
+ Returns a pointer to a static area holding the result. */
+static char* tui_get_function_from_frame (struct frame_info *fi);
+
+/* Set the filename portion of the locator. */
+static void tui_set_locator_filename (const char *filename);
+
+/* Update the locator, with the provided arguments. */
+static void tui_set_locator_info (const char *filename, const char *procname,
+ int lineno, CORE_ADDR addr);
+
+static void tui_update_command (char *, int);
+\f
+
+/* Create the status line to display as much information as we
+ can on this single line: target name, process number, current
+ function, current line, current PC, SingleKey mode. */
+static char*
+tui_make_status_line (struct tui_locator_element* loc)
+{
+ char* string;
+ char line_buf[50], *pname;
+ char* buf;
+ int status_size;
+ int i, proc_width;
+ const char* pid_name;
+ const char* pc_buf;
+ int target_width;
+ int pid_width;
+ int line_width;
+ int pc_width;
+ struct ui_file *pc_out;
+
+ if (ptid_equal (inferior_ptid, null_ptid))
+ pid_name = "No process";
+ else
+ pid_name = target_pid_to_str (inferior_ptid);
+
+ target_width = strlen (target_shortname);
+ if (target_width > MAX_TARGET_WIDTH)
+ target_width = MAX_TARGET_WIDTH;
+
+ pid_width = strlen (pid_name);
+ if (pid_width > MAX_PID_WIDTH)
+ pid_width = MAX_PID_WIDTH;
+
+ status_size = tui_term_width ();
+ string = (char *) xmalloc (status_size + 1);
+ buf = (char*) alloca (status_size + 1);
+
+ /* Translate line number and obtain its size. */
+ if (loc->line_no > 0)
+ sprintf (line_buf, "%d", loc->line_no);
+ else
+ strcpy (line_buf, "??");
+ line_width = strlen (line_buf);
+ if (line_width < MIN_LINE_WIDTH)
+ line_width = MIN_LINE_WIDTH;
+
+ /* Translate PC address. */
+ pc_out = tui_sfileopen (128);
+ print_address_numeric (loc->addr, 1, pc_out);
+ pc_buf = tui_file_get_strbuf (pc_out);
+ pc_width = strlen (pc_buf);
+
+ /* First determine the amount of proc name width we have available.
+ The +1 are for a space separator between fields.
+ The -1 are to take into account the \0 counted by sizeof. */
+ proc_width = (status_size
+ - (target_width + 1)
+ - (pid_width + 1)
+ - (sizeof (PROC_PREFIX) - 1 + 1)
+ - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
+ - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
+ - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
+ ? (sizeof (SINGLE_KEY) - 1 + 1)
+ : 0));
+
+ /* If there is no room to print the function name, try by removing
+ some fields. */
+ if (proc_width < MIN_PROC_WIDTH)
+ {
+ proc_width += target_width + 1;
+ target_width = 0;
+ if (proc_width < MIN_PROC_WIDTH)
+ {
+ proc_width += pid_width + 1;
+ pid_width = 0;
+ if (proc_width <= MIN_PROC_WIDTH)
+ {
+ proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
+ pc_width = 0;
+ if (proc_width < 0)
+ {
+ proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
+ line_width = 0;
+ if (proc_width < 0)
+ proc_width = 0;
+ }
+ }
+ }
+ }
+
+ /* Now convert elements to string form */
+ pname = loc->proc_name;
+
+ /* Now create the locator line from the string version
+ of the elements. We could use sprintf() here but
+ that wouldn't ensure that we don't overrun the size
+ of the allocated buffer. strcat_to_buf() will. */
+ *string = (char) 0;
+
+ if (target_width > 0)
+ {
+ sprintf (buf, "%*.*s ",
+ -target_width, target_width, target_shortname);
+ strcat_to_buf (string, status_size, buf);
+ }
+ if (pid_width > 0)
+ {
+ sprintf (buf, "%*.*s ",
+ -pid_width, pid_width, pid_name);
+ strcat_to_buf (string, status_size, buf);
+ }
+
+ /* Show whether we are in SingleKey mode. */
+ if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
+ {
+ strcat_to_buf (string, status_size, SINGLE_KEY);
+ strcat_to_buf (string, status_size, " ");
+ }
+
+ /* procedure/class name */
+ if (proc_width > 0)
+ {
+ if (strlen (pname) > proc_width)
+ sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
+ 1 - proc_width, proc_width - 1, pname);
+ else
+ sprintf (buf, "%s%*.*s ", PROC_PREFIX,
+ -proc_width, proc_width, pname);
+ strcat_to_buf (string, status_size, buf);
+ }
+
+ if (line_width > 0)
+ {
+ sprintf (buf, "%s%*.*s ", LINE_PREFIX,
+ -line_width, line_width, line_buf);
+ strcat_to_buf (string, status_size, buf);
+ }
+ if (pc_width > 0)
+ {
+ strcat_to_buf (string, status_size, PC_PREFIX);
+ strcat_to_buf (string, status_size, pc_buf);
+ }
+
+
+ for (i = strlen (string); i < status_size; i++)
+ string[i] = ' ';
+ string[status_size] = (char) 0;
+
+ ui_file_delete (pc_out);
+ return string;
+}
+
+/* Get a printable name for the function at the address.
+ The symbol name is demangled if demangling is turned on.
+ Returns a pointer to a static area holding the result. */
+static char*
+tui_get_function_from_frame (struct frame_info *fi)
+{
+ static char name[256];
+ struct ui_file *stream = tui_sfileopen (256);
+ char *p;
+
+ print_address_symbolic (get_frame_pc (fi), stream, demangle, "");
+ p = tui_file_get_strbuf (stream);
+
+ /* Use simple heuristics to isolate the function name. The symbol can
+ be demangled and we can have function parameters. Remove them because
+ the status line is too short to display them. */
+ if (*p == '<')
+ p++;
+ strncpy (name, p, sizeof (name));
+ p = strchr (name, '(');
+ if (!p)
+ p = strchr (name, '>');
+ if (p)
+ *p = 0;
+ p = strchr (name, '+');
+ if (p)
+ *p = 0;
+ ui_file_delete (stream);
+ return name;
+}
+
+void
+tui_show_locator_content (void)
+{
+ char *string;
+ struct tui_gen_win_info * locator;
+
+ locator = tui_locator_win_info_ptr ();
+
+ if (locator != NULL && locator->handle != (WINDOW *) NULL)
+ {
+ struct tui_win_element * element;
+
+ element = (struct tui_win_element *) locator->content[0];
+
+ string = tui_make_status_line (&element->which_element.locator);
+ wmove (locator->handle, 0, 0);
+ wstandout (locator->handle);
+ waddstr (locator->handle, string);
+ wclrtoeol (locator->handle);
+ wstandend (locator->handle);
+ tui_refresh_win (locator);
+ wmove (locator->handle, 0, 0);
+ xfree (string);
+ locator->content_in_use = TRUE;
+ }
+}
+
+
+/* Set the filename portion of the locator. */
+static void
+tui_set_locator_filename (const char *filename)
+{
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ struct tui_locator_element * element;
+
+ if (locator->content[0] == NULL)
+ {
+ tui_set_locator_info (filename, NULL, 0, 0);
+ return;
+ }
+
+ element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+ element->file_name[0] = 0;
+ strcat_to_buf (element->file_name, MAX_LOCATOR_ELEMENT_LEN, filename);
+}
+
+/* Update the locator, with the provided arguments. */
+static void
+tui_set_locator_info (const char *filename, const char *procname, int lineno,
+ CORE_ADDR addr)
+{
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ struct tui_locator_element * element;
+
+ /* Allocate the locator content if necessary. */
+ if (locator->content_size <= 0)
+ {
+ locator->content = (void **) tui_alloc_content (1, locator->type);
+ locator->content_size = 1;
+ }
+
+ element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
+ element->proc_name[0] = (char) 0;
+ strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
+ element->line_no = lineno;
+ element->addr = addr;
+ tui_set_locator_filename (filename);
+}
+
+/* Update only the filename portion of the locator. */
+void
+tui_update_locator_filename (const char *filename)
+{
+ tui_set_locator_filename (filename);
+ tui_show_locator_content ();
+}
+
+/* Function to print the frame information for the TUI. */
+void
+tui_show_frame_info (struct frame_info *fi)
+{
+ struct tui_win_info * win_info;
+ int i;
+
+ if (fi)
+ {
+ int start_line, i;
+ CORE_ADDR low;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ int source_already_displayed;
+ struct symtab_and_line sal;
+
+ find_frame_sal (fi, &sal);
+
+ source_already_displayed = sal.symtab != 0
+ && tui_source_is_displayed (sal.symtab->filename);
+ tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename,
+ tui_get_function_from_frame (fi),
+ sal.line,
+ get_frame_pc (fi));
+ tui_show_locator_content ();
+ start_line = 0;
+ for (i = 0; i < (tui_source_windows ())->count; i++)
+ {
+ union tui_which_element *item;
+ win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+ item = &((struct tui_win_element *) locator->content[0])->which_element;
+ if (win_info == TUI_SRC_WIN)
+ {
+ start_line = (item->locator.line_no -
+ (win_info->generic.viewport_height / 2)) + 1;
+ if (start_line <= 0)
+ start_line = 1;
+ }
+ else
+ {
+ if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL,
+ &low, (CORE_ADDR) NULL) == 0)
+ error ("No function contains program counter for selected frame.\n");
+ else
+ low = tui_get_low_disassembly_address (low, get_frame_pc (fi));
+ }
+
+ if (win_info == TUI_SRC_WIN)
+ {
+ union tui_line_or_address l;
+ l.line_no = start_line;
+ if (!(source_already_displayed
+ && tui_line_is_displayed (item->locator.line_no, win_info, TRUE)))
+ tui_update_source_window (win_info, sal.symtab, l, TRUE);
+ else
+ {
+ l.line_no = item->locator.line_no;
+ tui_set_is_exec_point_at (l, win_info);
+ }
+ }
+ else
+ {
+ if (win_info == TUI_DISASM_WIN)
+ {
+ union tui_line_or_address a;
+ a.addr = low;
+ if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE))
+ tui_update_source_window (win_info, sal.symtab, a, TRUE);
+ else
+ {
+ a.addr = item->locator.addr;
+ tui_set_is_exec_point_at (a, win_info);
+ }
+ }
+ }
+ tui_update_exec_info (win_info);
+ }
+ }
+ else
+ {
+ tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0);
+ tui_show_locator_content ();
+ for (i = 0; i < (tui_source_windows ())->count; i++)
+ {
+ win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+ tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+ tui_update_exec_info (win_info);
+ }
+ }
+}
+
+/* Function to initialize gdb commands, for tui window stack
+ manipulation. */
+void
+_initialize_tui_stack (void)
+{
+ add_com ("update", class_tui, tui_update_command,
+ "Update the source window and locator to display the current "
+ "execution point.\n");
+}
+
+/* Command to update the display with the current execution point. */
+static void
+tui_update_command (char *arg, int from_tty)
+{
+ char cmd[sizeof("frame 0")];
+
+ strcpy (cmd, "frame 0");
+ execute_command (cmd, from_tty);
+}
--- /dev/null
+/* TUI display locator.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_STACK_H
+#define TUI_STACK_H
+
+struct frame_info;
+
+extern void tui_update_locator_filename (const char *);
+extern void tui_show_locator_content (void);
+extern void tui_show_frame_info (struct frame_info *);
+
+#endif
--- /dev/null
+/* TUI window generic functions.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* This module contains procedures for handling tui window functions
+ like resize, scrolling, scrolling, changing focus, etc.
+
+ Author: Susan B. Macchia */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+#include "cli/cli-cmds.h"
+#include "top.h"
+#include "source.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-regs.h"
+#include "tui/tui-disasm.h"
+#include "tui/tui-source.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-windata.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+#include "gdb_string.h"
+#include <ctype.h>
+#include <readline/readline.h>
+
+/*******************************
+** Static Local Decls
+********************************/
+static void make_visible_with_new_height (struct tui_win_info *);
+static void make_invisible_and_set_new_height (struct tui_win_info *, int);
+static enum tui_status tui_adjust_win_heights (struct tui_win_info *, int);
+static int new_height_ok (struct tui_win_info *, int);
+static void tui_set_tab_width_command (char *, int);
+static void tui_refresh_all_command (char *, int);
+static void tui_set_win_height_command (char *, int);
+static void tui_xdb_set_win_height_command (char *, int);
+static void tui_all_windows_info (char *, int);
+static void tui_set_focus_command (char *, int);
+static void tui_scroll_forward_command (char *, int);
+static void tui_scroll_backward_command (char *, int);
+static void tui_scroll_left_command (char *, int);
+static void tui_scroll_right_command (char *, int);
+static void parse_scrolling_args (char *, struct tui_win_info * *, int *);
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+#define WIN_HEIGHT_USAGE "Usage: winheight <win_name> [+ | -] <#lines>\n"
+#define XDBWIN_HEIGHT_USAGE "Usage: w <#lines>\n"
+#define FOCUS_USAGE "Usage: focus {<win> | next | prev}\n"
+
+/***************************************
+** PUBLIC FUNCTIONS
+***************************************/
+
+#ifndef ACS_LRCORNER
+# define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+# define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_ULCORNER
+# define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+# define ACS_URCORNER '+'
+#endif
+#ifndef ACS_HLINE
+# define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+# define ACS_VLINE '|'
+#endif
+
+/* Possible values for tui-border-kind variable. */
+static const char *tui_border_kind_enums[] = {
+ "space",
+ "ascii",
+ "acs",
+ NULL
+};
+
+/* Possible values for tui-border-mode and tui-active-border-mode. */
+static const char *tui_border_mode_enums[] = {
+ "normal",
+ "standout",
+ "reverse",
+ "half",
+ "half-standout",
+ "bold",
+ "bold-standout",
+ NULL
+};
+
+struct tui_translate
+{
+ const char *name;
+ int value;
+};
+
+/* Translation table for border-mode variables.
+ The list of values must be terminated by a NULL.
+ After the NULL value, an entry defines the default. */
+struct tui_translate tui_border_mode_translate[] = {
+ { "normal", A_NORMAL },
+ { "standout", A_STANDOUT },
+ { "reverse", A_REVERSE },
+ { "half", A_DIM },
+ { "half-standout", A_DIM | A_STANDOUT },
+ { "bold", A_BOLD },
+ { "bold-standout", A_BOLD | A_STANDOUT },
+ { 0, 0 },
+ { "normal", A_NORMAL }
+};
+
+/* Translation tables for border-kind, one for each border
+ character (see wborder, border curses operations).
+ -1 is used to indicate the ACS because ACS characters
+ are determined at run time by curses (depends on terminal). */
+struct tui_translate tui_border_kind_translate_vline[] = {
+ { "space", ' ' },
+ { "ascii", '|' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '|' }
+};
+
+struct tui_translate tui_border_kind_translate_hline[] = {
+ { "space", ' ' },
+ { "ascii", '-' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '-' }
+};
+
+struct tui_translate tui_border_kind_translate_ulcorner[] = {
+ { "space", ' ' },
+ { "ascii", '+' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '+' }
+};
+
+struct tui_translate tui_border_kind_translate_urcorner[] = {
+ { "space", ' ' },
+ { "ascii", '+' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '+' }
+};
+
+struct tui_translate tui_border_kind_translate_llcorner[] = {
+ { "space", ' ' },
+ { "ascii", '+' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '+' }
+};
+
+struct tui_translate tui_border_kind_translate_lrcorner[] = {
+ { "space", ' ' },
+ { "ascii", '+' },
+ { "acs", -1 },
+ { 0, 0 },
+ { "ascii", '+' }
+};
+
+
+/* Tui configuration variables controlled with set/show command. */
+const char *tui_active_border_mode = "bold-standout";
+const char *tui_border_mode = "normal";
+const char *tui_border_kind = "acs";
+
+/* Tui internal configuration variables. These variables are
+ updated by tui_update_variables to reflect the tui configuration
+ variables. */
+chtype tui_border_vline;
+chtype tui_border_hline;
+chtype tui_border_ulcorner;
+chtype tui_border_urcorner;
+chtype tui_border_llcorner;
+chtype tui_border_lrcorner;
+
+int tui_border_attrs;
+int tui_active_border_attrs;
+
+/* Identify the item in the translation table.
+ When the item is not recognized, use the default entry. */
+static struct tui_translate *
+translate (const char *name, struct tui_translate *table)
+{
+ while (table->name)
+ {
+ if (name && strcmp (table->name, name) == 0)
+ return table;
+ table++;
+ }
+
+ /* Not found, return default entry. */
+ table++;
+ return table;
+}
+
+/* Update the tui internal configuration according to gdb settings.
+ Returns 1 if the configuration has changed and the screen should
+ be redrawn. */
+int
+tui_update_variables (void)
+{
+ int need_redraw = 0;
+ struct tui_translate *entry;
+
+ entry = translate (tui_border_mode, tui_border_mode_translate);
+ if (tui_border_attrs != entry->value)
+ {
+ tui_border_attrs = entry->value;
+ need_redraw = 1;
+ }
+ entry = translate (tui_active_border_mode, tui_border_mode_translate);
+ if (tui_active_border_attrs != entry->value)
+ {
+ tui_active_border_attrs = entry->value;
+ need_redraw = 1;
+ }
+
+ /* If one corner changes, all characters are changed.
+ Only check the first one. The ACS characters are determined at
+ run time by curses terminal management. */
+ entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner);
+ if (tui_border_lrcorner != (chtype) entry->value)
+ {
+ tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value;
+ need_redraw = 1;
+ }
+ entry = translate (tui_border_kind, tui_border_kind_translate_llcorner);
+ tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value;
+
+ entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner);
+ tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value;
+
+ entry = translate (tui_border_kind, tui_border_kind_translate_urcorner);
+ tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value;
+
+ entry = translate (tui_border_kind, tui_border_kind_translate_hline);
+ tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value;
+
+ entry = translate (tui_border_kind, tui_border_kind_translate_vline);
+ tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value;
+
+ return need_redraw;
+}
+
+static void
+set_tui_cmd (char *args, int from_tty)
+{
+}
+
+static void
+show_tui_cmd (char *args, int from_tty)
+{
+}
+
+/* Function to initialize gdb commands, for tui window manipulation. */
+void
+_initialize_tui_win (void)
+{
+ struct cmd_list_element *c;
+ static struct cmd_list_element *tui_setlist;
+ static struct cmd_list_element *tui_showlist;
+
+ /* Define the classes of commands.
+ They will appear in the help list in the reverse of this order. */
+ add_cmd ("tui", class_tui, NULL,
+ "Text User Interface commands.",
+ &cmdlist);
+
+ add_prefix_cmd ("tui", class_tui, set_tui_cmd,
+ "TUI configuration variables",
+ &tui_setlist, "set tui ",
+ 0/*allow-unknown*/, &setlist);
+ add_prefix_cmd ("tui", class_tui, show_tui_cmd,
+ "TUI configuration variables",
+ &tui_showlist, "show tui ",
+ 0/*allow-unknown*/, &showlist);
+
+ add_com ("refresh", class_tui, tui_refresh_all_command,
+ "Refresh the terminal display.\n");
+ if (xdb_commands)
+ add_com_alias ("U", "refresh", class_tui, 0);
+ add_com ("tabset", class_tui, tui_set_tab_width_command,
+ "Set the width (in characters) of tab stops.\n\
+Usage: tabset <n>\n");
+ add_com ("winheight", class_tui, tui_set_win_height_command,
+ "Set the height of a specified window.\n\
+Usage: winheight <win_name> [+ | -] <#lines>\n\
+Window names are:\n\
+src : the source window\n\
+cmd : the command window\n\
+asm : the disassembly window\n\
+regs : the register display\n");
+ add_com_alias ("wh", "winheight", class_tui, 0);
+ add_info ("win", tui_all_windows_info,
+ "List of all displayed windows.\n");
+ add_com ("focus", class_tui, tui_set_focus_command,
+ "Set focus to named window or next/prev window.\n\
+Usage: focus {<win> | next | prev}\n\
+Valid Window names are:\n\
+src : the source window\n\
+asm : the disassembly window\n\
+regs : the register display\n\
+cmd : the command window\n");
+ add_com_alias ("fs", "focus", class_tui, 0);
+ add_com ("+", class_tui, tui_scroll_forward_command,
+ "Scroll window forward.\nUsage: + [win] [n]\n");
+ add_com ("-", class_tui, tui_scroll_backward_command,
+ "Scroll window backward.\nUsage: - [win] [n]\n");
+ add_com ("<", class_tui, tui_scroll_left_command,
+ "Scroll window forward.\nUsage: < [win] [n]\n");
+ add_com (">", class_tui, tui_scroll_right_command,
+ "Scroll window backward.\nUsage: > [win] [n]\n");
+ if (xdb_commands)
+ add_com ("w", class_xdb, tui_xdb_set_win_height_command,
+ "XDB compatibility command for setting the height of a command window.\n\
+Usage: w <#lines>\n");
+
+ /* Define the tui control variables. */
+ c = add_set_enum_cmd
+ ("border-kind", no_class,
+ tui_border_kind_enums, &tui_border_kind,
+ "Set the kind of border for TUI windows.\n"
+ "This variable controls the border of TUI windows:\n"
+ "space use a white space\n"
+ "ascii use ascii characters + - | for the border\n"
+ "acs use the Alternate Character Set\n",
+ &tui_setlist);
+ add_show_from_set (c, &tui_showlist);
+
+ c = add_set_enum_cmd
+ ("border-mode", no_class,
+ tui_border_mode_enums, &tui_border_mode,
+ "Set the attribute mode to use for the TUI window borders.\n"
+ "This variable controls the attributes to use for the window borders:\n"
+ "normal normal display\n"
+ "standout use highlight mode of terminal\n"
+ "reverse use reverse video mode\n"
+ "half use half bright\n"
+ "half-standout use half bright and standout mode\n"
+ "bold use extra bright or bold\n"
+ "bold-standout use extra bright or bold with standout mode\n",
+ &tui_setlist);
+ add_show_from_set (c, &tui_showlist);
+
+ c = add_set_enum_cmd
+ ("active-border-mode", no_class,
+ tui_border_mode_enums, &tui_active_border_mode,
+ "Set the attribute mode to use for the active TUI window border.\n"
+ "This variable controls the attributes to use for the active window border:\n"
+ "normal normal display\n"
+ "standout use highlight mode of terminal\n"
+ "reverse use reverse video mode\n"
+ "half use half bright\n"
+ "half-standout use half bright and standout mode\n"
+ "bold use extra bright or bold\n"
+ "bold-standout use extra bright or bold with standout mode\n",
+ &tui_setlist);
+ add_show_from_set (c, &tui_showlist);
+}
+
+/* Update gdb's knowledge of the terminal size. */
+void
+tui_update_gdb_sizes (void)
+{
+ char cmd[50];
+ int screenheight, screenwidth;
+
+ rl_get_screen_size (&screenheight, &screenwidth);
+ /* Set to TUI command window dimension or use readline values. */
+ sprintf (cmd, "set width %d",
+ tui_active ? TUI_CMD_WIN->generic.width : screenwidth);
+ execute_command (cmd, 0);
+ sprintf (cmd, "set height %d",
+ tui_active ? TUI_CMD_WIN->generic.height : screenheight);
+ execute_command (cmd, 0);
+}
+
+
+/* Set the logical focus to win_info. */
+void
+tui_set_win_focus_to (struct tui_win_info * win_info)
+{
+ if (win_info != NULL)
+ {
+ struct tui_win_info * win_with_focus = tui_win_with_focus ();
+
+ if (win_with_focus != NULL
+ && win_with_focus->generic.type != CMD_WIN)
+ tui_unhighlight_win (win_with_focus);
+ tui_set_win_with_focus (win_info);
+ if (win_info->generic.type != CMD_WIN)
+ tui_highlight_win (win_info);
+ }
+}
+
+
+void
+tui_scroll_forward (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+ if (win_to_scroll != TUI_CMD_WIN)
+ {
+ int _num_to_scroll = num_to_scroll;
+
+ if (num_to_scroll == 0)
+ _num_to_scroll = win_to_scroll->generic.height - 3;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If win_to_scroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (win_to_scroll == TUI_SRC_WIN)
+ tui_vertical_source_scroll (FORWARD_SCROLL, _num_to_scroll);
+ else if (win_to_scroll == TUI_DISASM_WIN)
+ tui_vertical_disassem_scroll (FORWARD_SCROLL, _num_to_scroll);
+ else if (win_to_scroll == TUI_DATA_WIN)
+ tui_vertical_data_scroll (FORWARD_SCROLL, _num_to_scroll);
+ }
+}
+
+void
+tui_scroll_backward (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+ if (win_to_scroll != TUI_CMD_WIN)
+ {
+ int _num_to_scroll = num_to_scroll;
+
+ if (num_to_scroll == 0)
+ _num_to_scroll = win_to_scroll->generic.height - 3;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If win_to_scroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (win_to_scroll == TUI_SRC_WIN)
+ tui_vertical_source_scroll (BACKWARD_SCROLL, _num_to_scroll);
+ else if (win_to_scroll == TUI_DISASM_WIN)
+ tui_vertical_disassem_scroll (BACKWARD_SCROLL, _num_to_scroll);
+ else if (win_to_scroll == TUI_DATA_WIN)
+ tui_vertical_data_scroll (BACKWARD_SCROLL, _num_to_scroll);
+ }
+}
+
+
+void
+tui_scroll_left (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+ if (win_to_scroll != TUI_CMD_WIN)
+ {
+ int _num_to_scroll = num_to_scroll;
+
+ if (_num_to_scroll == 0)
+ _num_to_scroll = 1;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If win_to_scroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN)
+ tui_horizontal_source_scroll (win_to_scroll, LEFT_SCROLL, _num_to_scroll);
+ }
+}
+
+
+void
+tui_scroll_right (struct tui_win_info * win_to_scroll, int num_to_scroll)
+{
+ if (win_to_scroll != TUI_CMD_WIN)
+ {
+ int _num_to_scroll = num_to_scroll;
+
+ if (_num_to_scroll == 0)
+ _num_to_scroll = 1;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If win_to_scroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (win_to_scroll == TUI_SRC_WIN || win_to_scroll == TUI_DISASM_WIN)
+ tui_horizontal_source_scroll (win_to_scroll, RIGHT_SCROLL, _num_to_scroll);
+ }
+}
+
+
+/* Scroll a window. Arguments are passed through a va_list. */
+void
+tui_scroll (enum tui_scroll_direction direction,
+ struct tui_win_info * win_to_scroll,
+ int num_to_scroll)
+{
+ switch (direction)
+ {
+ case FORWARD_SCROLL:
+ tui_scroll_forward (win_to_scroll, num_to_scroll);
+ break;
+ case BACKWARD_SCROLL:
+ tui_scroll_backward (win_to_scroll, num_to_scroll);
+ break;
+ case LEFT_SCROLL:
+ tui_scroll_left (win_to_scroll, num_to_scroll);
+ break;
+ case RIGHT_SCROLL:
+ tui_scroll_right (win_to_scroll, num_to_scroll);
+ break;
+ default:
+ break;
+ }
+}
+
+
+void
+tui_refresh_all_win (void)
+{
+ enum tui_win_type type;
+
+ clearok (curscr, TRUE);
+ tui_refresh_all (tui_win_list);
+ for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
+ {
+ if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+ {
+ switch (type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ tui_show_source_content (tui_win_list[type]);
+ tui_check_and_display_highlight_if_needed (tui_win_list[type]);
+ tui_erase_exec_info_content (tui_win_list[type]);
+ tui_update_exec_info (tui_win_list[type]);
+ break;
+ case DATA_WIN:
+ tui_refresh_data_win ();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ tui_show_locator_content ();
+}
+
+
+/* Resize all the windows based on the the terminal size. This
+ function gets called from within the readline sinwinch handler. */
+void
+tui_resize_all (void)
+{
+ int height_diff, width_diff;
+ int screenheight, screenwidth;
+
+ rl_get_screen_size (&screenheight, &screenwidth);
+ width_diff = screenwidth - tui_term_width ();
+ height_diff = screenheight - tui_term_height ();
+ if (height_diff || width_diff)
+ {
+ enum tui_layout_type cur_layout = tui_current_layout ();
+ struct tui_win_info * win_with_focus = tui_win_with_focus ();
+ struct tui_win_info *first_win;
+ struct tui_win_info *second_win;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ enum tui_win_type win_type;
+ int new_height, split_diff, cmd_split_diff, num_wins_displayed = 2;
+
+ /* turn keypad off while we resize */
+ if (win_with_focus != TUI_CMD_WIN)
+ keypad (TUI_CMD_WIN->generic.handle, FALSE);
+ tui_update_gdb_sizes ();
+ tui_set_term_height_to (screenheight);
+ tui_set_term_width_to (screenwidth);
+ if (cur_layout == SRC_DISASSEM_COMMAND ||
+ cur_layout == SRC_DATA_COMMAND || cur_layout == DISASSEM_DATA_COMMAND)
+ num_wins_displayed++;
+ split_diff = height_diff / num_wins_displayed;
+ cmd_split_diff = split_diff;
+ if (height_diff % num_wins_displayed)
+ {
+ if (height_diff < 0)
+ cmd_split_diff--;
+ else
+ cmd_split_diff++;
+ }
+ /* now adjust each window */
+ clear ();
+ refresh ();
+ switch (cur_layout)
+ {
+ case SRC_COMMAND:
+ case DISASSEM_COMMAND:
+ first_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ first_win->generic.width += width_diff;
+ locator->width += width_diff;
+ /* check for invalid heights */
+ if (height_diff == 0)
+ new_height = first_win->generic.height;
+ else if ((first_win->generic.height + split_diff) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+ else if ((first_win->generic.height + split_diff) <= 0)
+ new_height = MIN_WIN_HEIGHT;
+ else
+ new_height = first_win->generic.height + split_diff;
+
+ make_invisible_and_set_new_height (first_win, new_height);
+ TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+ TUI_CMD_WIN->generic.width += width_diff;
+ new_height = screenheight - TUI_CMD_WIN->generic.origin.y;
+ make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
+ make_visible_with_new_height (first_win);
+ make_visible_with_new_height (TUI_CMD_WIN);
+ if (first_win->generic.content_size <= 0)
+ tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+ break;
+ default:
+ if (cur_layout == SRC_DISASSEM_COMMAND)
+ {
+ first_win = TUI_SRC_WIN;
+ first_win->generic.width += width_diff;
+ second_win = TUI_DISASM_WIN;
+ second_win->generic.width += width_diff;
+ }
+ else
+ {
+ first_win = TUI_DATA_WIN;
+ first_win->generic.width += width_diff;
+ second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ second_win->generic.width += width_diff;
+ }
+ /* Change the first window's height/width */
+ /* check for invalid heights */
+ if (height_diff == 0)
+ new_height = first_win->generic.height;
+ else if ((first_win->generic.height +
+ second_win->generic.height + (split_diff * 2)) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ new_height = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
+ else if ((first_win->generic.height + split_diff) <= 0)
+ new_height = MIN_WIN_HEIGHT;
+ else
+ new_height = first_win->generic.height + split_diff;
+ make_invisible_and_set_new_height (first_win, new_height);
+
+ if (first_win == TUI_DATA_WIN && width_diff != 0)
+ first_win->detail.data_display_info.regs_column_count =
+ tui_calculate_regs_column_count (
+ first_win->detail.data_display_info.regs_display_type);
+ locator->width += width_diff;
+
+ /* Change the second window's height/width */
+ /* check for invalid heights */
+ if (height_diff == 0)
+ new_height = second_win->generic.height;
+ else if ((first_win->generic.height +
+ second_win->generic.height + (split_diff * 2)) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ {
+ new_height = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+ if (new_height % 2)
+ new_height = (new_height / 2) + 1;
+ else
+ new_height /= 2;
+ }
+ else if ((second_win->generic.height + split_diff) <= 0)
+ new_height = MIN_WIN_HEIGHT;
+ else
+ new_height = second_win->generic.height + split_diff;
+ second_win->generic.origin.y = first_win->generic.height - 1;
+ make_invisible_and_set_new_height (second_win, new_height);
+
+ /* Change the command window's height/width */
+ TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+ make_invisible_and_set_new_height (
+ TUI_CMD_WIN, TUI_CMD_WIN->generic.height + cmd_split_diff);
+ make_visible_with_new_height (first_win);
+ make_visible_with_new_height (second_win);
+ make_visible_with_new_height (TUI_CMD_WIN);
+ if (first_win->generic.content_size <= 0)
+ tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+ if (second_win->generic.content_size <= 0)
+ tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
+ break;
+ }
+ /*
+ ** Now remove all invisible windows, and their content so that they get
+ ** created again when called for with the new size
+ */
+ for (win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
+ {
+ if (win_type != CMD_WIN && (tui_win_list[win_type] != NULL)
+ && !tui_win_list[win_type]->generic.is_visible)
+ {
+ tui_free_window (tui_win_list[win_type]);
+ tui_win_list[win_type] = (struct tui_win_info *) NULL;
+ }
+ }
+ tui_set_win_resized_to (TRUE);
+ /* turn keypad back on, unless focus is in the command window */
+ if (win_with_focus != TUI_CMD_WIN)
+ keypad (TUI_CMD_WIN->generic.handle, TRUE);
+ }
+}
+
+
+/* SIGWINCH signal handler for the tui. This signal handler is always
+ called, even when the readline package clears signals because it is
+ set as the old_sigwinch() (TUI only). */
+void
+tui_sigwinch_handler (int signal)
+{
+ /*
+ ** Say that a resize was done so that the readline can do it
+ ** later when appropriate.
+ */
+ tui_set_win_resized_to (TRUE);
+}
+
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+static void
+tui_scroll_forward_command (char *arg, int from_tty)
+{
+ int num_to_scroll = 1;
+ struct tui_win_info * win_to_scroll;
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (arg == (char *) NULL)
+ parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
+ else
+ parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+ tui_scroll (FORWARD_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_backward_command (char *arg, int from_tty)
+{
+ int num_to_scroll = 1;
+ struct tui_win_info * win_to_scroll;
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (arg == (char *) NULL)
+ parse_scrolling_args (arg, &win_to_scroll, (int *) NULL);
+ else
+ parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+ tui_scroll (BACKWARD_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_left_command (char *arg, int from_tty)
+{
+ int num_to_scroll;
+ struct tui_win_info * win_to_scroll;
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+ tui_scroll (LEFT_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+static void
+tui_scroll_right_command (char *arg, int from_tty)
+{
+ int num_to_scroll;
+ struct tui_win_info * win_to_scroll;
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ parse_scrolling_args (arg, &win_to_scroll, &num_to_scroll);
+ tui_scroll (RIGHT_SCROLL, win_to_scroll, num_to_scroll);
+}
+
+
+/* Set focus to the window named by 'arg'. */
+static void
+tui_set_focus (char *arg, int from_tty)
+{
+ if (arg != (char *) NULL)
+ {
+ char *buf_ptr = (char *) xstrdup (arg);
+ int i;
+ struct tui_win_info * win_info = (struct tui_win_info *) NULL;
+
+ for (i = 0; (i < strlen (buf_ptr)); i++)
+ buf_ptr[i] = toupper (arg[i]);
+
+ if (subset_compare (buf_ptr, "NEXT"))
+ win_info = tui_next_win (tui_win_with_focus ());
+ else if (subset_compare (buf_ptr, "PREV"))
+ win_info = tui_prev_win (tui_win_with_focus ());
+ else
+ win_info = tui_partial_win_by_name (buf_ptr);
+
+ if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else
+ {
+ tui_set_win_focus_to (win_info);
+ keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
+ }
+
+ if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
+ tui_refresh_data_win ();
+ xfree (buf_ptr);
+ printf_filtered ("Focus set to %s window.\n",
+ tui_win_name ((struct tui_gen_win_info *) tui_win_with_focus ()));
+ }
+ else
+ warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE);
+}
+
+static void
+tui_set_focus_command (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ tui_set_focus (arg, from_tty);
+}
+
+
+static void
+tui_all_windows_info (char *arg, int from_tty)
+{
+ enum tui_win_type type;
+ struct tui_win_info * win_with_focus = tui_win_with_focus ();
+
+ for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+ if (tui_win_list[type] && tui_win_list[type]->generic.is_visible)
+ {
+ if (win_with_focus == tui_win_list[type])
+ printf_filtered (" %s\t(%d lines) <has focus>\n",
+ tui_win_name (&tui_win_list[type]->generic),
+ tui_win_list[type]->generic.height);
+ else
+ printf_filtered (" %s\t(%d lines)\n",
+ tui_win_name (&tui_win_list[type]->generic),
+ tui_win_list[type]->generic.height);
+ }
+}
+
+
+static void
+tui_refresh_all_command (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+
+ tui_refresh_all_win ();
+}
+
+
+/* Set the height of the specified window. */
+static void
+tui_set_tab_width_command (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (arg != (char *) NULL)
+ {
+ int ts;
+
+ ts = atoi (arg);
+ if (ts > 0)
+ tui_set_default_tab_len (ts);
+ else
+ warning ("Tab widths greater than 0 must be specified.\n");
+ }
+}
+
+
+/* Set the height of the specified window. */
+static void
+tui_set_win_height (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (arg != (char *) NULL)
+ {
+ char *buf = xstrdup (arg);
+ char *buf_ptr = buf;
+ char *wname = (char *) NULL;
+ int new_height, i;
+ struct tui_win_info * win_info;
+
+ wname = buf_ptr;
+ buf_ptr = strchr (buf_ptr, ' ');
+ if (buf_ptr != (char *) NULL)
+ {
+ *buf_ptr = (char) 0;
+
+ /*
+ ** Validate the window name
+ */
+ for (i = 0; i < strlen (wname); i++)
+ wname[i] = toupper (wname[i]);
+ win_info = tui_partial_win_by_name (wname);
+
+ if (win_info == (struct tui_win_info *) NULL || !win_info->generic.is_visible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else
+ {
+ /* Process the size */
+ while (*(++buf_ptr) == ' ')
+ ;
+
+ if (*buf_ptr != (char) 0)
+ {
+ int negate = FALSE;
+ int fixed_size = TRUE;
+ int input_no;;
+
+ if (*buf_ptr == '+' || *buf_ptr == '-')
+ {
+ if (*buf_ptr == '-')
+ negate = TRUE;
+ fixed_size = FALSE;
+ buf_ptr++;
+ }
+ input_no = atoi (buf_ptr);
+ if (input_no > 0)
+ {
+ if (negate)
+ input_no *= (-1);
+ if (fixed_size)
+ new_height = input_no;
+ else
+ new_height = win_info->generic.height + input_no;
+ /*
+ ** Now change the window's height, and adjust all
+ ** other windows around it
+ */
+ if (tui_adjust_win_heights (win_info,
+ new_height) == TUI_FAILURE)
+ warning ("Invalid window height specified.\n%s",
+ WIN_HEIGHT_USAGE);
+ else
+ tui_update_gdb_sizes ();
+ }
+ else
+ warning ("Invalid window height specified.\n%s",
+ WIN_HEIGHT_USAGE);
+ }
+ }
+ }
+ else
+ printf_filtered (WIN_HEIGHT_USAGE);
+
+ if (buf != (char *) NULL)
+ xfree (buf);
+ }
+ else
+ printf_filtered (WIN_HEIGHT_USAGE);
+}
+
+/* Set the height of the specified window, with va_list. */
+static void
+tui_set_win_height_command (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ tui_set_win_height (arg, from_tty);
+}
+
+
+/* XDB Compatibility command for setting the window height. This will
+ increase or decrease the command window by the specified amount. */
+static void
+tui_xdb_set_win_height (char *arg, int from_tty)
+{
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+ if (arg != (char *) NULL)
+ {
+ int input_no = atoi (arg);
+
+ if (input_no > 0)
+ { /* Add 1 for the locator */
+ int new_height = tui_term_height () - (input_no + 1);
+
+ if (!new_height_ok (tui_win_list[CMD_WIN], new_height) ||
+ tui_adjust_win_heights (tui_win_list[CMD_WIN],
+ new_height) == TUI_FAILURE)
+ warning ("Invalid window height specified.\n%s",
+ XDBWIN_HEIGHT_USAGE);
+ }
+ else
+ warning ("Invalid window height specified.\n%s",
+ XDBWIN_HEIGHT_USAGE);
+ }
+ else
+ warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE);
+}
+
+/* Set the height of the specified window, with va_list. */
+static void
+tui_xdb_set_win_height_command (char *arg, int from_tty)
+{
+ tui_xdb_set_win_height (arg, from_tty);
+}
+
+
+/* Function to adjust all window heights around the primary. */
+static enum tui_status
+tui_adjust_win_heights (struct tui_win_info * primary_win_info, int new_height)
+{
+ enum tui_status status = TUI_FAILURE;
+
+ if (new_height_ok (primary_win_info, new_height))
+ {
+ status = TUI_SUCCESS;
+ if (new_height != primary_win_info->generic.height)
+ {
+ int diff;
+ struct tui_win_info * win_info;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+ enum tui_layout_type cur_layout = tui_current_layout ();
+
+ diff = (new_height - primary_win_info->generic.height) * (-1);
+ if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
+ {
+ struct tui_win_info * src_win_info;
+
+ make_invisible_and_set_new_height (primary_win_info, new_height);
+ if (primary_win_info->generic.type == CMD_WIN)
+ {
+ win_info = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ src_win_info = win_info;
+ }
+ else
+ {
+ win_info = tui_win_list[CMD_WIN];
+ src_win_info = primary_win_info;
+ }
+ make_invisible_and_set_new_height (win_info,
+ win_info->generic.height + diff);
+ TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+ make_visible_with_new_height (win_info);
+ make_visible_with_new_height (primary_win_info);
+ if (src_win_info->generic.content_size <= 0)
+ tui_erase_source_content (src_win_info, EMPTY_SOURCE_PROMPT);
+ }
+ else
+ {
+ struct tui_win_info *first_win;
+ struct tui_win_info *second_win;
+
+ if (cur_layout == SRC_DISASSEM_COMMAND)
+ {
+ first_win = TUI_SRC_WIN;
+ second_win = TUI_DISASM_WIN;
+ }
+ else
+ {
+ first_win = TUI_DATA_WIN;
+ second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ }
+ if (primary_win_info == TUI_CMD_WIN)
+ { /*
+ ** Split the change in height accross the 1st & 2nd windows
+ ** adjusting them as well.
+ */
+ int first_split_diff = diff / 2; /* subtract the locator */
+ int second_split_diff = first_split_diff;
+
+ if (diff % 2)
+ {
+ if (first_win->generic.height >
+ second_win->generic.height)
+ if (diff < 0)
+ first_split_diff--;
+ else
+ first_split_diff++;
+ else
+ {
+ if (diff < 0)
+ second_split_diff--;
+ else
+ second_split_diff++;
+ }
+ }
+ /* make sure that the minimum hieghts are honored */
+ while ((first_win->generic.height + first_split_diff) < 3)
+ {
+ first_split_diff++;
+ second_split_diff--;
+ }
+ while ((second_win->generic.height + second_split_diff) < 3)
+ {
+ second_split_diff++;
+ first_split_diff--;
+ }
+ make_invisible_and_set_new_height (
+ first_win,
+ first_win->generic.height + first_split_diff);
+ second_win->generic.origin.y = first_win->generic.height - 1;
+ make_invisible_and_set_new_height (
+ second_win, second_win->generic.height + second_split_diff);
+ TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+ make_invisible_and_set_new_height (TUI_CMD_WIN, new_height);
+ }
+ else
+ {
+ if ((TUI_CMD_WIN->generic.height + diff) < 1)
+ { /*
+ ** If there is no way to increase the command window
+ ** take real estate from the 1st or 2nd window.
+ */
+ if ((TUI_CMD_WIN->generic.height + diff) < 1)
+ {
+ int i;
+ for (i = TUI_CMD_WIN->generic.height + diff;
+ (i < 1); i++)
+ if (primary_win_info == first_win)
+ second_win->generic.height--;
+ else
+ first_win->generic.height--;
+ }
+ }
+ if (primary_win_info == first_win)
+ make_invisible_and_set_new_height (first_win, new_height);
+ else
+ make_invisible_and_set_new_height (
+ first_win,
+ first_win->generic.height);
+ second_win->generic.origin.y = first_win->generic.height - 1;
+ if (primary_win_info == second_win)
+ make_invisible_and_set_new_height (second_win, new_height);
+ else
+ make_invisible_and_set_new_height (
+ second_win, second_win->generic.height);
+ TUI_CMD_WIN->generic.origin.y = locator->origin.y + 1;
+ if ((TUI_CMD_WIN->generic.height + diff) < 1)
+ make_invisible_and_set_new_height (TUI_CMD_WIN, 1);
+ else
+ make_invisible_and_set_new_height (
+ TUI_CMD_WIN, TUI_CMD_WIN->generic.height + diff);
+ }
+ make_visible_with_new_height (TUI_CMD_WIN);
+ make_visible_with_new_height (second_win);
+ make_visible_with_new_height (first_win);
+ if (first_win->generic.content_size <= 0)
+ tui_erase_source_content (first_win, EMPTY_SOURCE_PROMPT);
+ if (second_win->generic.content_size <= 0)
+ tui_erase_source_content (second_win, EMPTY_SOURCE_PROMPT);
+ }
+ }
+ }
+
+ return status;
+}
+
+
+/* Function make the target window (and auxillary windows associated
+ with the targer) invisible, and set the new height and location. */
+static void
+make_invisible_and_set_new_height (struct tui_win_info * win_info, int height)
+{
+ int i;
+ struct tui_gen_win_info * gen_win_info;
+
+ tui_make_invisible (&win_info->generic);
+ win_info->generic.height = height;
+ if (height > 1)
+ win_info->generic.viewport_height = height - 1;
+ else
+ win_info->generic.viewport_height = height;
+ if (win_info != TUI_CMD_WIN)
+ win_info->generic.viewport_height--;
+
+ /* Now deal with the auxillary windows associated with win_info */
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ gen_win_info = win_info->detail.source_info.execution_info;
+ tui_make_invisible (gen_win_info);
+ gen_win_info->height = height;
+ gen_win_info->origin.y = win_info->generic.origin.y;
+ if (height > 1)
+ gen_win_info->viewport_height = height - 1;
+ else
+ gen_win_info->viewport_height = height;
+ if (win_info != TUI_CMD_WIN)
+ gen_win_info->viewport_height--;
+
+ if (tui_win_has_locator (win_info))
+ {
+ gen_win_info = tui_locator_win_info_ptr ();
+ tui_make_invisible (gen_win_info);
+ gen_win_info->origin.y = win_info->generic.origin.y + height;
+ }
+ break;
+ case DATA_WIN:
+ /* delete all data item windows */
+ for (i = 0; i < win_info->generic.content_size; i++)
+ {
+ gen_win_info = (struct tui_gen_win_info *) & ((struct tui_win_element *)
+ win_info->generic.content[i])->which_element.data_window;
+ tui_delete_win (gen_win_info->handle);
+ gen_win_info->handle = (WINDOW *) NULL;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+/* Function to make the windows with new heights visible. This means
+ re-creating the windows' content since the window had to be
+ destroyed to be made invisible. */
+static void
+make_visible_with_new_height (struct tui_win_info * win_info)
+{
+ struct symtab *s;
+
+ tui_make_visible (&win_info->generic);
+ tui_check_and_display_highlight_if_needed (win_info);
+ switch (win_info->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ tui_free_win_content (win_info->detail.source_info.execution_info);
+ tui_make_visible (win_info->detail.source_info.execution_info);
+ if (win_info->generic.content != NULL)
+ {
+ union tui_line_or_address line_or_addr;
+ struct symtab_and_line cursal
+ = get_current_source_symtab_and_line ();
+
+ if (win_info->generic.type == SRC_WIN)
+ line_or_addr.line_no =
+ win_info->detail.source_info.start_line_or_addr.line_no;
+ else
+ line_or_addr.addr =
+ win_info->detail.source_info.start_line_or_addr.addr;
+ tui_free_win_content (&win_info->generic);
+ tui_update_source_window (win_info, cursal.symtab, line_or_addr, TRUE);
+ }
+ else if (deprecated_selected_frame != (struct frame_info *) NULL)
+ {
+ union tui_line_or_address line;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+
+ s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+ if (win_info->generic.type == SRC_WIN)
+ line.line_no = cursal.line;
+ else
+ {
+ find_line_pc (s, cursal.line, &line.addr);
+ }
+ tui_update_source_window (win_info, s, line, TRUE);
+ }
+ if (tui_win_has_locator (win_info))
+ {
+ tui_make_visible (tui_locator_win_info_ptr ());
+ tui_show_locator_content ();
+ }
+ break;
+ case DATA_WIN:
+ tui_display_all_data ();
+ break;
+ case CMD_WIN:
+ win_info->detail.command_info.cur_line = 0;
+ win_info->detail.command_info.curch = 0;
+ wmove (win_info->generic.handle,
+ win_info->detail.command_info.cur_line,
+ win_info->detail.command_info.curch);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static int
+new_height_ok (struct tui_win_info * primary_win_info, int new_height)
+{
+ int ok = (new_height < tui_term_height ());
+
+ if (ok)
+ {
+ int diff;
+ enum tui_layout_type cur_layout = tui_current_layout ();
+
+ diff = (new_height - primary_win_info->generic.height) * (-1);
+ if (cur_layout == SRC_COMMAND || cur_layout == DISASSEM_COMMAND)
+ {
+ ok = ((primary_win_info->generic.type == CMD_WIN &&
+ new_height <= (tui_term_height () - 4) &&
+ new_height >= MIN_CMD_WIN_HEIGHT) ||
+ (primary_win_info->generic.type != CMD_WIN &&
+ new_height <= (tui_term_height () - 2) &&
+ new_height >= MIN_WIN_HEIGHT));
+ if (ok)
+ { /* check the total height */
+ struct tui_win_info * win_info;
+
+ if (primary_win_info == TUI_CMD_WIN)
+ win_info = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ else
+ win_info = TUI_CMD_WIN;
+ ok = ((new_height +
+ (win_info->generic.height + diff)) <= tui_term_height ());
+ }
+ }
+ else
+ {
+ int cur_total_height, total_height, min_height = 0;
+ struct tui_win_info *first_win;
+ struct tui_win_info *second_win;
+
+ if (cur_layout == SRC_DISASSEM_COMMAND)
+ {
+ first_win = TUI_SRC_WIN;
+ second_win = TUI_DISASM_WIN;
+ }
+ else
+ {
+ first_win = TUI_DATA_WIN;
+ second_win = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ }
+ /*
+ ** We could simply add all the heights to obtain the same result
+ ** but below is more explicit since we subtract 1 for the
+ ** line that the first and second windows share, and add one
+ ** for the locator.
+ */
+ total_height = cur_total_height =
+ (first_win->generic.height + second_win->generic.height - 1)
+ + TUI_CMD_WIN->generic.height + 1 /*locator */ ;
+ if (primary_win_info == TUI_CMD_WIN)
+ {
+ /* locator included since first & second win share a line */
+ ok = ((first_win->generic.height +
+ second_win->generic.height + diff) >=
+ (MIN_WIN_HEIGHT * 2) &&
+ new_height >= MIN_CMD_WIN_HEIGHT);
+ if (ok)
+ {
+ total_height = new_height + (first_win->generic.height +
+ second_win->generic.height + diff);
+ min_height = MIN_CMD_WIN_HEIGHT;
+ }
+ }
+ else
+ {
+ min_height = MIN_WIN_HEIGHT;
+ /*
+ ** First see if we can increase/decrease the command
+ ** window. And make sure that the command window is
+ ** at least 1 line
+ */
+ ok = ((TUI_CMD_WIN->generic.height + diff) > 0);
+ if (!ok)
+ { /*
+ ** Looks like we have to increase/decrease one of
+ ** the other windows
+ */
+ if (primary_win_info == first_win)
+ ok = (second_win->generic.height + diff) >= min_height;
+ else
+ ok = (first_win->generic.height + diff) >= min_height;
+ }
+ if (ok)
+ {
+ if (primary_win_info == first_win)
+ total_height = new_height +
+ second_win->generic.height +
+ TUI_CMD_WIN->generic.height + diff;
+ else
+ total_height = new_height +
+ first_win->generic.height +
+ TUI_CMD_WIN->generic.height + diff;
+ }
+ }
+ /*
+ ** Now make sure that the proposed total height doesn't exceed
+ ** the old total height.
+ */
+ if (ok)
+ ok = (new_height >= min_height && total_height <= cur_total_height);
+ }
+ }
+
+ return ok;
+}
+
+
+static void
+parse_scrolling_args (char *arg, struct tui_win_info * * win_to_scroll,
+ int *num_to_scroll)
+{
+ if (num_to_scroll)
+ *num_to_scroll = 0;
+ *win_to_scroll = tui_win_with_focus ();
+
+ /*
+ ** First set up the default window to scroll, in case there is no
+ ** window name arg
+ */
+ if (arg != (char *) NULL)
+ {
+ char *buf, *buf_ptr;
+
+ /* process the number of lines to scroll */
+ buf = buf_ptr = xstrdup (arg);
+ if (isdigit (*buf_ptr))
+ {
+ char *num_str;
+
+ num_str = buf_ptr;
+ buf_ptr = strchr (buf_ptr, ' ');
+ if (buf_ptr != (char *) NULL)
+ {
+ *buf_ptr = (char) 0;
+ if (num_to_scroll)
+ *num_to_scroll = atoi (num_str);
+ buf_ptr++;
+ }
+ else if (num_to_scroll)
+ *num_to_scroll = atoi (num_str);
+ }
+
+ /* process the window name if one is specified */
+ if (buf_ptr != (char *) NULL)
+ {
+ char *wname;
+ int i;
+
+ if (*buf_ptr == ' ')
+ while (*(++buf_ptr) == ' ')
+ ;
+
+ if (*buf_ptr != (char) 0)
+ wname = buf_ptr;
+ else
+ wname = "?";
+
+ /* Validate the window name */
+ for (i = 0; i < strlen (wname); i++)
+ wname[i] = toupper (wname[i]);
+ *win_to_scroll = tui_partial_win_by_name (wname);
+
+ if (*win_to_scroll == (struct tui_win_info *) NULL ||
+ !(*win_to_scroll)->generic.is_visible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else if (*win_to_scroll == TUI_CMD_WIN)
+ *win_to_scroll = (struct tui_win_info *) (tui_source_windows ())->list[0];
+ }
+ xfree (buf);
+ }
+}
--- /dev/null
+/* TUI window generic functions.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_WIN_H
+#define TUI_WIN_H
+
+#include "tui/tui-data.h"
+
+struct tui_win_info;
+
+extern void tui_scroll_forward (struct tui_win_info *, int);
+extern void tui_scroll_backward (struct tui_win_info *, int);
+extern void tui_scroll_left (struct tui_win_info *, int);
+extern void tui_scroll_right (struct tui_win_info *, int);
+extern void tui_scroll (enum tui_scroll_direction, struct tui_win_info *, int);
+extern void tui_set_win_focus_to (struct tui_win_info *);
+extern void tui_resize_all (void);
+extern void tui_refresh_all_win (void);
+extern void tui_sigwinch_handler (int);
+
+extern chtype tui_border_ulcorner;
+extern chtype tui_border_urcorner;
+extern chtype tui_border_lrcorner;
+extern chtype tui_border_llcorner;
+extern chtype tui_border_vline;
+extern chtype tui_border_hline;
+extern int tui_border_attrs;
+extern int tui_active_border_attrs;
+
+extern int tui_update_variables (void);
+
+/* Update gdb's knowledge of the terminal size. */
+extern void tui_update_gdb_sizes (void);
+
+#endif
--- /dev/null
+/* Data/register window display.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-regs.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+
+/* Answer the index first element displayed. If none are displayed,
+ then return (-1). */
+int
+tui_first_data_item_displayed (void)
+{
+ int element_no = (-1);
+ int i;
+
+ for (i = 0; (i < TUI_DATA_WIN->generic.content_size && element_no < 0); i++)
+ {
+ struct tui_gen_win_info * data_item_win;
+
+ data_item_win = &((tui_win_content)
+ TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
+ if (data_item_win->handle != (WINDOW *) NULL && data_item_win->is_visible)
+ element_no = i;
+ }
+
+ return element_no;
+}
+
+
+/* Answer the index of the first element in line_no. If line_no is
+ past the data area (-1) is returned. */
+int
+tui_first_data_element_no_in_line (int line_no)
+{
+ int first_element_no = (-1);
+
+ /*
+ ** First see if there is a register on line_no, and if so, set the
+ ** first element number
+ */
+ if ((first_element_no = tui_first_reg_element_no_inline (line_no)) == -1)
+ { /*
+ ** Looking at the general data, the 1st element on line_no
+ */
+ }
+
+ return first_element_no;
+}
+
+
+/* Function to delete all the item windows in the data window. This
+ is usually done when the data window is scrolled. */
+void
+tui_delete_data_content_windows (void)
+{
+ int i;
+ struct tui_gen_win_info * data_item_win_ptr;
+
+ for (i = 0; (i < TUI_DATA_WIN->generic.content_size); i++)
+ {
+ data_item_win_ptr = &((tui_win_content)
+ TUI_DATA_WIN->generic.content)[i]->which_element.data_window;
+ tui_delete_win (data_item_win_ptr->handle);
+ data_item_win_ptr->handle = (WINDOW *) NULL;
+ data_item_win_ptr->is_visible = FALSE;
+ }
+}
+
+
+void
+tui_erase_data_content (char *prompt)
+{
+ werase (TUI_DATA_WIN->generic.handle);
+ tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+ if (prompt != (char *) NULL)
+ {
+ int half_width = (TUI_DATA_WIN->generic.width - 2) / 2;
+ int x_pos;
+
+ if (strlen (prompt) >= half_width)
+ x_pos = 1;
+ else
+ x_pos = half_width - strlen (prompt);
+ mvwaddstr (TUI_DATA_WIN->generic.handle,
+ (TUI_DATA_WIN->generic.height / 2),
+ x_pos,
+ prompt);
+ }
+ wrefresh (TUI_DATA_WIN->generic.handle);
+}
+
+
+/* This function displays the data that is in the data window's
+ content. It does not set the content. */
+void
+tui_display_all_data (void)
+{
+ if (TUI_DATA_WIN->generic.content_size <= 0)
+ tui_erase_data_content (NO_DATA_STRING);
+ else
+ {
+ tui_erase_data_content ((char *) NULL);
+ tui_delete_data_content_windows ();
+ tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+ tui_display_registers_from (0);
+ /*
+ ** Then display the other data
+ */
+ if (TUI_DATA_WIN->detail.data_display_info.data_content !=
+ (tui_win_content) NULL &&
+ TUI_DATA_WIN->detail.data_display_info.data_content_count > 0)
+ {
+ }
+ }
+}
+
+
+/* Function to display the data starting at line, line_no, in the data
+ window. */
+void
+tui_display_data_from_line (int line_no)
+{
+ int _line_no = line_no;
+
+ if (line_no < 0)
+ _line_no = 0;
+
+ tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
+
+ /* there is no general data, force regs to display (if there are any) */
+ if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0)
+ tui_display_registers_from_line (_line_no, TRUE);
+ else
+ {
+ int element_no, start_line_no;
+ int regs_last_line = tui_last_regs_line_no ();
+
+
+ /* display regs if we can */
+ if (tui_display_registers_from_line (_line_no, FALSE) < 0)
+ { /*
+ ** _line_no is past the regs display, so calc where the
+ ** start data element is
+ */
+ if (regs_last_line < _line_no)
+ { /* figure out how many lines each element is to obtain
+ the start element_no */
+ }
+ }
+ else
+ { /*
+ ** calculate the starting element of the data display, given
+ ** regs_last_line and how many lines each element is, up to
+ ** _line_no
+ */
+ }
+ /* Now display the data , starting at element_no */
+ }
+}
+
+
+/* Display data starting at element element_no. */
+void
+tui_display_data_from (int element_no, int reuse_windows)
+{
+ int first_line = (-1);
+
+ if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ first_line = tui_line_from_reg_element_no (element_no);
+ else
+ { /* calculate the first_line from the element number */
+ }
+
+ if (first_line >= 0)
+ {
+ tui_erase_data_content ((char *) NULL);
+ if (!reuse_windows)
+ tui_delete_data_content_windows ();
+ tui_display_data_from_line (first_line);
+ }
+}
+
+
+/* Function to redisplay the contents of the data window. */
+void
+tui_refresh_data_win (void)
+{
+ tui_erase_data_content ((char *) NULL);
+ if (TUI_DATA_WIN->generic.content_size > 0)
+ {
+ int first_element = tui_first_data_item_displayed ();
+
+ if (first_element >= 0) /* re-use existing windows */
+ tui_display_data_from (first_element, TRUE);
+ }
+}
+
+
+/* Function to check the data values and hilite any that have changed. */
+void
+tui_check_data_values (struct frame_info *frame)
+{
+ tui_check_register_values (frame);
+
+ /* Now check any other data values that there are */
+ if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
+ {
+ int i;
+
+ for (i = 0; TUI_DATA_WIN->detail.data_display_info.data_content_count; i++)
+ {
+#ifdef LATER
+ tui_data_element_ptr data_element_ptr;
+ struct tui_gen_win_info * data_item_win_ptr;
+ Opaque new_value;
+
+ data_item_ptr = &TUI_DATA_WIN->detail.data_display_info.
+ data_content[i]->which_element.data_window;
+ data_element_ptr = &((tui_win_content)
+ data_item_win_ptr->content)[0]->which_element.data;
+ if value
+ has changed (data_element_ptr, frame, &new_value)
+ {
+ data_element_ptr->value = new_value;
+ update the display with the new value, hiliting it.
+ }
+#endif
+ }
+ }
+}
+
+
+/* Scroll the data window vertically forward or backward. */
+void
+tui_vertical_data_scroll (enum tui_scroll_direction scroll_direction, int num_to_scroll)
+{
+ int first_element_no;
+ int first_line = (-1);
+
+ first_element_no = tui_first_data_item_displayed ();
+ if (first_element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
+ first_line = tui_line_from_reg_element_no (first_element_no);
+ else
+ { /* calculate the first line from the element number which is in
+ ** the general data content
+ */
+ }
+
+ if (first_line >= 0)
+ {
+ int last_element_no, last_line;
+
+ if (scroll_direction == FORWARD_SCROLL)
+ first_line += num_to_scroll;
+ else
+ first_line -= num_to_scroll;
+ tui_erase_data_content ((char *) NULL);
+ tui_delete_data_content_windows ();
+ tui_display_data_from_line (first_line);
+ }
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
--- /dev/null
+/* Data/register window display.
+
+ Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation,
+ Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_WINDATA_H
+#define TUI_WINDATA_H
+
+#include "tui/tui-data.h"
+
+extern void tui_erase_data_content (char *);
+extern void tui_display_all_data (void);
+extern void tui_check_data_values (struct frame_info *);
+extern void tui_display_data_from_line (int);
+extern int tui_first_data_item_displayed (void);
+extern int tui_first_data_element_no_in_line (int);
+extern void tui_delete_data_content_windows (void);
+extern void tui_refresh_data_win (void);
+extern void tui_display_data_from (int, int);
+extern void tui_vertical_data_scroll (enum tui_scroll_direction, int);
+
+#endif
--- /dev/null
+/* General window behavior.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
+ Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-win.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/***********************
+** PUBLIC FUNCTIONS
+***********************/
+
+/* Refresh the window. */
+void
+tui_refresh_win (struct tui_gen_win_info * win_info)
+{
+ if (win_info->type == DATA_WIN && win_info->content_size > 0)
+ {
+ int i;
+
+ for (i = 0; (i < win_info->content_size); i++)
+ {
+ struct tui_gen_win_info * data_item_win_ptr;
+
+ data_item_win_ptr = &((tui_win_content)
+ win_info->content)[i]->which_element.data_window;
+ if (data_item_win_ptr != NULL
+ && data_item_win_ptr->handle != (WINDOW *) NULL)
+ wrefresh (data_item_win_ptr->handle);
+ }
+ }
+ else if (win_info->type == CMD_WIN)
+ {
+ /* Do nothing */
+ }
+ else
+ {
+ if (win_info->handle != (WINDOW *) NULL)
+ wrefresh (win_info->handle);
+ }
+
+ return;
+}
+
+
+/* Function to delete the curses window, checking for NULL. */
+void
+tui_delete_win (WINDOW * window)
+{
+ if (window != (WINDOW *) NULL)
+ delwin (window);
+
+ return;
+}
+
+
+/* Draw a border arround the window. */
+void
+box_win (struct tui_gen_win_info * win_info, int highlight_flag)
+{
+ if (win_info && win_info->handle)
+ {
+ WINDOW *win;
+ int attrs;
+
+ win = win_info->handle;
+ if (highlight_flag == HILITE)
+ attrs = tui_active_border_attrs;
+ else
+ attrs = tui_border_attrs;
+
+ wattron (win, attrs);
+ wborder (win, tui_border_vline, tui_border_vline,
+ tui_border_hline, tui_border_hline,
+ tui_border_ulcorner, tui_border_urcorner,
+ tui_border_llcorner, tui_border_lrcorner);
+ if (win_info->title)
+ mvwaddstr (win, 0, 3, win_info->title);
+ wattroff (win, attrs);
+ }
+}
+
+
+void
+tui_unhighlight_win (struct tui_win_info * win_info)
+{
+ if (win_info != NULL && win_info->generic.handle != (WINDOW *) NULL)
+ {
+ box_win ((struct tui_gen_win_info *) win_info, NO_HILITE);
+ wrefresh (win_info->generic.handle);
+ tui_set_win_highlight (win_info, 0);
+ }
+}
+
+
+void
+tui_highlight_win (struct tui_win_info * win_info)
+{
+ if (win_info != NULL
+ && win_info->can_highlight
+ && win_info->generic.handle != (WINDOW *) NULL)
+ {
+ box_win ((struct tui_gen_win_info *) win_info, HILITE);
+ wrefresh (win_info->generic.handle);
+ tui_set_win_highlight (win_info, 1);
+ }
+}
+
+void
+tui_check_and_display_highlight_if_needed (struct tui_win_info * win_info)
+{
+ if (win_info != NULL && win_info->generic.type != CMD_WIN)
+ {
+ if (win_info->is_highlighted)
+ tui_highlight_win (win_info);
+ else
+ tui_unhighlight_win (win_info);
+
+ }
+ return;
+}
+
+
+void
+tui_make_window (struct tui_gen_win_info * win_info, int box_it)
+{
+ WINDOW *handle;
+
+ handle = newwin (win_info->height,
+ win_info->width,
+ win_info->origin.y,
+ win_info->origin.x);
+ win_info->handle = handle;
+ if (handle != (WINDOW *) NULL)
+ {
+ if (box_it == BOX_WINDOW)
+ box_win (win_info, NO_HILITE);
+ win_info->is_visible = TRUE;
+ scrollok (handle, TRUE);
+ }
+}
+
+
+/* We can't really make windows visible, or invisible. So we have to
+ delete the entire window when making it visible, and create it
+ again when making it visible. */
+static void
+make_visible (struct tui_gen_win_info *win_info, int visible)
+{
+ /* Don't tear down/recreate command window */
+ if (win_info->type == CMD_WIN)
+ return;
+
+ if (visible)
+ {
+ if (!win_info->is_visible)
+ {
+ tui_make_window (win_info,
+ (win_info->type != CMD_WIN
+ && !tui_win_is_auxillary (win_info->type)));
+ win_info->is_visible = TRUE;
+ }
+ }
+ else if (!visible &&
+ win_info->is_visible && win_info->handle != (WINDOW *) NULL)
+ {
+ win_info->is_visible = FALSE;
+ tui_delete_win (win_info->handle);
+ win_info->handle = (WINDOW *) NULL;
+ }
+
+ return;
+}
+
+void
+tui_make_visible (struct tui_gen_win_info *win_info)
+{
+ make_visible (win_info, 1);
+}
+
+void
+tui_make_invisible (struct tui_gen_win_info *win_info)
+{
+ make_visible (win_info, 0);
+}
+
+
+/* Makes all windows invisible (except the command and locator windows). */
+static void
+make_all_visible (int visible)
+{
+ int i;
+
+ for (i = 0; i < MAX_MAJOR_WINDOWS; i++)
+ {
+ if (tui_win_list[i] != NULL
+ && ((tui_win_list[i])->generic.type) != CMD_WIN)
+ {
+ if (tui_win_is_source_type ((tui_win_list[i])->generic.type))
+ make_visible ((tui_win_list[i])->detail.source_info.execution_info,
+ visible);
+ make_visible ((struct tui_gen_win_info *) tui_win_list[i], visible);
+ }
+ }
+
+ return;
+}
+
+void
+tui_make_all_visible (void)
+{
+ make_all_visible (1);
+}
+
+void
+tui_make_all_invisible (void)
+{
+ make_all_visible (0);
+}
+
+/* Function to refresh all the windows currently displayed. */
+
+void
+tui_refresh_all (struct tui_win_info * * list)
+{
+ enum tui_win_type type;
+ struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
+
+ for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+ {
+ if (list[type] && list[type]->generic.is_visible)
+ {
+ if (type == SRC_WIN || type == DISASSEM_WIN)
+ {
+ touchwin (list[type]->detail.source_info.execution_info->handle);
+ tui_refresh_win (list[type]->detail.source_info.execution_info);
+ }
+ touchwin (list[type]->generic.handle);
+ tui_refresh_win (&list[type]->generic);
+ }
+ }
+ if (locator->is_visible)
+ {
+ touchwin (locator->handle);
+ tui_refresh_win (locator);
+ }
+}
+
+
+/*********************************
+** Local Static Functions
+*********************************/
--- /dev/null
+/* General window behavior.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_WINGENERAL_H
+#define TUI_WINGENERAL_H
+
+struct tui_win_info;
+struct tui_gen_win_info;
+
+extern void tui_unhighlight_win (struct tui_win_info *);
+extern void tui_make_visible (struct tui_gen_win_info *);
+extern void tui_make_invisible (struct tui_gen_win_info *);
+extern void tui_make_all_visible (void);
+extern void tui_make_all_invisible (void);
+extern void tui_make_window (struct tui_gen_win_info *, int);
+extern struct tui_win_info *tui_copy_win (struct tui_win_info *);
+extern void tui_box_win (struct tui_gen_win_info *, int);
+extern void tui_highlight_win (struct tui_win_info *);
+extern void tui_check_and_display_highlight_if_needed (struct tui_win_info *);
+extern void tui_refresh_all (struct tui_win_info **);
+extern void tui_delete_win (WINDOW * window);
+extern void tui_refresh_win (struct tui_gen_win_info *);
+
+#endif
--- /dev/null
+/* TUI display source/assembly window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "value.h"
+#include "source.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-win.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-source.h"
+#include "tui/tui-disasm.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Function to display the "main" routine. */
+void
+tui_display_main (void)
+{
+ if ((tui_source_windows ())->count > 0)
+ {
+ CORE_ADDR addr;
+
+ addr = tui_get_begin_asm_address ();
+ if (addr != (CORE_ADDR) 0)
+ {
+ struct symtab_and_line sal;
+
+ tui_update_source_windows_with_addr (addr);
+ sal = find_pc_line (addr, 0);
+ if (sal.symtab)
+ tui_update_locator_filename (sal.symtab->filename);
+ else
+ tui_update_locator_filename ("??");
+ }
+ }
+}
+
+
+
+/* Function to display source in the source window. This function
+ initializes the horizontal scroll to 0. */
+void
+tui_update_source_window (struct tui_win_info * win_info, struct symtab *s,
+ union tui_line_or_address line_or_addr, int noerror)
+{
+ win_info->detail.source_info.horizontal_offset = 0;
+ tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
+
+ return;
+}
+
+
+/* Function to display source in the source/asm window. This function
+ shows the source as specified by the horizontal offset. */
+void
+tui_update_source_window_as_is (struct tui_win_info * win_info, struct symtab *s,
+ union tui_line_or_address line_or_addr, int noerror)
+{
+ enum tui_status ret;
+
+ if (win_info->generic.type == SRC_WIN)
+ ret = tui_set_source_content (s, line_or_addr.line_no, noerror);
+ else
+ ret = tui_set_disassem_content (line_or_addr.addr);
+
+ if (ret == TUI_FAILURE)
+ {
+ tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+ tui_clear_exec_info_content (win_info);
+ }
+ else
+ {
+ tui_update_breakpoint_info (win_info, 0);
+ tui_show_source_content (win_info);
+ tui_update_exec_info (win_info);
+ if (win_info->generic.type == SRC_WIN)
+ {
+ struct symtab_and_line sal;
+
+ sal.line = line_or_addr.line_no +
+ (win_info->generic.content_size - 2);
+ sal.symtab = s;
+ set_current_source_symtab_and_line (&sal);
+ /*
+ ** If the focus was in the asm win, put it in the src
+ ** win if we don't have a split layout
+ */
+ if (tui_win_with_focus () == TUI_DISASM_WIN &&
+ tui_current_layout () != SRC_DISASSEM_COMMAND)
+ tui_set_win_focus_to (TUI_SRC_WIN);
+ }
+ }
+
+
+ return;
+}
+
+
+/* Function to ensure that the source and/or disassemly windows
+ reflect the input address. */
+void
+tui_update_source_windows_with_addr (CORE_ADDR addr)
+{
+ if (addr != 0)
+ {
+ struct symtab_and_line sal;
+ union tui_line_or_address l;
+
+ switch (tui_current_layout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ tui_show_disassem (addr);
+ break;
+ case SRC_DISASSEM_COMMAND:
+ tui_show_disassem_and_update_source (addr);
+ break;
+ default:
+ sal = find_pc_line (addr, 0);
+ l.line_no = sal.line;
+ tui_show_symtab_source (sal.symtab, l, FALSE);
+ break;
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < (tui_source_windows ())->count; i++)
+ {
+ struct tui_win_info * win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
+
+ tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
+ tui_clear_exec_info_content (win_info);
+ }
+ }
+}
+
+/* Function to ensure that the source and/or disassemly windows
+ reflect the input address. */
+void
+tui_update_source_windows_with_line (struct symtab *s, int line)
+{
+ CORE_ADDR pc;
+ union tui_line_or_address l;
+
+ switch (tui_current_layout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ find_line_pc (s, line, &pc);
+ tui_update_source_windows_with_addr (pc);
+ break;
+ default:
+ l.line_no = line;
+ tui_show_symtab_source (s, l, FALSE);
+ if (tui_current_layout () == SRC_DISASSEM_COMMAND)
+ {
+ find_line_pc (s, line, &pc);
+ tui_show_disassem (pc);
+ }
+ break;
+ }
+
+ return;
+}
+
+void
+tui_clear_source_content (struct tui_win_info * win_info, int display_prompt)
+{
+ if (win_info != NULL)
+ {
+ int i;
+
+ win_info->generic.content_in_use = FALSE;
+ tui_erase_source_content (win_info, display_prompt);
+ for (i = 0; i < win_info->generic.content_size; i++)
+ {
+ struct tui_win_element * element =
+ (struct tui_win_element *) win_info->generic.content[i];
+ element->which_element.source.has_break = FALSE;
+ element->which_element.source.is_exec_point = FALSE;
+ }
+ }
+}
+
+
+void
+tui_erase_source_content (struct tui_win_info * win_info, int display_prompt)
+{
+ int x_pos;
+ int half_width = (win_info->generic.width - 2) / 2;
+
+ if (win_info->generic.handle != (WINDOW *) NULL)
+ {
+ werase (win_info->generic.handle);
+ tui_check_and_display_highlight_if_needed (win_info);
+ if (display_prompt == EMPTY_SOURCE_PROMPT)
+ {
+ char *no_src_str;
+
+ if (win_info->generic.type == SRC_WIN)
+ no_src_str = NO_SRC_STRING;
+ else
+ no_src_str = NO_DISASSEM_STRING;
+ if (strlen (no_src_str) >= half_width)
+ x_pos = 1;
+ else
+ x_pos = half_width - strlen (no_src_str);
+ mvwaddstr (win_info->generic.handle,
+ (win_info->generic.height / 2),
+ x_pos,
+ no_src_str);
+
+ /* elz: added this function call to set the real contents of
+ the window to what is on the screen, so that later calls
+ to refresh, do display
+ the correct stuff, and not the old image */
+
+ tui_set_source_content_nil (win_info, no_src_str);
+ }
+ tui_refresh_win (&win_info->generic);
+ }
+}
+
+
+/* Redraw the complete line of a source or disassembly window. */
+static void
+tui_show_source_line (struct tui_win_info * win_info, int lineno)
+{
+ struct tui_win_element * line;
+ int x, y;
+
+ line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
+ if (line->which_element.source.is_exec_point)
+ wattron (win_info->generic.handle, A_STANDOUT);
+
+ mvwaddstr (win_info->generic.handle, lineno, 1,
+ line->which_element.source.line);
+ if (line->which_element.source.is_exec_point)
+ wattroff (win_info->generic.handle, A_STANDOUT);
+
+ /* Clear to end of line but stop before the border. */
+ getyx (win_info->generic.handle, y, x);
+ while (x + 1 < win_info->generic.width)
+ {
+ waddch (win_info->generic.handle, ' ');
+ getyx (win_info->generic.handle, y, x);
+ }
+}
+
+void
+tui_show_source_content (struct tui_win_info * win_info)
+{
+ if (win_info->generic.content_size > 0)
+ {
+ int lineno;
+
+ for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
+ tui_show_source_line (win_info, lineno);
+ }
+ else
+ tui_erase_source_content (win_info, TRUE);
+
+ tui_check_and_display_highlight_if_needed (win_info);
+ tui_refresh_win (&win_info->generic);
+ win_info->generic.content_in_use = TRUE;
+}
+
+
+/* Scroll the source forward or backward horizontally. */
+void
+tui_horizontal_source_scroll (struct tui_win_info * win_info,
+ enum tui_scroll_direction direction,
+ int num_to_scroll)
+{
+ if (win_info->generic.content != NULL)
+ {
+ int offset;
+ struct symtab *s;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+ if (cursal.symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+ else
+ s = cursal.symtab;
+
+ if (direction == LEFT_SCROLL)
+ offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
+ else
+ {
+ if ((offset =
+ win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
+ offset = 0;
+ }
+ win_info->detail.source_info.horizontal_offset = offset;
+ tui_update_source_window_as_is (win_info, s,
+ ((struct tui_win_element *)
+ win_info->generic.content[0])->which_element.source.line_or_addr,
+ FALSE);
+ }
+
+ return;
+}
+
+
+/* Set or clear the has_break flag in the line whose line is line_no. */
+void
+tui_set_is_exec_point_at (union tui_line_or_address l, struct tui_win_info * win_info)
+{
+ int changed = 0;
+ int i;
+ tui_win_content content = (tui_win_content) win_info->generic.content;
+
+ i = 0;
+ while (i < win_info->generic.content_size)
+ {
+ int new_state;
+
+ if (content[i]->which_element.source.line_or_addr.addr == l.addr)
+ new_state = TRUE;
+ else
+ new_state = FALSE;
+ if (new_state != content[i]->which_element.source.is_exec_point)
+ {
+ changed++;
+ content[i]->which_element.source.is_exec_point = new_state;
+ tui_show_source_line (win_info, i + 1);
+ }
+ i++;
+ }
+ if (changed)
+ tui_refresh_win (&win_info->generic);
+}
+
+/* Update the execution windows to show the active breakpoints.
+ This is called whenever a breakpoint is inserted, removed or
+ has its state changed. */
+void
+tui_update_all_breakpoint_info (void)
+{
+ struct tui_list *list = tui_source_windows ();
+ int i;
+
+ for (i = 0; i < list->count; i++)
+ {
+ struct tui_win_info * win = (struct tui_win_info *) list->list[i];
+
+ if (tui_update_breakpoint_info (win, FALSE))
+ {
+ tui_update_exec_info (win);
+ }
+ }
+}
+
+
+/* Scan the source window and the breakpoints to update the
+ has_break information for each line.
+ Returns 1 if something changed and the execution window
+ must be refreshed. */
+int
+tui_update_breakpoint_info (struct tui_win_info * win, int current_only)
+{
+ int i;
+ int need_refresh = 0;
+ struct tui_source_info * src = &win->detail.source_info;
+
+ for (i = 0; i < win->generic.content_size; i++)
+ {
+ struct breakpoint *bp;
+ extern struct breakpoint *breakpoint_chain;
+ int mode;
+ struct tui_source_element* line;
+
+ line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
+ if (current_only && !line->is_exec_point)
+ continue;
+
+ /* Scan each breakpoint to see if the current line has something to
+ do with it. Identify enable/disabled breakpoints as well as
+ those that we already hit. */
+ mode = 0;
+ for (bp = breakpoint_chain;
+ bp != (struct breakpoint *) NULL;
+ bp = bp->next)
+ {
+ if ((win == TUI_SRC_WIN
+ && bp->source_file
+ && (strcmp (src->filename, bp->source_file) == 0)
+ && bp->line_number == line->line_or_addr.line_no)
+ || (win == TUI_DISASM_WIN
+ && bp->loc->address == line->line_or_addr.addr))
+ {
+ if (bp->enable_state == bp_disabled)
+ mode |= TUI_BP_DISABLED;
+ else
+ mode |= TUI_BP_ENABLED;
+ if (bp->hit_count)
+ mode |= TUI_BP_HIT;
+ if (bp->cond)
+ mode |= TUI_BP_CONDITIONAL;
+ if (bp->type == bp_hardware_breakpoint)
+ mode |= TUI_BP_HARDWARE;
+ }
+ }
+ if (line->has_break != mode)
+ {
+ line->has_break = mode;
+ need_refresh = 1;
+ }
+ }
+ return need_refresh;
+}
+
+
+/* Function to initialize the content of the execution info window,
+ based upon the input window which is either the source or
+ disassembly window. */
+enum tui_status
+tui_set_exec_info_content (struct tui_win_info * win_info)
+{
+ enum tui_status ret = TUI_SUCCESS;
+
+ if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
+ {
+ struct tui_gen_win_info * exec_info_ptr = win_info->detail.source_info.execution_info;
+
+ if (exec_info_ptr->content == NULL)
+ exec_info_ptr->content =
+ (void **) tui_alloc_content (win_info->generic.height,
+ exec_info_ptr->type);
+ if (exec_info_ptr->content != NULL)
+ {
+ int i;
+
+ tui_update_breakpoint_info (win_info, 1);
+ for (i = 0; i < win_info->generic.content_size; i++)
+ {
+ struct tui_win_element * element;
+ struct tui_win_element * src_element;
+ int mode;
+
+ element = (struct tui_win_element *) exec_info_ptr->content[i];
+ src_element = (struct tui_win_element *) win_info->generic.content[i];
+
+ memset(element->which_element.simple_string, ' ',
+ sizeof(element->which_element.simple_string));
+ element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
+
+ /* Now update the exec info content based upon the state
+ of each line as indicated by the source content. */
+ mode = src_element->which_element.source.has_break;
+ if (mode & TUI_BP_HIT)
+ element->which_element.simple_string[TUI_BP_HIT_POS] =
+ (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
+ else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
+ element->which_element.simple_string[TUI_BP_HIT_POS] =
+ (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
+
+ if (mode & TUI_BP_ENABLED)
+ element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
+ else if (mode & TUI_BP_DISABLED)
+ element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
+
+ if (src_element->which_element.source.is_exec_point)
+ element->which_element.simple_string[TUI_EXEC_POS] = '>';
+ }
+ exec_info_ptr->content_size = win_info->generic.content_size;
+ }
+ else
+ ret = TUI_FAILURE;
+ }
+
+ return ret;
+}
+
+
+void
+tui_show_exec_info_content (struct tui_win_info * win_info)
+{
+ struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
+ int cur_line;
+
+ werase (exec_info->handle);
+ tui_refresh_win (exec_info);
+ for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
+ mvwaddstr (exec_info->handle,
+ cur_line,
+ 0,
+ ((struct tui_win_element *)
+ exec_info->content[cur_line - 1])->which_element.simple_string);
+ tui_refresh_win (exec_info);
+ exec_info->content_in_use = TRUE;
+}
+
+
+void
+tui_erase_exec_info_content (struct tui_win_info * win_info)
+{
+ struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
+
+ werase (exec_info->handle);
+ tui_refresh_win (exec_info);
+}
+
+void
+tui_clear_exec_info_content (struct tui_win_info * win_info)
+{
+ win_info->detail.source_info.execution_info->content_in_use = FALSE;
+ tui_erase_exec_info_content (win_info);
+
+ return;
+}
+
+/* Function to update the execution info window. */
+void
+tui_update_exec_info (struct tui_win_info * win_info)
+{
+ tui_set_exec_info_content (win_info);
+ tui_show_exec_info_content (win_info);
+}
+
+enum tui_status
+tui_alloc_source_buffer (struct tui_win_info *win_info)
+{
+ char *src_line_buf;
+ int i, line_width, max_lines;
+ enum tui_status ret = TUI_FAILURE;
+
+ max_lines = win_info->generic.height; /* less the highlight box */
+ line_width = win_info->generic.width - 1;
+ /*
+ ** Allocate the buffer for the source lines. Do this only once since they
+ ** will be re-used for all source displays. The only other time this will
+ ** be done is when a window's size changes.
+ */
+ if (win_info->generic.content == NULL)
+ {
+ src_line_buf = (char *) xmalloc ((max_lines * line_width) * sizeof (char));
+ if (src_line_buf == (char *) NULL)
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ else
+ {
+ /* allocate the content list */
+ if ((win_info->generic.content =
+ (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
+ {
+ xfree (src_line_buf);
+ src_line_buf = (char *) NULL;
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ }
+ }
+ for (i = 0; i < max_lines; i++)
+ ((struct tui_win_element *)
+ win_info->generic.content[i])->which_element.source.line =
+ src_line_buf + (line_width * i);
+ ret = TUI_SUCCESS;
+ }
+ else
+ ret = TUI_SUCCESS;
+
+ return ret;
+}
+
+
+/* Answer whether the a particular line number or address is displayed
+ in the current source window. */
+int
+tui_line_is_displayed (int line, struct tui_win_info * win_info,
+ int check_threshold)
+{
+ int is_displayed = FALSE;
+ int i, threshold;
+
+ if (check_threshold)
+ threshold = SCROLL_THRESHOLD;
+ else
+ threshold = 0;
+ i = 0;
+ while (i < win_info->generic.content_size - threshold && !is_displayed)
+ {
+ is_displayed = (((struct tui_win_element *)
+ win_info->generic.content[i])->which_element.source.line_or_addr.line_no
+ == (int) line);
+ i++;
+ }
+
+ return is_displayed;
+}
+
+
+/* Answer whether the a particular line number or address is displayed
+ in the current source window. */
+int
+tui_addr_is_displayed (CORE_ADDR addr, struct tui_win_info * win_info,
+ int check_threshold)
+{
+ int is_displayed = FALSE;
+ int i, threshold;
+
+ if (check_threshold)
+ threshold = SCROLL_THRESHOLD;
+ else
+ threshold = 0;
+ i = 0;
+ while (i < win_info->generic.content_size - threshold && !is_displayed)
+ {
+ is_displayed = (((struct tui_win_element *)
+ win_info->generic.content[i])->which_element.source.line_or_addr.addr
+ == addr);
+ i++;
+ }
+
+ return is_displayed;
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
--- /dev/null
+/* TUI display source/assembly window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TUI_SOURCEWIN_H
+#define TUI_SOURCEWIN_H
+
+#include "tui/tui-data.h"
+
+struct tui_win_info;
+
+/* Update the execution windows to show the active breakpoints. This
+ is called whenever a breakpoint is inserted, removed or has its
+ state changed. */
+extern void tui_update_all_breakpoint_info (void);
+
+/* Scan the source window and the breakpoints to update the hasBreak
+ information for each line. Returns 1 if something changed and the
+ execution window must be refreshed. */
+extern int tui_update_breakpoint_info (struct tui_win_info * win,
+ int current_only);
+
+/* Function to display the "main" routine. */
+extern void tui_display_main (void);
+extern void tui_update_source_window (struct tui_win_info *, struct symtab *,
+ union tui_line_or_address, int);
+extern void tui_update_source_window_as_is (struct tui_win_info *,
+ struct symtab *,
+ union tui_line_or_address, int);
+extern void tui_update_source_windows_with_addr (CORE_ADDR);
+extern void tui_update_source_windows_with_line (struct symtab *, int);
+extern void tui_clear_source_content (struct tui_win_info *, int);
+extern void tui_erase_source_content (struct tui_win_info *, int);
+extern void tui_show_source_content (struct tui_win_info *);
+extern void tui_horizontal_source_scroll (struct tui_win_info *,
+ enum tui_scroll_direction, int);
+extern enum tui_status tui_set_exec_info_content (struct tui_win_info *);
+extern void tui_show_exec_info_content (struct tui_win_info *);
+extern void tui_erase_exec_info_content (struct tui_win_info *);
+extern void tui_clear_exec_info_content (struct tui_win_info *);
+extern void tui_update_exec_info (struct tui_win_info *);
+
+extern void tui_set_is_exec_point_at (union tui_line_or_address,
+ struct tui_win_info *);
+extern enum tui_status tui_alloc_source_buffer (struct tui_win_info *);
+extern int tui_line_is_displayed (int, struct tui_win_info *, int);
+extern int tui_addr_is_displayed (CORE_ADDR, struct tui_win_info *, int);
+
+
+/* Constant definitions. */
+#define SCROLL_THRESHOLD 2 /* threshold for lazy scroll */
+
+#endif
--- /dev/null
+2004-01-26 Chris Demetriou <cgd@broadcom.com>
+
+ * basic.exp: New file.
+ * testutils.inc: New file.
+ * sanity.s: New file.
--- /dev/null
+# MIPS simulator instruction tests
+
+# As gross as it is, we unset the linker script specifid by the target
+# board. The MIPS libgloss linker scripts include libgcc (and possibly
+# other libraries), which the linker (used to link these tests rather
+# than the compiler) can't necessarily find.
+unset_currtarget_info ldscript
+
+# Only test mips*-elf (e.g., no mips-linux), and only test if the target
+# board really is a simulator (sim tests don't work on real HW).
+if {[istarget mips*-elf] && [board_info target exists is_simulator]} {
+
+ if {[istarget mipsisa64*-elf]} {
+ set models "mips1 mips2 mips3 mips4 mips32 mips64"
+ } elseif {[istarget mipsisa32*-elf]} {
+ set models "mips1 mips2 mips32"
+ } elseif {[istarget mips64*-elf]} {
+ set models "mips1 mips2 mips3"
+ } else {
+ # fall back to just testing mips1 code.
+ set models "mips1"
+ }
+ set cpu_option -march
+
+ run_sim_test sanity.s $models
+}
--- /dev/null
+# mips test sanity, expected to pass.
+# mach: all
+# as: -mabi=eabi
+# ld: -N -Ttext=0x80010000
+# output: *\\npass\\n
+
+ .include "testutils.inc"
+
+ setup
+
+ .set noreorder
+
+ .ent DIAG
+DIAG:
+
+ writemsg "Sanity is good!"
+
+ pass
+
+ .end DIAG
--- /dev/null
+# MIPS simulator testsuite utility functions.
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Contributed by Chris Demetriou of Broadcom Corporation.
+#
+# This file is part of the GNU simulators.
+#
+# 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 2, 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, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+# $1, $4, $5, %6, are used as temps by the macros defined here.
+
+ .macro writemsg msg
+ .data
+901: .ascii "\msg\n"
+902:
+ .previous
+ la $5, 901b
+ li $6, 902b - 901b
+ .set push
+ .set noreorder
+ jal _dowrite
+ li $4, 0
+ .set pop
+ .endm
+
+
+ # The MIPS simulator uses "break 0x3ff" as the code to exit,
+ # with the return value in $4 (a0).
+ .macro exit rc
+ li $4, \rc
+ break 0x3ff
+ .endm
+
+
+ .macro setup
+
+ .global _start
+ .ent _start
+_start:
+ .set push
+ .set noreorder
+ j DIAG
+ nop
+ .set pop
+ .end _start
+
+ .global _fail
+ .ent _fail
+_fail:
+ writemsg "fail"
+ exit 1
+ .end _fail
+
+ .global _pass
+ .ent _pass
+_pass:
+ writemsg "pass"
+ exit 0
+ .end _pass
+
+ # The MIPS simulator can use multiple different monitor types,
+ # so we hard-code the simulator "write" reserved instruction opcode,
+ # rather than jumping to a vector that invokes it. The operation
+ # expects RA to point to the location at which to continue
+ # after writing.
+ .global _dowrite
+ .ent _dowrite
+_dowrite:
+ # Write opcode (reserved instruction). See sim_monitor and its
+ # callers in sim/mips/interp.c.
+ .word 0x00000005 | ((8 << 1) << 6)
+ .end _dowrite
+
+ .endm # setup
+
+
+ .macro pass
+ .set push
+ .set noreorder
+ j _pass
+ nop
+ .set pop
+ .endm
+
+
+ .macro fail
+ .set push
+ .set noreorder
+ j _fail
+ nop
+ .set pop
+ .endm
+
+
+ .macro load32 reg, val
+ li \reg, \val
+ .endm
+
+
+ .macro load64 reg, val
+ dli \reg, \val
+ .endm
+
+
+ .macro loadaddr reg, addr
+ la \reg, \addr
+ .endm
+
+
+ .macro checkreg reg, expreg
+ .set push
+ .set noat
+ .set noreorder
+ beq \expreg, \reg, 901f
+ nop
+ fail
+901:
+ .set pop
+ .endm
+
+
+ .macro check32 reg, val
+ .set push
+ .set noat
+ load32 $1, \val
+ checkreg \reg, $1
+ .set pop
+ .endm
+
+
+ .macro check64 reg, val
+ .set push
+ .set noat
+ load64 $1, \val
+ checkreg \reg, $1
+ .set pop
+ .endm