From 6da95a677b977e132bc936a73b2bb92844b14f32 Mon Sep 17 00:00:00 2001
From: Stan Shebs <shebs@codesourcery.com>
Date: Thu, 31 Dec 2009 17:47:43 +0000
Subject: [PATCH] 	Add new tracepoint action teval. 	* tracepoint.c
 (teval_pseudocommand): New function. 	(validate_actionline): Add teval
 action case. 	(encode_actions): Ditto. 	(_initialize_tracepoint):
 Define teval pseudocommand. 	* NEWS: Mention teval.

	* gdb.texinfo (Tracepoint Actions): Describe teval.

	* gdb.trace/actions.exp: Test teval action.
---
 gdb/ChangeLog                       |  7 +++
 gdb/NEWS                            |  4 ++
 gdb/doc/ChangeLog                   |  4 ++
 gdb/doc/gdb.texinfo                 |  9 ++++
 gdb/testsuite/ChangeLog             |  4 ++
 gdb/testsuite/gdb.trace/actions.exp | 28 ++++++++++
 gdb/tracepoint.c                    | 80 +++++++++++++++++++++++++++++
 7 files changed, 136 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4f538acc807..753fbb0cc0a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2009-12-31  Stan Shebs  <stan@codesourcery.com>
 
+	Add new tracepoint action teval.
+	* tracepoint.c (teval_pseudocommand): New function.
+	(validate_actionline): Add teval action case.
+	(encode_actions): Ditto.
+	(_initialize_tracepoint): Define teval pseudocommand.
+	* NEWS: Mention teval.
+
 	* tracepoint.c (trace_find_command): Error out if trace running.
 	(trace_find_pc_command): Ditto.
 	(trace_find_tracepoint_command): Ditto.
diff --git a/gdb/NEWS b/gdb/NEWS
index eb84ee7e9e7..184c4e64c29 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -97,6 +97,10 @@ info tvariables
 delete tvariable $NAME ...
   Delete one or more trace state variables.
 
+teval EXPR, ...
+  Evaluate the given expressions without collecting anything into the
+  trace buffer. (Valid in tracepoint actions only.)
+
 * New options
 
 set follow-exec-mode new|same
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 7171423258b..6c5bfe77f92 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2009-12-31  Stan Shebs  <stan@codesourcery.com>
+
+	* gdb.texinfo (Tracepoint Actions): Describe teval.
+	
 2009-12-29  Stan Shebs  <stan@codesourcery.com>
 
 	* gdb.texinfo (Tracepoint Actions): Describe default-collect.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 39f0d679240..f7bc686e42e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9626,6 +9626,15 @@ arguments separated by commas: the effect is the same.
 The command @code{info scope} (@pxref{Symbols, info scope}) is
 particularly useful for figuring out what data to collect.
 
+@kindex teval @r{(tracepoints)}
+@item teval @var{expr1}, @var{expr2}, @dots{}
+Evaluate the given expressions when the tracepoint is hit.  This
+command accepts a comma-separated list of expressions.  The results
+are discarded, so this is mainly useful for assigning values to trace
+state variables (@pxref{Trace State Variables}) without adding those
+values to the trace buffer, as would be the case if the @code{collect}
+action were used.
+
 @kindex while-stepping @r{(tracepoints)}
 @item while-stepping @var{n}
 Perform @var{n} single-step traces after the tracepoint, collecting
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 33aee0831c3..10dc1d55eb0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-12-31  Stan Shebs  <stan@codesourcery.com>
+
+	* gdb.trace/actions.exp: Test teval action.
+	
 2009-12-30  Thiago Jung Bauermann  <bauerman@br.ibm.com>
 
 	* gdb.base/watchpoint.exp (test_watchpoint_in_big_blob): New function.
diff --git a/gdb/testsuite/gdb.trace/actions.exp b/gdb/testsuite/gdb.trace/actions.exp
index bb7277f9935..616a656f2f3 100644
--- a/gdb/testsuite/gdb.trace/actions.exp
+++ b/gdb/testsuite/gdb.trace/actions.exp
@@ -212,3 +212,31 @@ gdb_test "set default-collect gdb_char_test, gdb_long_test - 100" \
 gdb_test "show default-collect" \
     "The list of expressions to collect by default is \"gdb_char_test, gdb_long_test - 100\"..*" \
     "5.9b: show default-collect"
+
+# 5.10 teval
+
+gdb_test "tvariable \$tsv" \
+  "Trace state variable \\\$tsv created, with initial value 0." \
+  "Create a trace state variable"
+
+gdb_trace_setactions "5.10a: set teval action for first tracepoint" \
+	"$trcpt1" \
+	"teval gdb_char_test" "^$"
+
+gdb_trace_setactions "5.10a: set teval action for second tracepoint" \
+	"$trcpt2" \
+	"teval \$tsv += 1" "^$"
+
+gdb_test "info tracepoints" \
+    "Num     Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_c_test at .*$srcfile:\[0-9\]+.
+\[\t \]+A\[\t \]+teval gdb_char_test.
+\[\t \]+A\[\t \]+end.
+\[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_asm_test at .*$srcfile:\[0-9\]+.
+\[\t \]+A\[\t \]+teval \\\$tsv \\\+= 1.
+\[\t \]+A\[\t \]+end.
+\[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_recursion_test at .*$srcfile:\[0-9\]+.
+\[\t \]+A\[\t \]+collect gdb_long_test.
+\[\t \]+A\[\t \]+end." \
+		"5.10a: verify teval actions set for two tracepoints"
+
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 26a836d80c7..fd7c1616409 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -525,6 +525,12 @@ collect_pseudocommand (char *args, int from_tty)
   error (_("This command can only be used in a tracepoint actions list."));
 }
 
+static void
+teval_pseudocommand (char *args, int from_tty)
+{
+  error (_("This command can only be used in a tracepoint actions list."));
+}
+
 /* Enter a list of actions for a tracepoint.  */
 static void
 trace_actions_command (char *args, int from_tty)
@@ -761,6 +767,34 @@ validate_actionline (char **line, struct breakpoint *t)
       while (p && *p++ == ',');
       return GENERIC;
     }
+  else if (cmd_cfunc_eq (c, teval_pseudocommand))
+    {
+      struct agent_expr *aexpr;
+
+      do
+	{			/* repeat over a comma-separated list */
+	  QUIT;			/* allow user to bail out with ^C */
+	  while (isspace ((int) *p))
+	    p++;
+
+	  /* Only expressions are allowed for this action.  */
+	  exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1);
+	  old_chain = make_cleanup (free_current_contents, &exp);
+
+	  /* We have something to evaluate, make sure that the expr to
+	     bytecode translator can handle it and that it's not too
+	     long.  */
+	  aexpr = gen_eval_for_expr (t->loc->address, exp);
+	  make_cleanup_free_agent_expr (aexpr);
+
+	  if (aexpr->len > MAX_AGENT_EXPR_LEN)
+	    error (_("expression too complicated, try simplifying"));
+
+	  do_cleanups (old_chain);
+	}
+      while (p && *p++ == ',');
+      return GENERIC;
+    }
   else if (cmd_cfunc_eq (c, while_stepping_pseudocommand))
     {
       char *steparg;		/* in case warning is necessary */
@@ -1464,6 +1498,46 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
 	    }
 	  while (action_exp && *action_exp++ == ',');
 	}			/* if */
+      else if (cmd_cfunc_eq (cmd, teval_pseudocommand))
+	{
+	  do
+	    {			/* repeat over a comma-separated list */
+	      QUIT;		/* allow user to bail out with ^C */
+	      while (isspace ((int) *action_exp))
+		action_exp++;
+
+		{
+		  unsigned long addr, len;
+		  struct cleanup *old_chain = NULL;
+		  struct cleanup *old_chain1 = NULL;
+		  struct agent_reqs areqs;
+
+		  exp = parse_exp_1 (&action_exp, 
+				     block_for_pc (t->loc->address), 1);
+		  old_chain = make_cleanup (free_current_contents, &exp);
+
+		  aexpr = gen_eval_for_expr (t->loc->address, exp);
+		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
+
+		  ax_reqs (aexpr, &areqs);
+		  if (areqs.flaw != agent_flaw_none)
+		    error (_("malformed expression"));
+
+		  if (areqs.min_height < 0)
+		    error (_("gdb: Internal error: expression has min height < 0"));
+		  if (areqs.max_height > 20)
+		    error (_("expression too complicated, try simplifying"));
+
+		  discard_cleanups (old_chain1);
+		  /* Even though we're not officially collecting, add
+		     to the collect list anyway.  */
+		  add_aexpr (collect, aexpr);
+
+		  do_cleanups (old_chain);
+		}		/* do */
+	    }
+	  while (action_exp && *action_exp++ == ',');
+	}			/* if */
       else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
 	{
 	  collect = &stepping_list;
@@ -2624,6 +2698,12 @@ Also accepts the following special arguments:\n\
     $locals -- all variables local to the block/function scope.\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
+  add_com ("teval", class_trace, teval_pseudocommand, _("\
+Specify one or more expressions to be evaluated at a tracepoint.\n\
+Accepts a comma-separated list of (one or more) expressions.\n\
+The result of each evaluation will be discarded.\n\
+Note: this command can only be used in a tracepoint \"actions\" list."));
+
   add_com ("actions", class_trace, trace_actions_command, _("\
 Specify the actions to be taken at a tracepoint.\n\
 Tracepoint actions may include collecting of specified data, \n\
-- 
GitLab