PR gdb/7912:
[platform/upstream/binutils.git] / gdb / cli / cli-script.c
index 5903015..3b24799 100644 (file)
@@ -1,8 +1,6 @@
 /* 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, 2006, 2007, 2008,
-   2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -35,6 +33,7 @@
 #include "gdb_assert.h"
 
 #include "python/python.h"
+#include "interps.h"
 
 /* Prototypes for local functions.  */
 
@@ -315,15 +314,15 @@ execute_user_command (struct cmd_list_element *c, char *args)
   struct cleanup *old_chain;
   enum command_control_type ret;
   static int user_call_depth = 0;
-  extern int max_user_call_depth;
-
-  old_chain = setup_user_args (args);
+  extern unsigned int max_user_call_depth;
 
   cmdlines = c->user_commands;
   if (cmdlines == 0)
     /* Null command */
     return;
 
+  old_chain = setup_user_args (args);
+
   if (++user_call_depth > max_user_call_depth)
     error (_("Max user call depth exceeded -- command aborted."));
 
@@ -338,6 +337,9 @@ execute_user_command (struct cmd_list_element *c, char *args)
      not confused with Insight.  */
   in_user_command = 1;
 
+  make_cleanup_restore_integer (&interpreter_async);
+  interpreter_async = 0;
+
   command_nest_depth++;
   while (cmdlines)
     {
@@ -439,9 +441,10 @@ execute_control_command (struct command_line *cmd)
 
     case while_control:
       {
-       char *buffer = alloca (strlen (cmd->line) + 7);
+       int len = strlen (cmd->line) + 7;
+       char *buffer = alloca (len);
 
-       sprintf (buffer, "while %s", cmd->line);
+       xsnprintf (buffer, len, "while %s", cmd->line);
        print_command_trace (buffer);
 
        /* Parse the loop control expression for the while statement.  */
@@ -507,9 +510,10 @@ execute_control_command (struct command_line *cmd)
 
     case if_control:
       {
-       char *buffer = alloca (strlen (cmd->line) + 4);
+       int len = strlen (cmd->line) + 4;
+       char *buffer = alloca (len);
 
-       sprintf (buffer, "if %s", cmd->line);
+       xsnprintf (buffer, len, "if %s", cmd->line);
        print_command_trace (buffer);
 
        new_line = insert_args (cmd->line);
@@ -594,10 +598,11 @@ execute_control_command_untraced (struct command_line *cmd)
 /* "while" command support.  Executes a body of statements while the
    loop condition is nonzero.  */
 
-void
+static void
 while_command (char *arg, int from_tty)
 {
   struct command_line *command = NULL;
+  struct cleanup *old_chain;
 
   control_level = 1;
   command = get_command_line (while_control, arg);
@@ -605,17 +610,23 @@ while_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
+  old_chain = make_cleanup_restore_integer (&interpreter_async);
+  interpreter_async = 0;
+
   execute_control_command_untraced (command);
   free_command_lines (&command);
+
+  do_cleanups (old_chain);
 }
 
 /* "if" command support.  Execute either the true or false arm depending
    on the value of the if conditional.  */
 
-void
+static void
 if_command (char *arg, int from_tty)
 {
   struct command_line *command = NULL;
+  struct cleanup *old_chain;
 
   control_level = 1;
   command = get_command_line (if_control, arg);
@@ -623,8 +634,13 @@ if_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
+  old_chain = make_cleanup_restore_integer (&interpreter_async);
+  interpreter_async = 0;
+
   execute_control_command_untraced (command);
   free_command_lines (&command);
+
+  do_cleanups (old_chain);
 }
 
 /* Cleanup */
@@ -1164,6 +1180,12 @@ recurse_read_control_structure (char * (*read_next_line_func) (void),
   return ret;
 }
 
+static void
+restore_interp (void *arg)
+{
+  interp_set_temp (interp_name ((struct interp *)arg));
+}
+
 /* Read lines from the input stream and accumulate them in a chain of
    struct command_line's, which is then returned.  For input from a
    terminal, the special command "end" is used to mark the end of the
@@ -1196,8 +1218,21 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands,
        }
     }
 
-  head = read_command_lines_1 (read_next_line, parse_commands,
-                              validator, closure);
+
+  /* Reading commands assumes the CLI behavior, so temporarily
+     override the current interpreter with CLI.  */
+  if (current_interp_named_p (INTERP_CONSOLE))
+    head = read_command_lines_1 (read_next_line, parse_commands,
+                                validator, closure);
+  else
+    {
+      struct interp *old_interp = interp_set_temp (INTERP_CONSOLE);
+      struct cleanup *old_chain = make_cleanup (restore_interp, old_interp);
+
+      head = read_command_lines_1 (read_next_line, parse_commands,
+                                  validator, closure);
+      do_cleanups (old_chain);
+    }
 
   if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
     {
@@ -1381,7 +1416,8 @@ validate_comname (char **comname)
   if (last_word != *comname)
     {
       struct cmd_list_element *c;
-      char saved_char, *tem = *comname;
+      char saved_char;
+      const char *tem = *comname;
 
       /* Separate the prefix and the command.  */
       saved_char = last_word[-1];
@@ -1413,7 +1449,7 @@ user_defined_command (char *ignore, int from_tty)
 {
 }
 
-void
+static void
 define_command (char *comname, int from_tty)
 {
 #define MAX_TMPBUF 128   
@@ -1426,6 +1462,7 @@ define_command (char *comname, int from_tty)
   struct command_line *cmds;
   struct cmd_list_element *c, *newc, *hookc = 0, **list;
   char *tem, *comfull;
+  const char *tem_c;
   char tmpbuf[MAX_TMPBUF];
   int  hook_type      = CMD_NO_HOOK;
   int  hook_name_size = 0;
@@ -1439,8 +1476,8 @@ define_command (char *comname, int from_tty)
   list = validate_comname (&comname);
 
   /* Look it up, and verify that we got an exact match.  */
-  tem = comname;
-  c = lookup_cmd (&tem, *list, "", -1, 1);
+  tem_c = comname;
+  c = lookup_cmd (&tem_c, *list, "", -1, 1);
   if (c && strcmp (comname, c->name) != 0)
     c = 0;
 
@@ -1474,8 +1511,8 @@ define_command (char *comname, int from_tty)
   if (hook_type != CMD_NO_HOOK)
     {
       /* Look up cmd it hooks, and verify that we got an exact match.  */
-      tem = comname + hook_name_size;
-      hookc = lookup_cmd (&tem, *list, "", -1, 0);
+      tem_c = comname + hook_name_size;
+      hookc = lookup_cmd (&tem_c, *list, "", -1, 0);
       if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0)
        hookc = 0;
       if (!hookc)
@@ -1496,7 +1533,8 @@ define_command (char *comname, int from_tty)
     if (isupper (*tem))
       *tem = tolower (*tem);
 
-  sprintf (tmpbuf, "Type commands for definition of \"%s\".", comfull);
+  xsnprintf (tmpbuf, sizeof (tmpbuf),
+            "Type commands for definition of \"%s\".", comfull);
   cmds = read_command_lines (tmpbuf, from_tty, 1, 0, 0);
 
   if (c && c->class == class_user)
@@ -1529,12 +1567,13 @@ define_command (char *comname, int from_tty)
     }
 }
 
-void
+static void
 document_command (char *comname, int from_tty)
 {
   struct command_line *doclines;
   struct cmd_list_element *c, **list;
-  char *tem, *comfull;
+  const char *tem;
+  char *comfull;
   char tmpbuf[128];
 
   comfull = comname;
@@ -1546,7 +1585,8 @@ document_command (char *comname, int from_tty)
   if (c->class != class_user)
     error (_("Command \"%s\" is built-in."), comfull);
 
-  sprintf (tmpbuf, "Type documentation for \"%s\".", comfull);
+  xsnprintf (tmpbuf, sizeof (tmpbuf), "Type documentation for \"%s\".",
+            comfull);
   doclines = read_command_lines (tmpbuf, from_tty, 0, 0, 0);
 
   if (c->doc)
@@ -1589,19 +1629,6 @@ source_cleanup_lines (void *args)
   source_file_name = p->old_file;
 }
 
-struct wrapped_read_command_file_args
-{
-  FILE *stream;
-};
-
-static void
-wrapped_read_command_file (struct ui_out *uiout, void *data)
-{
-  struct wrapped_read_command_file_args *args = data;
-
-  read_command_file (args->stream);
-}
-
 /* Used to implement source_command.  */
 
 void
@@ -1613,11 +1640,9 @@ script_from_file (FILE *stream, const char *file)
   if (stream == NULL)
     internal_error (__FILE__, __LINE__, _("called with NULL file pointer!"));
 
-  old_cleanups = make_cleanup_fclose (stream);
-
   old_lines.old_line = source_line_number;
   old_lines.old_file = source_file_name;
-  make_cleanup (source_cleanup_lines, &old_lines);
+  old_cleanups = make_cleanup (source_cleanup_lines, &old_lines);
   source_line_number = 0;
   source_file_name = file;
   /* This will get set every time we read a line.  So it won't stay ""
@@ -1625,12 +1650,12 @@ script_from_file (FILE *stream, const char *file)
   error_pre_print = "";
 
   {
-    struct gdb_exception e;
-    struct wrapped_read_command_file_args args;
+    volatile struct gdb_exception e;
 
-    args.stream = stream;
-    e = catch_exception (uiout, wrapped_read_command_file, &args,
-                        RETURN_MASK_ERROR);
+    TRY_CATCH (e, RETURN_MASK_ERROR)
+      {
+       read_command_file (stream);
+      }
     switch (e.reason)
       {
       case 0:
@@ -1654,7 +1679,7 @@ script_from_file (FILE *stream, const char *file)
    (recursively).  PREFIX and NAME combined are the name of the
    current command.  */
 void
-show_user_1 (struct cmd_list_element *c, char *prefix, char *name,
+show_user_1 (struct cmd_list_element *c, const char *prefix, const char *name,
             struct ui_file *stream)
 {
   struct command_line *cmdlines;
@@ -1674,7 +1699,38 @@ show_user_1 (struct cmd_list_element *c, char *prefix, char *name,
     return;
   fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name);
 
-  print_command_lines (uiout, cmdlines, 1);
+  print_command_lines (current_uiout, cmdlines, 1);
   fputs_filtered ("\n", stream);
 }
 
+\f
+
+initialize_file_ftype _initialize_cli_script;
+
+void
+_initialize_cli_script (void)
+{
+  add_com ("document", class_support, document_command, _("\
+Document a user-defined command.\n\
+Give command name as argument.  Give documentation on following lines.\n\
+End with a line of just \"end\"."));
+  add_com ("define", class_support, define_command, _("\
+Define a new command name.  Command name is argument.\n\
+Definition appears on following lines, one command per line.\n\
+End with a line of just \"end\".\n\
+Use the \"document\" command to give documentation for the new command.\n\
+Commands defined in this way may have up to ten arguments."));
+
+  add_com ("while", class_support, while_command, _("\
+Execute nested commands WHILE the conditional expression is non zero.\n\
+The conditional expression must follow the word `while' and must in turn be\n\
+followed by a new line.  The nested commands must be entered one per line,\n\
+and should be terminated by the word `end'."));
+
+  add_com ("if", class_support, if_command, _("\
+Execute nested commands once IF the conditional expression is non zero.\n\
+The conditional expression must follow the word `if' and must in turn be\n\
+followed by a new line.  The nested commands must be entered one per line,\n\
+and should be terminated by the word 'else' or `end'.  If an else clause\n\
+is used, the same rules apply to its nested commands as to the first ones."));
+}