2007-06-18 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / cli / cli-script.c
index ee986d11c72eaf43af568fadc28ecbb785438fbb..ad64a4a65b18e8b83e4b15dd364b7aa0401e86e7 100644 (file)
@@ -1,8 +1,8 @@
 /* GDB CLI command scripting.
 
-   Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free
-   Software Foundation, Inc.
+   Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -30,6 +30,7 @@
 #include "gdb_string.h"
 #include "exceptions.h"
 #include "top.h"
+#include "breakpoint.h"
 #include "cli/cli-cmds.h"
 #include "cli/cli-decode.h"
 #include "cli/cli-script.h"
@@ -46,14 +47,23 @@ static struct cleanup * setup_user_args (char *p);
 
 static void validate_comname (char *);
 
-/* Level of control structure.  */
+/* Level of control structure when reading.  */
 static int control_level;
 
+/* Level of control structure when executing.  */
+static int command_nest_depth = 1;
+
+/* This is to prevent certain commands being printed twice.  */
+static int suppress_next_print_command_trace = 0;
+
 /* Structure for arguments to user defined functions.  */
 #define MAXUSERARGS 10
 struct user_args
   {
     struct user_args *next;
+    /* It is necessary to store a malloced copy of the command line to
+       ensure that the arguments are not overwritten before they are used.  */
+    char *command;
     struct
       {
        char *arg;
@@ -73,7 +83,7 @@ build_command_line (enum command_control_type type, char *args)
 {
   struct command_line *cmd;
 
-  if (args == NULL)
+  if (args == NULL && (type == if_control || type == while_control))
     error (_("if/while commands require arguments."));
 
   cmd = (struct command_line *) xmalloc (sizeof (struct command_line));
@@ -106,7 +116,7 @@ get_command_line (enum command_control_type type, char *arg)
   /* Read in the body of this command.  */
   if (recurse_read_control_structure (cmd) == invalid_control)
     {
-      warning (_("Error reading in control structure."));
+      warning (_("Error reading in canned sequence of commands."));
       do_cleanups (old_chain);
       return NULL;
     }
@@ -198,6 +208,23 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
          continue;
        }
 
+      /* A commands command.  Print the breakpoint commands and continue.  */
+      if (list->control_type == commands_control)
+       {
+         if (*(list->line))
+           ui_out_field_fmt (uiout, NULL, "commands %s", list->line);
+         else
+           ui_out_field_string (uiout, NULL, "commands");
+         ui_out_text (uiout, "\n");
+         print_command_lines (uiout, *list->body_list, depth + 1);
+         if (depth)
+           ui_out_spaces (uiout, 2 * depth);
+         ui_out_field_string (uiout, NULL, "end");
+         ui_out_text (uiout, "\n");
+         list = list->next;
+         continue;
+       }
+
       /* ignore illegal command type and try next */
       list = list->next;
     }                          /* while (list) */
@@ -241,9 +268,9 @@ static void
 do_restore_user_call_depth (void * call_depth)
 {      
   int * depth = call_depth;
-  /* We will be returning_to_top_level() at this point, so we want to
-     reset our depth. */
-  (*depth) = 0;
+  (*depth)--;
+  if ((*depth) == 0)
+    in_user_command = 0;
 }
 
 
@@ -266,25 +293,70 @@ execute_user_command (struct cmd_list_element *c, char *args)
   if (++user_call_depth > max_user_call_depth)
     error (_("Max user call depth exceeded -- command aborted."));
 
-  old_chain = make_cleanup (do_restore_user_call_depth, &user_call_depth);
+  make_cleanup (do_restore_user_call_depth, &user_call_depth);
 
   /* Set the instream to 0, indicating execution of a
      user-defined function.  */
-  old_chain = make_cleanup (do_restore_instream_cleanup, instream);
+  make_cleanup (do_restore_instream_cleanup, instream);
   instream = (FILE *) 0;
+
+  /* Also set the global in_user_command, so that NULL instream is
+     not confused with Insight.  */
+  in_user_command = 1;
+
+  command_nest_depth++;
   while (cmdlines)
     {
       ret = execute_control_command (cmdlines);
       if (ret != simple_control && ret != break_control)
        {
-         warning (_("Error in control structure."));
+         warning (_("Error executing canned sequence of commands."));
          break;
        }
       cmdlines = cmdlines->next;
     }
+  command_nest_depth--;
   do_cleanups (old_chain);
+}
+
+/* This function is called every time GDB prints a prompt.
+   It ensures that errors and the like to not confuse the command tracing.  */
+
+void
+reset_command_nest_depth (void)
+{
+  command_nest_depth = 1;
+
+  /* Just in case.  */
+  suppress_next_print_command_trace = 0;
+}
+
+/* Print the command, prefixed with '+' to represent the call depth.
+   This is slightly complicated because this function may be called
+   from execute_command and execute_control_command.  Unfortunately
+   execute_command also prints the top level control commands.
+   In these cases execute_command will call execute_control_command
+   via while_command or if_command.  Inner levels of 'if' and 'while'
+   are dealt with directly.  Therefore we can use these functions
+   to determine whether the command has been printed already or not.  */
+void
+print_command_trace (const char *cmd)
+{
+  int i;
+
+  if (suppress_next_print_command_trace)
+    {
+      suppress_next_print_command_trace = 0;
+      return;
+    }
+
+  if (!source_verbose && !trace_commands)
+    return;
 
-  user_call_depth--;
+  for (i=0; i < command_nest_depth; i++)
+    printf_filtered ("+");
+
+  printf_filtered ("%s\n", cmd);
 }
 
 enum command_control_type
@@ -316,7 +388,16 @@ execute_control_command (struct command_line *cmd)
       break;
 
     case continue_control:
+      print_command_trace ("loop_continue");
+
+      /* Return for "continue", and "break" so we can either
+         continue the loop at the top, or break out.  */
+      ret = cmd->control_type;
+      break;
+
     case break_control:
+      print_command_trace ("loop_break");
+
       /* Return for "continue", and "break" so we can either
          continue the loop at the top, or break out.  */
       ret = cmd->control_type;
@@ -324,6 +405,10 @@ execute_control_command (struct command_line *cmd)
 
     case while_control:
       {
+       char *buffer = alloca (strlen (cmd->line) + 7);
+       sprintf (buffer, "while %s", cmd->line);
+       print_command_trace (buffer);
+
        /* Parse the loop control expression for the while statement.  */
        new_line = insert_args (cmd->line);
        if (!new_line)
@@ -356,7 +441,9 @@ execute_control_command (struct command_line *cmd)
            current = *cmd->body_list;
            while (current)
              {
+               command_nest_depth++;
                ret = execute_control_command (current);
+               command_nest_depth--;
 
                /* If we got an error, or a "break" command, then stop
                   looping.  */
@@ -385,6 +472,10 @@ execute_control_command (struct command_line *cmd)
 
     case if_control:
       {
+       char *buffer = alloca (strlen (cmd->line) + 4);
+       sprintf (buffer, "if %s", cmd->line);
+       print_command_trace (buffer);
+
        new_line = insert_args (cmd->line);
        if (!new_line)
          break;
@@ -411,7 +502,9 @@ execute_control_command (struct command_line *cmd)
        /* Execute commands in the given arm.  */
        while (current)
          {
+           command_nest_depth++;
            ret = execute_control_command (current);
+           command_nest_depth--;
 
            /* If we got an error, get out.  */
            if (ret != simple_control)
@@ -423,9 +516,20 @@ execute_control_command (struct command_line *cmd)
 
        break;
       }
+    case commands_control:
+      {
+       /* Breakpoint commands list, record the commands in the breakpoint's
+          command list and return.  */
+       new_line = insert_args (cmd->line);
+       if (!new_line)
+         break;
+       make_cleanup (free_current_contents, &new_line);
+       ret = commands_from_control_command (new_line, cmd);
+       break;
+      }
 
     default:
-      warning (_("Invalid control type in command structure."));
+      warning (_("Invalid control type in canned commands structure."));
       break;
     }
 
@@ -448,6 +552,7 @@ while_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
+  suppress_next_print_command_trace = 1;
   execute_control_command (command);
   free_command_lines (&command);
 }
@@ -466,6 +571,7 @@ if_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
+  suppress_next_print_command_trace = 1;
   execute_control_command (command);
   free_command_lines (&command);
 }
@@ -480,6 +586,7 @@ arg_cleanup (void *ignore)
                    _("arg_cleanup called with no user args.\n"));
 
   user_args = user_args->next;
+  xfree (oargs->command);
   xfree (oargs);
 }
 
@@ -504,6 +611,8 @@ setup_user_args (char *p)
   if (p == NULL)
     return old_chain;
 
+  user_args->command = p = xstrdup (p);
+
   while (*p)
     {
       char *start_arg;
@@ -590,6 +699,11 @@ insert_args (char *line)
   char *p, *save_line, *new_line;
   unsigned len, i;
 
+  /* If we are not in a user-defined function, treat $argc, $arg0, et
+     cetera as normal convenience variables.  */
+  if (user_args == NULL)
+    return xstrdup (line);
+
   /* First we need to know how much memory to allocate for the new line.  */
   save_line = line;
   len = 0;
@@ -687,6 +801,7 @@ realloc_body_list (struct command_line *command, int new_length)
     xmalloc (sizeof (struct command_line *) * new_length);
 
   memcpy (body_list, command->body_list, sizeof (struct command_line *) * n);
+  memset (body_list + n, 0, sizeof (struct command_line *) * (new_length - n));
 
   xfree (command->body_list);
   command->body_list = body_list;
@@ -763,6 +878,14 @@ read_next_line (struct command_line **command)
         first_arg++;
       *command = build_command_line (if_control, first_arg);
     }
+  else if (p1 - p >= 8 && !strncmp (p, "commands", 8))
+    {
+      char *first_arg;
+      first_arg = p + 8;
+      while (first_arg < p1 && isspace (*first_arg))
+        first_arg++;
+      *command = build_command_line (commands_control, first_arg);
+    }
   else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
     {
       *command = (struct command_line *)
@@ -838,9 +961,10 @@ recurse_read_control_structure (struct command_line *current_cmd)
       if (val == end_command)
        {
          if (current_cmd->control_type == while_control
-             || current_cmd->control_type == if_control)
+             || current_cmd->control_type == if_control
+             || current_cmd->control_type == commands_control)
            {
-             /* Success reading an entire control structure.  */
+             /* Success reading an entire canned sequence of commands.  */
              ret = simple_control;
              break;
            }
@@ -888,7 +1012,8 @@ recurse_read_control_structure (struct command_line *current_cmd)
       /* If the latest line is another control structure, then recurse
          on it.  */
       if (next->control_type == while_control
-         || next->control_type == if_control)
+         || next->control_type == if_control
+         || next->control_type == commands_control)
        {
          control_level++;
          ret = recurse_read_control_structure (next);
@@ -920,15 +1045,19 @@ read_command_lines (char *prompt_arg, int from_tty)
   enum misc_command_type val;
 
   control_level = 0;
-  if (deprecated_readline_begin_hook)
-    {
-      /* Note - intentional to merge messages with no newline */
-      (*deprecated_readline_begin_hook) ("%s  %s\n", prompt_arg, END_MESSAGE);
-    }
-  else if (from_tty && input_from_terminal_p ())
+
+  if (from_tty && input_from_terminal_p ())
     {
-      printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE);
-      gdb_flush (gdb_stdout);
+      if (deprecated_readline_begin_hook)
+       {
+         /* Note - intentional to merge messages with no newline */
+         (*deprecated_readline_begin_hook) ("%s  %s\n", prompt_arg, END_MESSAGE);
+       }
+      else
+       {
+         printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE);
+         gdb_flush (gdb_stdout);
+       }
     }
 
   head = tail = NULL;
@@ -955,7 +1084,8 @@ read_command_lines (char *prompt_arg, int from_tty)
        }
 
       if (next->control_type == while_control
-         || next->control_type == if_control)
+         || next->control_type == if_control
+         || next->control_type == commands_control)
        {
          control_level++;
          ret = recurse_read_control_structure (next);
@@ -989,7 +1119,7 @@ read_command_lines (char *prompt_arg, int from_tty)
        do_cleanups (old_chain);
     }
 
-  if (deprecated_readline_end_hook)
+  if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
     {
       (*deprecated_readline_end_hook) ();
     }
This page took 0.027769 seconds and 4 git commands to generate.