This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] command trace / source verbose mode


Here is a new version of the patch.

I have changed the command from 'set debug commandtrace' to 'set trace-commands' and adjusted the variable name to match.

The source_verbose is now reset with a cleanup.

The -v option is only valid before the filename.

The -v option no longer applies to the --command option. This change has meant that I have had to stop main.c using source_command() and invent a new function, source_script(), for it to use.

The strings are now surrounded by _(...)

You do this in a couple places, at least here and for control_level.
Given the way GDB handles errors with longjmp, this isn't safe.

control_level is not a problem. It is always re-initialised whenever an 'if', 'while', or user defined command is encountered. The new code only uses it to prevent the same command getting printed more than once. This is necessary due to the way the execute_command() and execute_control_command() interact.


  Another alternative would be to use the time-honored shell
syntax for this: prefix with plusses up to the nesting level, like sh
-x.  What do you think?

I have considered this feature in some detail. There is, of course, nothing to stop us using any string or symbol we like, but the nesting level is tricky. As it stands the code does not really know how deep it is. The control_level is not the real depth - it only really says how deep it is from the last simple command such as 'source' or a user-defined command, as opposed to control commands such 'if'.


If you really want to show the depth then some more thought will be required. The depth will have to be calculated properly somehow and it will have to be exposed to top.c which prints all the top level commands and nested simple commands.

What do you think?

:ADDPATCH CLI:

Andrew Stubbs
2006-07-07  Andrew Stubbs  <andrew.stubbs@st.com>

	* cli/cli-cmds.c (source_verbose, trace_commands): New variables.
	(source_script): New function.
	(source_verbose_cleanup): New function.
	(source_command): Move old contents to source_script().
	Make function static. Parse -v option and call source_script.
	(init_cli_cmds): Update source command help.
	Add 'set trace_commands' command.
	* cli/cli-script.c (execute_user_command): Set control_level.
	(execute_control_command): Add instrumentation for the source_verbose
	and trace_command modes.
	* top.c (execute_command): Likewise.
	* cli/cli-cmds.h (source_verbose, trace_commands): New extern variables.
	(source_command): Change to source_script.
	* main.c (captued_main): Use source_script instead of source_command.
	* top.h (source_command): Change to source_script.

docs/
	* gdb.texinfo (Optional warnings and messages): Add
	'set/show trace-commands'.
	(Command files): Add '-v' to source command.

testsuite/
	*gdb.base/help.exp: Update 'help source' message.

Index: src/gdb/cli/cli-cmds.c
===================================================================
--- src.orig/gdb/cli/cli-cmds.c	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/cli/cli-cmds.c	2006-07-07 16:30:26.000000000 +0100
@@ -173,6 +173,11 @@ struct cmd_list_element *showdebuglist;
 struct cmd_list_element *setchecklist;
 
 struct cmd_list_element *showchecklist;
+
+/* Command tracing state.  */
+
+int source_verbose = 0;
+int trace_commands = 0;
 
 /* Utility used everywhere when at least one argument is needed and
    none is supplied. */
@@ -424,15 +429,14 @@ cd_command (char *dir, int from_tty)
 }
 
 void
-source_command (char *args, int from_tty)
+source_script (char *file, int from_tty)
 {
   FILE *stream;
   struct cleanup *old_cleanups;
-  char *file = args;
   char *full_pathname = NULL;
   int fd;
 
-  if (file == NULL)
+  if (file == NULL || strlen (file) == 0)
     {
       error (_("source command requires pathname of file to source."));
     }
@@ -465,6 +469,48 @@ source_command (char *args, int from_tty
   do_cleanups (old_cleanups);
 }
 
+/* Return the source_verbose global variable to its previous state
+   on exit from the source command, by whatever means.  */
+static void
+source_verbose_cleanup (void *old_value)
+{
+  source_verbose = (int) old_value;
+}
+
+static void
+source_command (char *args, int from_tty)
+{
+  struct cleanup *old_cleanups;
+  char *file = args;
+
+  old_cleanups = make_cleanup (source_verbose_cleanup, (void *)source_verbose);
+
+  /* -v causes the source command to run in verbose mode.
+     We still have to be able to handle filenames with spaces in a
+     backward compatible way, so buildargv is not appropriate.  */
+
+  if (args)
+    {
+      /* Make sure leading white space does not break the comparisons.  */
+      while (isspace(args[0]))
+	args++;
+
+      /* Is -v the first thing in the string?  */
+      if (args[0] == '-' && args[1] == 'v' && isspace (args[2]))
+	{
+	  source_verbose = 1;
+
+	  /* Trim -v and whitespace from the filename.  */
+	  file = &args[3];
+	  while (isspace (file[0]))
+	    file++;
+	}
+    }
+
+  return source_script (file, from_tty);
+}
+
+
 static void
 echo_command (char *text, int from_tty)
 {
@@ -1183,7 +1229,8 @@ Commands defined in this way may have up
   source_help_text = xstrprintf (_("\
 Read commands from a file named FILE.\n\
 Note that the file \"%s\" is read automatically in this way\n\
-when gdb is started."), gdbinit);
+when gdb is started.\n\
+Use -v to see the name of the commands issued."), gdbinit);
   c = add_cmd ("source", class_support, source_command,
 	       source_help_text, &cmdlist);
   set_cmd_completer (c, filename_completer);
@@ -1364,4 +1411,12 @@ Show the max call depth for user-defined
 			   NULL,
 			   show_max_user_call_depth,
 			   &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("trace-commands", no_class, &trace_commands, _("\
+Set tracing of GDB CLI commands."), _("\
+Show state of GDB CLI command tracing."), _("\
+When 'on', each command is displayed as it is executed."),
+			   NULL,
+			   NULL,
+			   &setlist, &showlist);
 }
Index: src/gdb/cli/cli-script.c
===================================================================
--- src.orig/gdb/cli/cli-script.c	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/cli/cli-script.c	2006-07-07 16:17:55.000000000 +0100
@@ -280,6 +280,10 @@ execute_user_command (struct cmd_list_el
      not confused with Insight.  */
   in_user_command = 1;
 
+  /* Set the control level to ensure that all control commands are
+     printed when trace_commands is set.  */
+  control_level = 2;
+
   while (cmdlines)
     {
       ret = execute_control_command (cmdlines);
@@ -322,7 +326,18 @@ execute_control_command (struct command_
       break;
 
     case continue_control:
+      if (source_verbose || trace_commands)
+	printf_unfiltered (_("Command issued: loop_continue %s\n"), cmd->line);
+
+      /* 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:
+      if (source_verbose || trace_commands)
+	printf_unfiltered (_("Command issued: loop_break %s\n"), cmd->line);
+
       /* Return for "continue", and "break" so we can either
          continue the loop at the top, or break out.  */
       ret = cmd->control_type;
@@ -330,6 +345,10 @@ execute_control_command (struct command_
 
     case while_control:
       {
+	if ((source_verbose || trace_commands)
+	    && control_level > 1) /* Top level printed in execute_command().  */
+	  printf_unfiltered (_("Command issued: while %s\n"), cmd->line);
+
 	/* Parse the loop control expression for the while statement.  */
 	new_line = insert_args (cmd->line);
 	if (!new_line)
@@ -362,7 +381,9 @@ execute_control_command (struct command_
 	    current = *cmd->body_list;
 	    while (current)
 	      {
+		control_level++;
 		ret = execute_control_command (current);
+		control_level--;
 
 		/* If we got an error, or a "break" command, then stop
 		   looping.  */
@@ -391,6 +412,10 @@ execute_control_command (struct command_
 
     case if_control:
       {
+	if ((source_verbose || trace_commands)
+	    && control_level > 1) /* Top level printed in execute_command().  */
+	  printf_unfiltered (_("Command issued: if %s\n"), cmd->line);
+
 	new_line = insert_args (cmd->line);
 	if (!new_line)
 	  break;
@@ -417,7 +442,9 @@ execute_control_command (struct command_
 	/* Execute commands in the given arm.  */
 	while (current)
 	  {
+	    control_level++;
 	    ret = execute_control_command (current);
+	    control_level--;
 
 	    /* If we got an error, get out.  */
 	    if (ret != simple_control)
Index: src/gdb/top.c
===================================================================
--- src.orig/gdb/top.c	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/top.c	2006-07-07 16:17:55.000000000 +0100
@@ -395,6 +395,11 @@ execute_command (char *p, int from_tty)
 
   while (*p == ' ' || *p == '\t')
     p++;
+
+  if ((source_verbose || trace_commands)
+      && strlen (p) > 0)
+    printf_unfiltered (_("Command issued: %s\n"), p);
+
   if (*p)
     {
       char *arg;
Index: src/gdb/testsuite/gdb.base/help.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.base/help.exp	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/testsuite/gdb.base/help.exp	2006-07-07 16:17:55.000000000 +0100
@@ -533,7 +533,7 @@ gdb_test "help stepi" "Step one instruct
 gdb_test "help signal" "Continue program giving it signal.*" "help signal"
 # test help source
 # vxgdb reads .vxgdbinit
-gdb_test "help source" "Read commands from a file named FILE\.\[\r\n\]+Note that the file \"\[^\"\]*\" is read automatically in this way\[\r\n\]+when gdb is started\." "help source"
+gdb_test "help source" "Read commands from a file named FILE\.\[\r\n\]+Note that the file \"\[^\"\]*\" is read automatically in this way\[\r\n\]+when gdb is started\.\[\r\n\]+Use -v to see the name of the commands issued\." "help source"
 # test help stack
 gdb_test "help stack" "Examining the stack\..*\[\r\n\]+When the program being debugged stops, gdb selects the innermost frame\.\[\r\n\]+The commands below can be used to select other frames by number or address\.\[\r\n\]+List of commands:\[\r\n\]+backtrace -- Print backtrace of all stack frames\[\r\n\]+bt -- Print backtrace of all stack frames\[\r\n\]+down -- Select and print stack frame called by this one\[\r\n\]+frame -- Select and print a stack frame\[\r\n\]+return -- Make selected stack frame return to its caller\[\r\n\]+select-frame -- Select a stack frame without printing anything\[\r\n\]+up -- Select and print stack frame that called this one\[\r\n\]+Type \"help\" followed by command name for full documentation\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\." "help stack"
 # test help status
Index: src/gdb/cli/cli-cmds.h
===================================================================
--- src.orig/gdb/cli/cli-cmds.h	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/cli/cli-cmds.h	2006-07-07 16:34:16.000000000 +0100
@@ -115,11 +115,16 @@ extern void cd_command (char *, int);
 
 extern void quit_command (char *, int);
 
-extern void source_command (char *, int);
+extern void source_script (char *, int);
 
 /* Used everywhere whenever at least one parameter is required and
   none is specified. */
 
 extern NORETURN void error_no_arg (char *) ATTR_NORETURN;
 
+/* Command tracing state.  */
+
+extern int source_verbose;
+extern int trace_commands;
+
 #endif /* !defined (CLI_CMDS_H) */
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2006-07-07 16:17:17.000000000 +0100
+++ src/gdb/doc/gdb.texinfo	2006-07-07 16:17:55.000000000 +0100
@@ -15999,6 +15999,20 @@ Displays state of confirmation requests.
 
 @end table
 
+If you need to debug user-defined commands or sourced files you may find it
+useful to enable command tracing.  In this mode each command will be printed
+as it is executed, prefixed with @samp{Command issued:}.
+
+@table @code
+@kindex set debug commandtrace
+@item set debug commandtrace on
+Enable command tracing.
+@item set debug commandtrace off
+Disable command tracing.
+@item show debug commandtrace
+Display the current state of command tracing.
+@end table
+
 @node Debugging Output
 @section Optional messages about internal happenings
 @cindex optional debugging messages
@@ -16347,7 +16361,7 @@ command:
 @table @code
 @kindex source
 @cindex execute commands from a file
-@item source @var{filename}
+@item source [@code{-v}] @var{filename}
 Execute the command file @var{filename}.
 @end table
 
@@ -16360,6 +16374,10 @@ execution of the command file and contro
 @value{GDBN} searches for @var{filename} in the current directory and then
 on the search path (specified with the @samp{directory} command).
 
+If @code{-v}, for verbose mode, is given then each command will
+be displayed as it is executed.  The option must be given before
+@var{filename}, and will be interpreted as part of the filename anywhere else.
+
 Commands that would ask for confirmation if used interactively proceed
 without asking when used in a command file.  Many @value{GDBN} commands that
 normally print messages to say what they are doing omit the messages
Index: src/gdb/main.c
===================================================================
--- src.orig/gdb/main.c	2006-02-21 19:46:48.000000000 +0000
+++ src/gdb/main.c	2006-07-07 16:35:19.000000000 +0100
@@ -643,7 +643,7 @@ extern int gdbtk_test (char *);
 
       if (!inhibit_gdbinit)
 	{
-	  catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL);
+	  catch_command_errors (source_script, homeinit, 0, RETURN_MASK_ALL);
 	}
 
       /* Do stats; no need to do them elsewhere since we'll only
@@ -730,7 +730,7 @@ extern int gdbtk_test (char *);
       || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat)))
     if (!inhibit_gdbinit)
       {
-	catch_command_errors (source_command, gdbinit, 0, RETURN_MASK_ALL);
+	catch_command_errors (source_script, gdbinit, 0, RETURN_MASK_ALL);
       }
 
   for (i = 0; i < ncmd; i++)
@@ -748,12 +748,12 @@ extern int gdbtk_test (char *);
 	    read_command_file (stdin);
 	  else
 #endif
-	    source_command (cmdarg[i], !batch);
+	    source_script (cmdarg[i], !batch);
 	  do_cleanups (ALL_CLEANUPS);
 	}
 #endif
       if (cmdarg[i].type == CMDARG_FILE)
-        catch_command_errors (source_command, cmdarg[i].string,
+        catch_command_errors (source_script, cmdarg[i].string,
 			      !batch, RETURN_MASK_ALL);
       else  /* cmdarg[i].type == CMDARG_COMMAND */
         catch_command_errors (execute_command, cmdarg[i].string,
Index: src/gdb/top.h
===================================================================
--- src.orig/gdb/top.h	2006-03-29 23:53:33.000000000 +0100
+++ src/gdb/top.h	2006-07-07 16:33:50.000000000 +0100
@@ -36,7 +36,7 @@ extern char gdbinit[];
 
 extern void print_gdb_version (struct ui_file *);
 
-extern void source_command (char *, int);
+extern void source_script (char *, int);
 extern void cd_command (char *, int);
 extern void read_command_file (FILE *);
 extern void init_history (void);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]