PR22348, conflicting global vars in crx and cr16
[deliverable/binutils-gdb.git] / gdb / top.c
index c7a9c21634a7013a10db86737a01af4a99e87e02..9f5dd58d21658b279194edf50153b24f221ff270 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1,6 +1,6 @@
 /* Top level stuff for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2016 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "value.h"
 #include "language.h"
 #include "terminal.h"          /* For job_control.  */
+#include "job-control.h"
 #include "annotate.h"
 #include "completer.h"
 #include "top.h"
 #include "version.h"
 #include "serial.h"
-#include "doublest.h"
 #include "main.h"
 #include "event-loop.h"
 #include "gdbthread.h"
@@ -128,17 +128,10 @@ show_confirm (struct ui_file *file, int from_tty,
                    value);
 }
 
-/* Flag to indicate whether a user defined command is currently running.  */
-
-int in_user_command;
-
 /* Current working directory.  */
 
 char *current_directory;
 
-/* The directory name is actually stored here (usually).  */
-char gdb_dirbuf[1024];
-
 /* The last command line executed on the console.  Used for command
    repetitions.  */
 char *saved_command_line;
@@ -218,7 +211,7 @@ void (*deprecated_warning_hook) (const char *, va_list);
    called to notify the GUI that we are done with the interaction
    window and it can close it.  */
 
-void (*deprecated_readline_begin_hook) (char *, ...);
+void (*deprecated_readline_begin_hook) (const char *, ...);
 char *(*deprecated_readline_hook) (const char *);
 void (*deprecated_readline_end_hook) (void);
 
@@ -255,130 +248,96 @@ static int highest_ui_num;
 
 /* See top.h.  */
 
-struct ui *
-new_ui (FILE *instream, FILE *outstream, FILE *errstream)
+ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
+  : next (nullptr),
+    num (++highest_ui_num),
+    call_readline (nullptr),
+    input_handler (nullptr),
+    command_editing (0),
+    interp_info (nullptr),
+    async (0),
+    secondary_prompt_depth (0),
+    stdin_stream (instream_),
+    instream (instream_),
+    outstream (outstream_),
+    errstream (errstream_),
+    input_fd (fileno (instream)),
+    input_interactive_p (ISATTY (instream)),
+    prompt_state (PROMPT_NEEDED),
+    m_gdb_stdout (new stdio_file (outstream)),
+    m_gdb_stdin (new stdio_file (instream)),
+    m_gdb_stderr (new stderr_file (errstream)),
+    m_gdb_stdlog (m_gdb_stderr),
+    m_current_uiout (nullptr)
 {
-  struct ui *ui;
-
-  ui = XCNEW (struct ui);
-
-  ui->num = ++highest_ui_num;
-  ui->stdin_stream = instream;
-  ui->instream = instream;
-  ui->outstream = outstream;
-  ui->errstream = errstream;
-
-  ui->input_fd = fileno (ui->instream);
-
-  ui->input_interactive_p = ISATTY (ui->instream);
-
-  ui->m_gdb_stdin = stdio_fileopen (ui->instream);
-  ui->m_gdb_stdout = stdio_fileopen (ui->outstream);
-  ui->m_gdb_stderr = stderr_fileopen (ui->errstream);
-  ui->m_gdb_stdlog = ui->m_gdb_stderr;
-
-  ui->prompt_state = PROMPT_NEEDED;
+  buffer_init (&line_buffer);
 
   if (ui_list == NULL)
-    ui_list = ui;
+    ui_list = this;
   else
     {
       struct ui *last;
 
       for (last = ui_list; last->next != NULL; last = last->next)
        ;
-      last->next = ui;
+      last->next = this;
     }
-
-  return ui;
-}
-
-static void
-free_ui (struct ui *ui)
-{
-  ui_file_delete (ui->m_gdb_stdin);
-  ui_file_delete (ui->m_gdb_stdout);
-  ui_file_delete (ui->m_gdb_stderr);
-
-  xfree (ui);
 }
 
-void
-delete_ui (struct ui *todel)
+ui::~ui ()
 {
   struct ui *ui, *uiprev;
 
   uiprev = NULL;
 
   for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
-    if (ui == todel)
+    if (ui == this)
       break;
 
   gdb_assert (ui != NULL);
 
   if (uiprev != NULL)
-    uiprev->next = ui->next;
+    uiprev->next = next;
   else
-    ui_list = ui->next;
-
-  free_ui (ui);
-}
-
-/* Cleanup that deletes a UI.  */
-
-static void
-delete_ui_cleanup (void *void_ui)
-{
-  struct ui *ui = (struct ui *) void_ui;
-
-  delete_ui (ui);
-}
+    ui_list = next;
 
-/* See top.h.  */
-
-struct cleanup *
-make_delete_ui_cleanup (struct ui *ui)
-{
-  return make_cleanup (delete_ui_cleanup, ui);
+  delete m_gdb_stdin;
+  delete m_gdb_stdout;
+  delete m_gdb_stderr;
 }
 
 /* Open file named NAME for read/write, making sure not to make it the
    controlling terminal.  */
 
-static FILE *
+static gdb_file_up
 open_terminal_stream (const char *name)
 {
   int fd;
 
-  fd = open (name, O_RDWR | O_NOCTTY);
+  fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
   if (fd < 0)
     perror_with_name  (_("opening terminal failed"));
 
-  return fdopen (fd, "w+");
+  return gdb_file_up (fdopen (fd, "w+"));
 }
 
 /* Implementation of the "new-ui" command.  */
 
 static void
-new_ui_command (char *args, int from_tty)
+new_ui_command (const char *args, int from_tty)
 {
-  struct ui *ui;
   struct interp *interp;
-  FILE *stream[3] = { NULL, NULL, NULL };
+  gdb_file_up stream[3];
   int i;
   int res;
   int argc;
-  char **argv;
   const char *interpreter_name;
   const char *tty_name;
-  struct cleanup *success_chain;
-  struct cleanup *failure_chain;
 
   dont_repeat ();
 
-  argv = gdb_buildargv (args);
-  success_chain = make_cleanup_freeargv (argv);
-  argc = countargv (argv);
+  gdb_argv argv (args);
+  argc = argv.count ();
 
   if (argc < 2)
     error (_("usage: new-ui <interpreter> <tty>"));
@@ -389,31 +348,28 @@ new_ui_command (char *args, int from_tty)
   {
     scoped_restore save_ui = make_scoped_restore (&current_ui);
 
-    failure_chain = make_cleanup (null_cleanup, NULL);
-
     /* Open specified terminal, once for each of
        stdin/stdout/stderr.  */
     for (i = 0; i < 3; i++)
-      {
-       stream[i] = open_terminal_stream (tty_name);
-       make_cleanup_fclose (stream[i]);
-      }
+      stream[i] = open_terminal_stream (tty_name);
 
-    ui = new_ui (stream[0], stream[1], stream[2]);
-    make_cleanup (delete_ui_cleanup, ui);
+    std::unique_ptr<ui> ui
+      (new struct ui (stream[0].get (), stream[1].get (), stream[2].get ()));
 
     ui->async = 1;
 
-    current_ui = ui;
+    current_ui = ui.get ();
 
     set_top_level_interpreter (interpreter_name);
 
     interp_pre_command_loop (top_level_interpreter ());
 
-    discard_cleanups (failure_chain);
+    /* Make sure the files are not closed.  */
+    stream[0].release ();
+    stream[1].release ();
+    stream[2].release ();
 
-    /* This restores the previous UI and frees argv.  */
-    do_cleanups (success_chain);
+    ui.release ();
   }
 
   printf_unfiltered ("New UI allocated\n");
@@ -447,27 +403,14 @@ quit_cover (void)
    event-top.c into this file, top.c.  */
 /* static */ const char *source_file_name;
 
-/* Clean up on error during a "source" command (or execution of a
-   user-defined command).  */
-
-void
-do_restore_instream_cleanup (void *stream)
-{
-  struct ui *ui = current_ui;
-
-  /* Restore the previous input stream.  */
-  ui->instream = (FILE *) stream;
-}
-
 /* Read commands from STREAM.  */
 void
 read_command_file (FILE *stream)
 {
   struct ui *ui = current_ui;
-  struct cleanup *cleanups;
 
-  cleanups = make_cleanup (do_restore_instream_cleanup, ui->instream);
-  ui->instream = stream;
+  scoped_restore save_instream
+    = make_scoped_restore (&ui->instream, stream);
 
   /* Read commands from `instream' and execute them until end of file
      or error reading instream.  */
@@ -482,8 +425,6 @@ read_command_file (FILE *stream)
        break;
       command_handler (command);
     }
-
-  do_cleanups (cleanups);
 }
 \f
 void (*pre_init_ui_hook) (void);
@@ -497,15 +438,9 @@ do_chdir_cleanup (void *old_dir)
 }
 #endif
 
-struct cleanup *
-prepare_execute_command (void)
+scoped_value_mark
+prepare_execute_command ()
 {
-  struct value *mark;
-  struct cleanup *cleanup;
-
-  mark = value_mark ();
-  cleanup = make_cleanup_value_free_to_mark (mark);
-
   /* With multiple threads running while the one we're examining is
      stopped, the dcache can get stale without us being able to detect
      it.  For the duration of the command, though, use the dcache to
@@ -513,7 +448,7 @@ prepare_execute_command (void)
   if (non_stop)
     target_dcache_invalidate ();
 
-  return cleanup;
+  return scoped_value_mark ();
 }
 
 /* Tell the user if the language has changed (except first time) after
@@ -593,12 +528,12 @@ maybe_wait_sync_command_done (int was_sync)
 void
 execute_command (char *p, int from_tty)
 {
-  struct cleanup *cleanup_if_error, *cleanup;
+  struct cleanup *cleanup_if_error;
   struct cmd_list_element *c;
   char *line;
 
   cleanup_if_error = make_bpstat_clear_actions_cleanup ();
-  cleanup = prepare_execute_command ();
+  scoped_value_mark cleanup = prepare_execute_command ();
 
   /* Force cleanup of any alloca areas if using C alloca instead of
      a builtin alloca.  */
@@ -607,7 +542,6 @@ execute_command (char *p, int from_tty)
   /* This can happen when command_line_input hits end of file.  */
   if (p == NULL)
     {
-      do_cleanups (cleanup);
       discard_cleanups (cleanup_if_error);
       return;
     }
@@ -682,7 +616,6 @@ execute_command (char *p, int from_tty)
 
   check_frame_language_change ();
 
-  do_cleanups (cleanup);
   discard_cleanups (cleanup_if_error);
 }
 
@@ -690,46 +623,36 @@ execute_command (char *p, int from_tty)
    returned string, do not display it to the screen.  BATCH_FLAG will be
    temporarily set to true.  */
 
-char *
+std::string
 execute_command_to_string (char *p, int from_tty)
 {
-  struct ui_file *str_file;
-  struct cleanup *cleanup;
-  char *retval;
-
   /* GDB_STDOUT should be better already restored during these
      restoration callbacks.  */
-  cleanup = set_batch_flag_and_make_cleanup_restore_page_info ();
+  set_batch_flag_and_restore_page_info save_page_info;
 
   scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
 
-  str_file = mem_fileopen ();
+  string_file str_file;
 
-  make_cleanup_ui_file_delete (str_file);
-
-  if (ui_out_redirect (current_uiout, str_file) < 0)
-    warning (_("Current output protocol does not support redirection"));
-  else
-    make_cleanup_ui_out_redirect_pop (current_uiout);
-
-  scoped_restore save_stdout
-    = make_scoped_restore (&gdb_stdout, str_file);
-  scoped_restore save_stderr
-    = make_scoped_restore (&gdb_stderr, str_file);
-  scoped_restore save_stdlog
-    = make_scoped_restore (&gdb_stdlog, str_file);
-  scoped_restore save_stdtarg
-    = make_scoped_restore (&gdb_stdtarg, str_file);
-  scoped_restore save_stdtargerr
-    = make_scoped_restore (&gdb_stdtargerr, str_file);
-
-  execute_command (p, from_tty);
-
-  retval = ui_file_xstrdup (str_file, NULL);
-
-  do_cleanups (cleanup);
+  {
+    current_uiout->redirect (&str_file);
+    ui_out_redirect_pop redirect_popper (current_uiout);
+
+    scoped_restore save_stdout
+      = make_scoped_restore (&gdb_stdout, &str_file);
+    scoped_restore save_stderr
+      = make_scoped_restore (&gdb_stderr, &str_file);
+    scoped_restore save_stdlog
+      = make_scoped_restore (&gdb_stdlog, &str_file);
+    scoped_restore save_stdtarg
+      = make_scoped_restore (&gdb_stdtarg, &str_file);
+    scoped_restore save_stdtargerr
+      = make_scoped_restore (&gdb_stdtargerr, &str_file);
+
+    execute_command (p, from_tty);
+  }
 
-  return retval;
+  return std::move (str_file.string ());
 }
 
 \f
@@ -758,13 +681,10 @@ dont_repeat (void)
 /* Prevent dont_repeat from working, and return a cleanup that
    restores the previous state.  */
 
-struct cleanup *
+scoped_restore_tmpl<int>
 prevent_dont_repeat (void)
 {
-  struct cleanup *result = make_cleanup_restore_integer (&suppress_dont_repeat);
-
-  suppress_dont_repeat = 1;
-  return result;
+  return make_scoped_restore (&suppress_dont_repeat, 1);
 }
 
 \f
@@ -1041,8 +961,11 @@ gdb_readline_wrapper (const char *prompt)
   if (cleanup->target_is_async_orig)
     target_async (0);
 
-  /* Display our prompt and prevent double prompt display.  */
-  display_gdb_prompt (prompt);
+  /* Display our prompt and prevent double prompt display.  Don't pass
+     down a NULL prompt, since that has special meaning for
+     display_gdb_prompt -- it indicates a request to print the primary
+     prompt, while we want a secondary prompt here.  */
+  display_gdb_prompt (prompt != NULL ? prompt : "");
   if (ui->command_editing)
     rl_already_prompted = 1;
 
@@ -1162,19 +1085,16 @@ static void
 gdb_safe_append_history (void)
 {
   int ret, saved_errno;
-  char *local_history_filename;
-  struct cleanup *old_chain;
 
-  local_history_filename
-    = xstrprintf ("%s-gdb%ld~", history_filename, (long) getpid ());
-  old_chain = make_cleanup (xfree, local_history_filename);
+  std::string local_history_filename
+    = string_printf ("%s-gdb%ld~", history_filename, (long) getpid ());
 
-  ret = rename (history_filename, local_history_filename);
+  ret = rename (history_filename, local_history_filename.c_str ());
   saved_errno = errno;
   if (ret < 0 && saved_errno != ENOENT)
     {
       warning (_("Could not rename %s to %s: %s"),
-              history_filename, local_history_filename,
+              history_filename, local_history_filename.c_str (),
               safe_strerror (saved_errno));
     }
   else
@@ -1190,24 +1110,23 @@ gdb_safe_append_history (void)
             to move it back anyway.  Otherwise a global history file would
             never get created!  */
           gdb_assert (saved_errno == ENOENT);
-          write_history (local_history_filename);
+          write_history (local_history_filename.c_str ());
        }
       else
        {
-         append_history (command_count, local_history_filename);
+         append_history (command_count, local_history_filename.c_str ());
          if (history_is_stifled ())
-           history_truncate_file (local_history_filename, history_max_entries);
+           history_truncate_file (local_history_filename.c_str (),
+                                  history_max_entries);
        }
 
-      ret = rename (local_history_filename, history_filename);
+      ret = rename (local_history_filename.c_str (), history_filename);
       saved_errno = errno;
       if (ret < 0 && saved_errno != EEXIST)
         warning (_("Could not rename %s to %s: %s"),
-                local_history_filename, history_filename,
+                local_history_filename.c_str (), history_filename,
                 safe_strerror (saved_errno));
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Read one line from the command input stream `instream' into a local
@@ -1224,7 +1143,8 @@ gdb_safe_append_history (void)
    as the user has requested.  */
 
 char *
-command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
+command_line_input (const char *prompt_arg, int repeat,
+                   const char *annotation_suffix)
 {
   static struct buffer cmd_line_buffer;
   static int cmd_line_buffer_initialized;
@@ -1318,6 +1238,9 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
       if (cmd != NULL)
        break;
 
+      /* Got partial input.  I.e., got a line that ends with a
+        continuation character (backslash).  Suppress printing the
+        prompt again.  */
       prompt = NULL;
     }
 
@@ -1342,7 +1265,7 @@ print_gdb_version (struct ui_file *stream)
   /* Second line is a copyright notice.  */
 
   fprintf_filtered (stream,
-                   "Copyright (C) 2016 Free Software Foundation, Inc.\n");
+                   "Copyright (C) 2017 Free Software Foundation, Inc.\n");
 
   /* Following the copyright is a brief statement that the program is
      free software, that users are free to copy and change it on
@@ -1575,29 +1498,18 @@ print_inferior_quit_action (struct inferior *inf, void *arg)
 int
 quit_confirm (void)
 {
-  struct ui_file *stb;
-  struct cleanup *old_chain;
-  char *str;
-  int qr;
-
   /* Don't even ask if we're only debugging a core file inferior.  */
   if (!have_live_inferiors ())
     return 1;
 
   /* Build the query string as a single string.  */
-  stb = mem_fileopen ();
-  old_chain = make_cleanup_ui_file_delete (stb);
-
-  fprintf_filtered (stb, _("A debugging session is active.\n\n"));
-  iterate_over_inferiors (print_inferior_quit_action, stb);
-  fprintf_filtered (stb, _("\nQuit anyway? "));
+  string_file stb;
 
-  str = ui_file_xstrdup (stb, NULL);
-  make_cleanup (xfree, str);
+  stb.puts (_("A debugging session is active.\n\n"));
+  iterate_over_inferiors (print_inferior_quit_action, &stb);
+  stb.puts (_("\nQuit anyway? "));
 
-  qr = query ("%s", str);
-  do_cleanups (old_chain);
-  return qr;
+  return query ("%s", stb.c_str ());
 }
 
 /* Prepare to exit GDB cleanly by undoing any changes made to the
@@ -1608,7 +1520,7 @@ undo_terminal_modifications_before_exit (void)
 {
   struct ui *saved_top_level = current_ui;
 
-  target_terminal_ours ();
+  target_terminal::ours ();
 
   current_ui = main_ui;
 
@@ -1838,7 +1750,7 @@ set_history_size_command (char *args, int from_tty, struct cmd_list_element *c)
 }
 
 void
-set_history (char *args, int from_tty)
+set_history (const char *args, int from_tty)
 {
   printf_unfiltered (_("\"set history\" must be followed "
                       "by the name of a history subcommand.\n"));
@@ -1846,7 +1758,7 @@ set_history (char *args, int from_tty)
 }
 
 void
-show_history (char *args, int from_tty)
+show_history (const char *args, int from_tty)
 {
   cmd_show_list (showhistlist, from_tty, "");
 }
@@ -2037,8 +1949,8 @@ init_main (void)
 
   /* Setup important stuff for command line editing.  */
   rl_completion_word_break_hook = gdb_completion_word_break_characters;
-  rl_completion_entry_function = readline_line_completion_function;
-  rl_completer_word_break_characters = default_word_break_characters ();
+  rl_attempted_completion_function = gdb_rl_attempted_completion_function;
+  set_rl_completer_word_break_characters (default_word_break_characters ());
   rl_completer_quote_characters = get_gdb_completer_quote_characters ();
   rl_completion_display_matches_hook = cli_display_match_list;
   rl_readline_name = "gdb";
This page took 0.031336 seconds and 4 git commands to generate.