* tui-hooks.c: New file, gdb hooks for tui.
authorStephane Carrez <stcarrez@nerim.fr>
Tue, 24 Jul 2001 20:40:39 +0000 (20:40 +0000)
committerStephane Carrez <stcarrez@nerim.fr>
Tue, 24 Jul 2001 20:40:39 +0000 (20:40 +0000)
* tui-out.c: New file, image copied from cli-out.c.
(tui_field_int): Identify "line" fields and keep track of them.
(tui_field_string): Likewise for "file".
(tui_out_new): Use flags = 0 to avoid printing the sources.

gdb/tui/ChangeLog
gdb/tui/tui-hooks.c [new file with mode: 0644]
gdb/tui/tui-out.c [new file with mode: 0644]

index 58fb19f..64ea70d 100644 (file)
@@ -1,3 +1,11 @@
+2001-07-24  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * tui-hooks.c: New file, gdb hooks for tui.
+       * tui-out.c: New file, image copied from cli-out.c.
+       (tui_field_int): Identify "line" fields and keep track of them.
+       (tui_field_string): Likewise for "file".
+       (tui_out_new): Use flags = 0 to avoid printing the sources.
+
 2001-07-23  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
 
        * tuiIO.c (tui_cont_sig): Update cursor position on the screen to
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
new file mode 100644 (file)
index 0000000..a7f24d3
--- /dev/null
@@ -0,0 +1,390 @@
+/* GDB hooks for TUI.
+   Copyright 2001 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 "symtab.h"
+#include "inferior.h"
+#include "command.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "event-loop.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "gdb-events.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiLayout.h"
+#include "tuiIO.h"
+#include "tuiRegs.h"
+#include "tuiWin.h"
+#include "tuiStack.h"
+#include "tuiDataWin.h"
+#include "tuiSourceWin.h"
+
+int tui_target_has_run = 0;
+
+static void (* tui_target_new_objfile_chain) (struct objfile*);
+extern void (*selected_frame_level_changed_hook) (int);
+
+static void
+tui_new_objfile_hook (struct objfile* objfile)
+{
+  if (tui_active)
+    {
+      tuiDisplayMainFunction ();
+    }
+  
+  if (tui_target_new_objfile_chain)
+    tui_target_new_objfile_chain (objfile);
+}
+
+static int
+tui_query_hook (const char * msg, va_list argp)
+{
+  int retval;
+  int ans2;
+  int answer;
+
+  /* Automatically answer "yes" if input is not from a terminal.  */
+  if (!input_from_terminal_p ())
+    return 1;
+
+  echo ();
+  while (1)
+    {
+      wrap_here ("");          /* Flush any buffered output */
+      gdb_flush (gdb_stdout);
+
+      vfprintf_filtered (gdb_stdout, msg, argp);
+      printf_filtered ("(y or n) ");
+
+      wrap_here ("");
+      gdb_flush (gdb_stdout);
+
+      answer = tui_getc (stdin);
+      clearerr (stdin);                /* in case of C-d */
+      if (answer == EOF)       /* C-d */
+       {
+         retval = 1;
+         break;
+       }
+      /* Eat rest of input line, to EOF or newline */
+      if (answer != '\n')
+       do
+         {
+            ans2 = tui_getc (stdin);
+           clearerr (stdin);
+         }
+       while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
+
+      if (answer >= 'a')
+       answer -= 040;
+      if (answer == 'Y')
+       {
+         retval = 1;
+         break;
+       }
+      if (answer == 'N')
+       {
+         retval = 0;
+         break;
+       }
+      printf_filtered ("Please answer y or n.\n");
+    }
+  noecho ();
+  return retval;
+}
+
+/* Prevent recursion of registers_changed_hook().  */
+static int tui_refreshing_registers = 0;
+
+static void
+tui_registers_changed_hook (void)
+{
+  struct frame_info *fi;
+
+  fi = selected_frame;
+  if (fi && tui_refreshing_registers == 0)
+    {
+      tui_refreshing_registers = 1;
+#if 0
+      tuiCheckDataValues (fi);
+#endif
+      tui_refreshing_registers = 0;
+    }
+}
+
+static void
+tui_register_changed_hook (int regno)
+{
+  struct frame_info *fi;
+
+  fi = selected_frame;
+  if (fi && tui_refreshing_registers == 0)
+    {
+      tui_refreshing_registers = 1;
+      tuiCheckDataValues (fi);
+      tui_refreshing_registers = 0;
+    }
+}
+
+extern struct breakpoint *breakpoint_chain;
+
+/* Find a breakpoint given its number.  Returns null if not found.  */
+static struct breakpoint *
+get_breakpoint (int number)
+{
+  struct breakpoint *bp;
+
+  for (bp = breakpoint_chain; bp; bp = bp->next)
+    {
+      if (bp->number == number)
+        return bp;
+    }
+  return 0;
+}
+
+/* Breakpoint creation hook.
+   Update the screen to show the new breakpoint.  */
+static void
+tui_event_create_breakpoint (int number)
+{
+  struct breakpoint *bp;
+
+  bp = get_breakpoint (number);
+  if (bp)
+    {
+      switch (bp->type)
+        {
+        case bp_breakpoint:
+        case bp_hardware_breakpoint:
+          tuiAllSetHasBreakAt (bp, 1);
+          tuiUpdateAllExecInfos ();
+          break;
+
+        default:
+          break;
+        }
+    }
+}
+
+/* Breakpoint deletion hook.
+   Refresh the screen to update the breakpoint marks.  */
+static void
+tui_event_delete_breakpoint (int number)
+{
+  struct breakpoint *bp;
+  struct breakpoint *b;
+  int clearIt;
+
+  bp = get_breakpoint (number);
+  if (bp == 0)
+    return;
+
+  /* Before turning off the visuals for the bp, check to see that
+     there are no other bps at the same address. */
+  clearIt = 0;
+  for (b = breakpoint_chain; b; b = b->next)
+    {
+      clearIt = (b == bp || b->address != bp->address);
+      if (!clearIt)
+        break;
+    }
+
+  if (clearIt)
+    {
+      tuiAllSetHasBreakAt (bp, 0);
+      tuiUpdateAllExecInfos ();
+    }
+}
+
+static void
+tui_event_modify_breakpoint (int number)
+{
+  ;
+}
+
+static void
+tui_event_default (int number)
+{
+  ;
+}
+
+static struct gdb_events *tui_old_event_hooks;
+
+static struct gdb_events tui_event_hooks =
+{
+  tui_event_create_breakpoint,
+  tui_event_delete_breakpoint,
+  tui_event_modify_breakpoint,
+  tui_event_default,
+  tui_event_default,
+  tui_event_default
+};
+
+/* Called when going to wait for the target.
+   Leave curses mode and setup program mode.  */
+static ptid_t
+tui_target_wait_hook (ptid_t pid, struct target_waitstatus *status)
+{
+  ptid_t res;
+
+  /* Leave tui mode (optional).  */
+#if 0
+  if (tui_active)
+    {
+      target_terminal_ours ();
+      endwin ();
+      target_terminal_inferior ();
+    }
+#endif
+  tui_target_has_run = 1;
+  res = target_wait (pid, status);
+
+  if (tui_active)
+    {
+      /* TODO: need to refresh (optional).  */
+    }
+  return res;
+}
+
+/* The selected frame has changed.  This is happens after a target
+   stop or when the user explicitly changes the frame (up/down/thread/...).  */
+static void
+tui_selected_frame_level_changed_hook (int level)
+{
+  struct frame_info *fi;
+
+  fi = selected_frame;
+  /* Ensure that symbols for this frame are read in.  Also, determine the
+     source language of this frame, and switch to it if desired.  */
+  if (fi)
+    {
+      struct symtab *s;
+      
+      s = find_pc_symtab (fi->pc);
+      /* elz: this if here fixes the problem with the pc not being displayed
+         in the tui asm layout, with no debug symbols. The value of s 
+         would be 0 here, and select_source_symtab would abort the
+         command by calling the 'error' function */
+      if (s)
+       {
+          select_source_symtab (s);
+          tuiShowFrameInfo (fi);
+       }
+
+      /* Refresh the register window if it's visible.  */
+      if (tui_is_window_visible (DATA_WIN))
+        {
+          tui_refreshing_registers = 1;
+          tuiCheckDataValues (fi);
+          tui_refreshing_registers = 0;
+        }
+    }
+}
+
+/* Called from print_frame_info to list the line we stopped in.  */
+static void
+tui_print_frame_info_listing_hook (struct symtab *s, int line,
+                                   int stopline, int noerror)
+{
+  select_source_symtab (s);
+  tuiShowFrameInfo (selected_frame);
+}
+
+/* Install the TUI specific hooks.  */
+void
+tui_install_hooks (void)
+{
+  target_wait_hook = tui_target_wait_hook;
+  selected_frame_level_changed_hook = tui_selected_frame_level_changed_hook;
+  print_frame_info_listing_hook = tui_print_frame_info_listing_hook;
+
+  query_hook = tui_query_hook;
+
+  /* Install the event hooks.  */
+  tui_old_event_hooks = set_gdb_event_hooks (&tui_event_hooks);
+
+  registers_changed_hook = tui_registers_changed_hook;
+  register_changed_hook = tui_register_changed_hook;
+}
+
+/* Remove the TUI specific hooks.  */
+void
+tui_remove_hooks (void)
+{
+  target_wait_hook = 0;
+  selected_frame_level_changed_hook = 0;
+  print_frame_info_listing_hook = 0;
+  query_hook = 0;
+  registers_changed_hook = 0;
+  register_changed_hook = 0;
+
+  /* Restore the previous event hooks.  */
+  set_gdb_event_hooks (tui_old_event_hooks);
+}
+
+/* Cleanup the tui before exiting.  */
+static void
+tui_exit (void)
+{
+  /* Disable the tui.  Curses mode is left leaving the screen
+     in a clean state (see endwin()).  */
+  tui_disable ();
+}
+
+/* Initialize the tui by installing several gdb hooks, initializing
+   the tui IO and preparing the readline with the kind binding.  */
+static void
+tui_init_hook (char *argv0)
+{
+  /* Install exit handler to leave the screen in a good shape.  */
+  atexit (tui_exit);
+
+  initializeStaticData ();
+
+  /* Install the permanent hooks.  */
+  tui_target_new_objfile_chain = target_new_objfile_hook;
+  target_new_objfile_hook = tui_new_objfile_hook;
+
+  tui_initialize_io ();
+  tui_initialize_readline ();
+
+  /* Decide in which mode to start using GDB (based on -tui).  */
+  if (tui_version)
+    {
+      tui_enable ();
+    }
+}
+
+/* Initialize the tui.  */
+void
+_initialize_tui (void)
+{
+  /* Setup initialization hook.  */
+  init_ui_hook = tui_init_hook;
+}
+
diff --git a/gdb/tui/tui-out.c b/gdb/tui/tui-out.c
new file mode 100644 (file)
index 0000000..9789c65
--- /dev/null
@@ -0,0 +1,414 @@
+/* Output generating routines for GDB CLI.
+   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Cygnus Solutions.
+   Written by Fernando Nasser for Cygnus.
+
+   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 "ui-out.h"
+#include "tui.h"
+#include "gdb_string.h"
+#include "gdb_assert.h"
+
+/* Convenience macro for allocting typesafe memory. */
+
+#ifndef XMALLOC
+#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE))
+#endif
+
+struct ui_out_data
+  {
+    struct ui_file *stream;
+    int suppress_output;
+    int line;
+    int start_of_line;
+  };
+
+/* These are the CLI output functions */
+
+static void tui_table_begin (struct ui_out *uiout, int nbrofcols,
+                            int nr_rows, const char *tblid);
+static void tui_table_body (struct ui_out *uiout);
+static void tui_table_end (struct ui_out *uiout);
+static void tui_table_header (struct ui_out *uiout, int width,
+                             enum ui_align alig, const char *col_name,
+                             const char *colhdr);
+static void tui_begin (struct ui_out *uiout, enum ui_out_type type,
+                      int level, const char *lstid);
+static void tui_end (struct ui_out *uiout, enum ui_out_type type, int level);
+static void tui_field_int (struct ui_out *uiout, int fldno, int width,
+                          enum ui_align alig, const char *fldname, int value);
+static void tui_field_skip (struct ui_out *uiout, int fldno, int width,
+                           enum ui_align alig, const char *fldname);
+static void tui_field_string (struct ui_out *uiout, int fldno, int width,
+                             enum ui_align alig, const char *fldname,
+                             const char *string);
+static void tui_field_fmt (struct ui_out *uiout, int fldno,
+                          int width, enum ui_align align,
+                          const char *fldname, const char *format,
+                          va_list args);
+static void tui_spaces (struct ui_out *uiout, int numspaces);
+static void tui_text (struct ui_out *uiout, const char *string);
+static void tui_message (struct ui_out *uiout, int verbosity,
+                        const char *format, va_list args);
+static void tui_wrap_hint (struct ui_out *uiout, char *identstring);
+static void tui_flush (struct ui_out *uiout);
+
+/* This is the CLI ui-out implementation functions vector */
+
+/* FIXME: This can be initialized dynamically after default is set to
+   handle initial output in main.c */
+
+static struct ui_out_impl tui_ui_out_impl =
+{
+  tui_table_begin,
+  tui_table_body,
+  tui_table_end,
+  tui_table_header,
+  tui_begin,
+  tui_end,
+  tui_field_int,
+  tui_field_skip,
+  tui_field_string,
+  tui_field_fmt,
+  tui_spaces,
+  tui_text,
+  tui_message,
+  tui_wrap_hint,
+  tui_flush,
+  0, /* Does not need MI hacks (i.e. needs CLI hacks).  */
+};
+
+/* Prototypes for local functions */
+
+extern void _initialize_tui_out (void);
+
+static void field_separator (void);
+
+static void out_field_fmt (struct ui_out *uiout, int fldno,
+                          const char *fldname,
+                          const char *format,...);
+
+/* local variables */
+
+/* (none yet) */
+
+/* Mark beginning of a table */
+
+void
+tui_table_begin (struct ui_out *uiout, int nbrofcols,
+                int nr_rows,
+                const char *tblid)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (nr_rows == 0)
+    data->suppress_output = 1;
+  else
+    /* Only the table suppresses the output and, fortunatly, a table
+       is not a recursive data structure. */
+    gdb_assert (data->suppress_output == 0);
+}
+
+/* Mark beginning of a table body */
+
+void
+tui_table_body (struct ui_out *uiout)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  /* first, close the table header line */
+  tui_text (uiout, "\n");
+}
+
+/* Mark end of a table */
+
+void
+tui_table_end (struct ui_out *uiout)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  data->suppress_output = 0;
+}
+
+/* Specify table header */
+
+void
+tui_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
+                 const char *col_name,
+                 const char *colhdr)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  tui_field_string (uiout, 0, width, alignment, 0, colhdr);
+}
+
+/* Mark beginning of a list */
+
+void
+tui_begin (struct ui_out *uiout,
+          enum ui_out_type type,
+          int level,
+          const char *id)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+}
+
+/* Mark end of a list */
+
+void
+tui_end (struct ui_out *uiout,
+        enum ui_out_type type,
+        int level)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+}
+
+/* output an int field */
+
+void
+tui_field_int (struct ui_out *uiout, int fldno, int width,
+              enum ui_align alignment,
+              const char *fldname, int value)
+{
+  char buffer[20];             /* FIXME: how many chars long a %d can become? */
+
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+
+  /* Don't print line number, keep it for later.  */
+  if (data->start_of_line == 0 && strcmp (fldname, "line") == 0)
+    {
+      data->start_of_line ++;
+      data->line = value;
+      return;
+    }
+  data->start_of_line ++;
+  sprintf (buffer, "%d", value);
+  tui_field_string (uiout, fldno, width, alignment, fldname, buffer);
+}
+
+/* used to ommit a field */
+
+void
+tui_field_skip (struct ui_out *uiout, int fldno, int width,
+               enum ui_align alignment,
+               const char *fldname)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  tui_field_string (uiout, fldno, width, alignment, fldname, "");
+}
+
+/* other specific tui_field_* end up here so alignment and field
+   separators are both handled by tui_field_string */
+
+void
+tui_field_string (struct ui_out *uiout,
+                 int fldno,
+                 int width,
+                 enum ui_align align,
+                 const char *fldname,
+                 const char *string)
+{
+  int before = 0;
+  int after = 0;
+
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+
+  if (fldname && data->line > 0 && strcmp (fldname, "file") == 0)
+    {
+      data->start_of_line ++;
+      if (data->line > 0)
+        {
+          tui_show_source (string, data->line);
+        }
+      return;
+    }
+  
+  data->start_of_line ++;
+  if ((align != ui_noalign) && string)
+    {
+      before = width - strlen (string);
+      if (before <= 0)
+       before = 0;
+      else
+       {
+         if (align == ui_right)
+           after = 0;
+         else if (align == ui_left)
+           {
+             after = before;
+             before = 0;
+           }
+         else
+           /* ui_center */
+           {
+             after = before / 2;
+             before -= after;
+           }
+       }
+    }
+
+  if (before)
+    ui_out_spaces (uiout, before);
+  if (string)
+    out_field_fmt (uiout, fldno, fldname, "%s", string);
+  if (after)
+    ui_out_spaces (uiout, after);
+
+  if (align != ui_noalign)
+    field_separator ();
+}
+
+/* This is the only field function that does not align */
+
+void
+tui_field_fmt (struct ui_out *uiout, int fldno,
+              int width, enum ui_align align,
+              const char *fldname,
+              const char *format,
+              va_list args)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+
+  data->start_of_line ++;
+  vfprintf_filtered (data->stream, format, args);
+
+  if (align != ui_noalign)
+    field_separator ();
+}
+
+void
+tui_spaces (struct ui_out *uiout, int numspaces)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  print_spaces_filtered (numspaces, data->stream);
+}
+
+void
+tui_text (struct ui_out *uiout, const char *string)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  data->start_of_line ++;
+  if (data->line > 0)
+    {
+      if (strchr (string, '\n') != 0)
+        {
+          data->line = -1;
+          data->start_of_line = 0;
+        }
+      return;
+    }
+  if (strchr (string, '\n'))
+    data->start_of_line = 0;
+  fputs_filtered (string, data->stream);
+}
+
+void
+tui_message (struct ui_out *uiout, int verbosity,
+            const char *format, va_list args)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  if (ui_out_get_verblvl (uiout) >= verbosity)
+    vfprintf_unfiltered (data->stream, format, args);
+}
+
+void
+tui_wrap_hint (struct ui_out *uiout, char *identstring)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  if (data->suppress_output)
+    return;
+  wrap_here (identstring);
+}
+
+void
+tui_flush (struct ui_out *uiout)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  gdb_flush (data->stream);
+}
+
+/* local functions */
+
+/* Like tui_field_fmt, but takes a variable number of args
+   and makes a va_list and does not insert a separator */
+
+/* VARARGS */
+static void
+out_field_fmt (struct ui_out *uiout, int fldno,
+              const char *fldname,
+              const char *format,...)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  va_list args;
+
+  va_start (args, format);
+  vfprintf_filtered (data->stream, format, args);
+
+  va_end (args);
+}
+
+/* access to ui_out format private members */
+
+static void
+field_separator (void)
+{
+  struct ui_out_data *data = ui_out_data (uiout);
+  fputc_filtered (' ', data->stream);
+}
+
+/* initalize private members at startup */
+
+struct ui_out *
+tui_out_new (struct ui_file *stream)
+{
+  int flags = 0;
+
+  struct ui_out_data *data = XMALLOC (struct ui_out_data);
+  data->stream = stream;
+  data->suppress_output = 0;
+  data->line = -1;
+  data->start_of_line = 1;
+  return ui_out_new (&tui_ui_out_impl, data, flags);
+}
+
+/* standard gdb initialization hook */
+void
+_initialize_tui_out (void)
+{
+  /* nothing needs to be done */
+}